diff --git a/nightly/CONTRIBUTING/index.html b/nightly/CONTRIBUTING/index.html index 15a052c804b..3485dcd88c6 100644 --- a/nightly/CONTRIBUTING/index.html +++ b/nightly/CONTRIBUTING/index.html @@ -8727,11 +8727,11 @@

Referencing Janssen Pr

Above command contains references to the release number at two places. v1.1.4 in the URL and 1.1.4 as part of the file name. There are many such places throughout the documentation when release numbers need to be mentioned. Whenever we make a new release, these numbers need to change as they point to the latest release number. This becomes a manual task.

-

To avoid this manual, error-prone approach the Janssen Project uses a release marker, 0.0.0-nightly instead +

To avoid this manual, error-prone approach the Janssen Project uses a release marker, replace-janssen-version instead of writing actual release numbers in the head(latest) documentation branch. So, when there is a need to mention the release number, instead of writing the actual release number, use the release marker. Let's see how to document the above command (at the head version) so that it stays up-to-date release after release.

-
wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly.ubuntu20.04_amd64.deb -P /tmp
+
wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version.ubuntu20.04_amd64.deb -P /tmp
 

Warning

diff --git a/nightly/casa/administration/quick-start/index.html b/nightly/casa/administration/quick-start/index.html index 00c2772f363..dedbee8539a 100644 --- a/nightly/casa/administration/quick-start/index.html +++ b/nightly/casa/administration/quick-start/index.html @@ -8665,7 +8665,7 @@

Jans Casa Quick Start GuideInstallation#

-

Jans Casa can be used with Janssen Server or Gluu Flex Server. At installation time (applies to any of these two products), you will be prompted if you desire to include Casa. If you want to add Casa post-installation, you will simply have to re-run the installer and ensure to select Casa.

+

Jans Casa can be used with Janssen Server or Gluu Flex Server. At installation time (applies to any of these two products), you will be prompted if you desire to include Casa. If you want to add Casa post-installation, you will simply have to re-run the installer and ensure to select Casa.

Configuration#

Enable authentication methods#

The "out-of-the-box" login experience in Casa consists of the usual username and password prompt. To start leveraging a stronger authentication login to Casa with an administrative account (visit https://<your-server-name>/jans-casa) and activate the methods you want to offer Casa users.

diff --git a/nightly/casa/developer/add-authn-methods/index.html b/nightly/casa/developer/add-authn-methods/index.html index cd78a36e903..434798da0ed 100644 --- a/nightly/casa/developer/add-authn-methods/index.html +++ b/nightly/casa/developer/add-authn-methods/index.html @@ -8804,7 +8804,7 @@

About Casa authentication flowFlow requisites#

-

To code the flow corresponding to the authentication method to add, you can use the Agama project found here as a canvas. Ensure the following conditions are met so that it properly integrates in the main Casa flow:

+

To code the flow corresponding to the authentication method to add, you can use the Agama project found here as a canvas. Ensure the following conditions are met so that it properly integrates in the main Casa flow:

The flow will be passed an Agama map containing information of the person attempting the authentication. This input parameter will contain at least three keys: uid, inum, and name. uid and inum map directly to attributes stored in the user's profile and are never empty, name is a displayable name which may come from attribute givenName or displayName. All values are strings.

The flow should terminate with a true outcome if the user successfully passes the challenge, presents the expected credential, etc. In any other case, false must be returned and an optional error message can be included for the caller flow (io.jans.casa.authn.main) to show it in the screen. Any additional data attached in the Finish instruction will not be processed.

If for some reason your flow crashes, the corresponding exception will be printed to the logs, the caller will continue running, and the browser taken to the selector page where an error message will be displayed.

@@ -8883,7 +8883,7 @@

Key questions

Depending on the answers, you may like to start instead with plugin development first. This is not always the case though, however, getting your hands on the plugin might help unclutter the path.

Enrollment plugin#

-

Coding a Casa plugin is mainly a Java development task. You can use the "Sample credential" plugin as a template to start the work. Ensure you have:

+

Coding a Casa plugin is mainly a Java development task. You can use the "Sample credential" plugin as a template to start the work. Ensure you have:

  • A Jans Server installation that includes Jans Casa - prefer a VM environment over the CN edition for development purposes. Also, you'll need a way to connect to your server via SSH

    diff --git a/nightly/casa/developer/overview/index.html b/nightly/casa/developer/overview/index.html index 3c220ce4e0e..2c5b7ea1ce5 100644 --- a/nightly/casa/developer/overview/index.html +++ b/nightly/casa/developer/overview/index.html @@ -8758,11 +8758,11 @@

    Tools#
  • The underlying database engine used by your Jans Server installation, e.g. PostgreSQL, MySQL, etc.

Sample plugins#

-

The best way to start learning Casa plugin development is by playing with the sample plugins you can find here. Clone the repository (a shallow clone of main branch is fine), cd to one of the directories in the folder and run mvn package, then upload the resulting jar-with-dependencies through the administration console.

+

The best way to start learning Casa plugin development is by playing with the sample plugins you can find here. Clone the repository (a shallow clone of main branch is fine), cd to one of the directories in the folder and run mvn package, then upload the resulting jar-with-dependencies through the administration console.

Configuration management#

-

Most aspects of Casa that are configurable through the admin console UI can be programmatically operated using the configuration API. A formal description can be found here. Note all endpoints are protected by OAuth tokens which must have the https://jans.io/casa.config scope.

+

Most aspects of Casa that are configurable through the admin console UI can be programmatically operated using the configuration API. A formal description can be found here. Note all endpoints are protected by OAuth tokens which must have the https://jans.io/casa.config scope.

Credentials enrollment#

-

Casa has enrollment capabilities built-in but there are use cases where credential enrollment needs to happen elsewhere in your app ecosystem. A typical scenario is in a user registration application, where users are asked to enroll strong authentication credentials during account creation. To facilitate these tasks, Casa exposes APIs for enrolling the following types of authenticators:

+

Casa has enrollment capabilities built-in but there are use cases where credential enrollment needs to happen elsewhere in your app ecosystem. A typical scenario is in a user registration application, where users are asked to enroll strong authentication credentials during account creation. To facilitate these tasks, Casa exposes APIs for enrolling the following types of authenticators:

-
wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.el8.x86_64.rpm -P ~/
+
wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.el8.x86_64.rpm -P ~/
 
  • Verify integrity of the downloaded package using published sha256sum.

    Download sha256sum file for the package

    -
    wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.el8.x86_64.rpm.sha256sum -P ~/
    +
    wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.el8.x86_64.rpm.sha256sum -P ~/
     

    Check the hash if it is matching.

    -
    sha256sum -c jans-0.0.0-nightly-el8.x86_64.rpm.sha256sum
    +
    sha256sum -c jans-replace-janssen-version-el8.x86_64.rpm.sha256sum
     

    Output similar to below should confirm the integrity of the downloaded package.

    -
    jans-0.0.0-nightly-el8.x86_64.rpm: OK
    +
    jans-replace-janssen-version-el8.x86_64.rpm: OK
     
  • Install the package

-
sudo yum install ~/jans-0.0.0-nightly-el8.x86_64.rpm
+
sudo yum install ~/jans-replace-janssen-version-el8.x86_64.rpm
 

Run the setup script#

    diff --git a/nightly/janssen-server/install/vm-install/suse/index.html b/nightly/janssen-server/install/vm-install/suse/index.html index a1a3a0617ef..9aaeb86b1bd 100644 --- a/nightly/janssen-server/install/vm-install/suse/index.html +++ b/nightly/janssen-server/install/vm-install/suse/index.html @@ -8700,17 +8700,17 @@

    Install the PackageReleases

-
wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.suse15.x86_64.rpm
+
wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.suse15.x86_64.rpm
 
  • Verify integrity of the downloaded package using published sha256sum.

Download sha256sum file for the package

-
wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.suse15.x86_64.rpm.sha256sum
+
wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.suse15.x86_64.rpm.sha256sum
 

Check the hash if it is matching. You may need to change your working directory to where both the rpm and sha256sum file are located.

-
sha256sum -c jans-0.0.0-nightly.suse15.x86_64.rpm.sha256sum
+
sha256sum -c jans-replace-janssen-version.suse15.x86_64.rpm.sha256sum
 

Output similar to below should confirm the integrity of the downloaded package.

<package-name>: OK
@@ -8718,7 +8718,7 @@ 

Install the Package
sudo zypper install ~/jans-0.0.0-nightly.suse15.x86_64.rpm
+
sudo zypper install ~/jans-replace-janssen-version.suse15.x86_64.rpm
 

Run the setup script#

    diff --git a/nightly/janssen-server/install/vm-install/ubuntu/index.html b/nightly/janssen-server/install/vm-install/ubuntu/index.html index 32800c573dd..6f378c8f3fe 100644 --- a/nightly/janssen-server/install/vm-install/ubuntu/index.html +++ b/nightly/janssen-server/install/vm-install/ubuntu/index.html @@ -8720,54 +8720,54 @@

    Ubuntu 22.04Download the release package from the Github Janssen Project Releases

-
wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu22.04_amd64.deb -P /tmp
+
wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu22.04_amd64.deb -P /tmp
 
  • Verify integrity of the downloaded package by verifying published sha256sum.

    Download sha256sum file for the package

    -
    wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu22.04_amd64.deb.sha256sum -P /tmp
    +
    wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu22.04_amd64.deb.sha256sum -P /tmp
     

    Check the hash if it is matching.

    cd /tmp
    -sha256sum -c jans_0.0.0-nightly.ubuntu22.04_amd64.deb.sha256sum
    +sha256sum -c jans_replace-janssen-version.ubuntu22.04_amd64.deb.sha256sum
     

    Output similar to below should confirm the integrity of the downloaded package.

    -
    jans_0.0.0-nightly.ubuntu22.04_amd64.deb.sha256sum: OK
    +
    jans_replace-janssen-version.ubuntu22.04_amd64.deb.sha256sum: OK
     
  • Install the package

-
sudo apt install  ./jans_0.0.0-nightly.ubuntu22.04_amd64.deb
+
sudo apt install  ./jans_replace-janssen-version.ubuntu22.04_amd64.deb
 

Ubuntu 20.04#

  • Download the release package from the Github Janssen Project Releases
-
wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu20.04_amd64.deb -P /tmp
+
wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu20.04_amd64.deb -P /tmp
 
  • Verify integrity of the downloaded package by verifying published sha256sum.

    Download sha256sum file for the package

    -
    wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu20.04_amd64.deb.sha256sum -P /tmp
    +
    wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu20.04_amd64.deb.sha256sum -P /tmp
     

    Check the hash if it is matching.

    cd /tmp
    -sha256sum -c jans_0.0.0-nightly.ubuntu20.04_amd64.deb.sha256sum
    +sha256sum -c jans_replace-janssen-version.ubuntu20.04_amd64.deb.sha256sum
     

    Output similar to below should confirm the integrity of the downloaded package.

    -
    jans_0.0.0-nightly.ubuntu20.04_amd64.deb.sha256sum: OK
    +
    jans_replace-janssen-version.ubuntu20.04_amd64.deb.sha256sum: OK
     
  • Install the package

-
sudo apt install  ./jans_0.0.0-nightly.ubuntu20.04_amd64.deb
+
sudo apt install  ./jans_replace-janssen-version.ubuntu20.04_amd64.deb
 

Run the setup script#

-

Keep note of the chart version. For example: 0.0.0-nightly

+

Keep note of the chart version. For example: replace-janssen-version

Manual Restore#

  1. @@ -8677,7 +8677,7 @@

    Manual Restore
    helm install <release-name> janssen/janssen -f values.yaml --version=<0.0.0-nightly> -n <namespace>
    +
    helm install <release-name> janssen/janssen -f values.yaml --version=<replace-janssen-version> -n <namespace>
     

    Automatic Backup and Restore#

    There are several tools that helps in automatic backups and restore, like Kasten K10.

    diff --git a/nightly/janssen-server/kubernetes-ops/cert-management/index.html b/nightly/janssen-server/kubernetes-ops/cert-management/index.html index c955dddb353..04267c4b145 100644 --- a/nightly/janssen-server/kubernetes-ops/cert-management/index.html +++ b/nightly/janssen-server/kubernetes-ops/cert-management/index.html @@ -8686,7 +8686,7 @@

    Rotate restartPolicy: Never containers: - name: web-key-rotation - image: ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly-1 + image: ghcr.io/janssenproject/jans/certmanager:replace-janssen-version-1 envFrom: - configMapRef: name: janssen-config-cm # This may be differnet in Helm @@ -8738,7 +8738,7 @@

    Load from existing source path: web_https.key containers: - name: load-web-key-rotation - image: ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly-1 + image: ghcr.io/janssenproject/jans/certmanager:replace-janssen-version-1 envFrom: - configMapRef: name: janssen-config-cm #This may be differnet in Helm @@ -8798,7 +8798,7 @@

    Auth-server spec: containers: - name: auth-key-rotation - image: ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly-1 + image: ghcr.io/janssenproject/jans/certmanager:replace-janssen-version-1 resources: requests: memory: "300Mi" diff --git a/nightly/janssen-server/kubernetes-ops/tui-k8s/index.html b/nightly/janssen-server/kubernetes-ops/tui-k8s/index.html index 8e090a5075c..5d52aed843b 100644 --- a/nightly/janssen-server/kubernetes-ops/tui-k8s/index.html +++ b/nightly/janssen-server/kubernetes-ops/tui-k8s/index.html @@ -8582,7 +8582,7 @@

    Overviewrelease assets depending on your OS. For example:

    -

    wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-cli-tui-linux-ubuntu-X86-64.pyz

    +

    wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-cli-tui-linux-ubuntu-X86-64.pyz

    Now we have jans-cli-tui-linux-ubuntu-X86-64.pyz downloaded.

  2. diff --git a/nightly/janssen-server/kubernetes-ops/upgrade/index.html b/nightly/janssen-server/kubernetes-ops/upgrade/index.html index 2b2850fe267..71fe16edfab 100644 --- a/nightly/janssen-server/kubernetes-ops/upgrade/index.html +++ b/nightly/janssen-server/kubernetes-ops/upgrade/index.html @@ -8537,7 +8537,7 @@

    Upgrade

  3. Apply your upgrade:

    -

    helm upgrade <janssen-release-name> janssen/janssen -n <namespace> -f override.yaml --version=0.0.0-nightly

    +

    helm upgrade <janssen-release-name> janssen/janssen -n <namespace> -f override.yaml --version=replace-janssen-version

diff --git a/nightly/janssen-server/planning/benchmarking/index.html b/nightly/janssen-server/planning/benchmarking/index.html index ce45685628a..5993d65f15e 100644 --- a/nightly/janssen-server/planning/benchmarking/index.html +++ b/nightly/janssen-server/planning/benchmarking/index.html @@ -8646,10 +8646,10 @@

Benchmarking

Load test#

In cloud-native architecture, the load testing is executed via k8s pods.

Authorization Code Flow jmeter load test#

-

For load testing with Authorization Code Flow jmeter test, the following script is used.

+

For load testing with Authorization Code Flow jmeter test, the following script is used.

See Authorization code flow recipe for details.

Resource Owner Password Grant (ROPC) Flow jmeter load test#

-

For load testing with Resource Owner Password Grant (ROPC) Flow jmeter test, the following script is used.

+

For load testing with Resource Owner Password Grant (ROPC) Flow jmeter test, the following script is used.

See ROPC flow recipe for details.


diff --git a/nightly/janssen-server/planning/self-service-password-2fa/index.html b/nightly/janssen-server/planning/self-service-password-2fa/index.html index 8ecbd347ef3..014875b9f98 100644 --- a/nightly/janssen-server/planning/self-service-password-2fa/index.html +++ b/nightly/janssen-server/planning/self-service-password-2fa/index.html @@ -8536,7 +8536,7 @@

Self-Service Password/2FA Portal

credentials on one page.

You can build a page like Google on your own website. You need to be able to list, add, and remove 2FA credentials for a given user's account. But another -good option is the Jans Casa web application.

+good option is the Jans Casa web application.


diff --git a/nightly/janssen-server/recipes/benchmark/index.html b/nightly/janssen-server/recipes/benchmark/index.html index b068b0346dd..20bde514e15 100644 --- a/nightly/janssen-server/recipes/benchmark/index.html +++ b/nightly/janssen-server/recipes/benchmark/index.html @@ -9012,13 +9012,13 @@

Kubernetes Cluster Load Test Res

Make sure helm is installed.

  • -

    Prepare your override.yaml. Copy the below into a file named override.yaml. At the time of writing this we are using image tags 0.0.0-nightly_dev which are the bleeding edge images for release 0.0.0-nightly. Stable images such as 0.0.0-nightly-1 should be used.

    +

    Prepare your override.yaml. Copy the below into a file named override.yaml. At the time of writing this we are using image tags replace-janssen-version_dev which are the bleeding edge images for release replace-janssen-version. Stable images such as replace-janssen-version-1 should be used.

  • config:
        image:
          repository: ghcr.io/janssenproject/jans/configurator
    -     tag: 0.0.0-nightly_dev 
    +     tag: replace-janssen-version_dev 
        countryCode: US
        email: support@gluu.org
        orgName: Gluu
    @@ -9062,17 +9062,17 @@ 

    Kubernetes Cluster Load Test Res image: pullPolicy: IfNotPresent repository: ghcr.io/janssenproject/jans/auth-server - tag: 0.0.0-nightly_dev + tag: replace-janssen-version_dev config-api: image: pullPolicy: IfNotPresent repository: ghcr.io/janssenproject/jans/config-api - tag: 0.0.0-nightly_dev + tag: replace-janssen-version_dev persistence: image: pullPolicy: IfNotPresent repository: ghcr.io/janssenproject/jans/persistence-loader - tag: 0.0.0-nightly_dev + tag: replace-janssen-version_dev nginx-ingress: ingress: path: / @@ -9102,7 +9102,7 @@

    Loading users

  • -

    Copy the following yaml into the folder under the name load_users.yaml.

    +

    Copy the following yaml into the folder under the name load_users.yaml.

  • Open the file and modify the required parameters. Note that the following environments can be used as configmaps data to configure the pod.

    @@ -9260,7 +9260,7 @@
    Setup Client} EOF
  • -3. Copy the following yaml into the folder.

    +3. Copy the following yaml into the folder.

  • Download or build config-cli-tui and run:

    @@ -9367,7 +9367,7 @@
    Setup Client
  • -

    Copy the following yaml into the folder.

    +

    Copy the following yaml into the folder.

  • Download or build config-cli-tui and run:

    @@ -9474,7 +9474,7 @@
    Setup Client
  • -

    Copy the following yaml into the folder.

    +

    Copy the following yaml into the folder.

  • Download or build config-cli-tui and run:

    diff --git a/nightly/janssen-server/reference/openapi/index.html b/nightly/janssen-server/reference/openapi/index.html index bac0e7436c9..fdc11993b02 100644 --- a/nightly/janssen-server/reference/openapi/index.html +++ b/nightly/janssen-server/reference/openapi/index.html @@ -8602,11 +8602,11 @@

    REST APISwagger +Swagger Jans Config API -Swagger +Swagger Jans Core @@ -8614,11 +8614,11 @@

    REST APISwagger +Swagger Jans SCIM API -Swagger +Swagger Jans KC SAML API diff --git a/nightly/janssen-server/vm-ops/upgrade/index.html b/nightly/janssen-server/vm-ops/upgrade/index.html index 46c43fa982a..008503d780b 100644 --- a/nightly/janssen-server/vm-ops/upgrade/index.html +++ b/nightly/janssen-server/vm-ops/upgrade/index.html @@ -8527,26 +8527,26 @@

    Upgrade

    Though this is made easy using Terraform. We recommend using Kubernetes installations over VM, to avail smooth upgrades and better HA support.

  • -

    Let's assume we are upgrading Jans VM installation from current version to nightly

    +

    Let's assume we are upgrading Jans VM installation from current version to vreplace-janssen-version

    1. Keep the old VM installation running.

    2. -

      Install on a separate VM the target new Jans installation, i.e. nightly.

      +

      Install on a separate VM the target new Jans installation, i.e. vreplace-janssen-version.

      You can install with a test client. For example:

      sudo python3 /opt/jans/jans-setup/setup.py -test-client-id 6382c9da-f25d-435f-ac63-6acde36f4859 -test-client-pw secret1172023

      This client-id and client-pw will then be used to import Terraform configurations

    3. -

      Use our Terraform docs on the new installation, i.e. nightly to:

      +

      Use our Terraform docs on the new installation, i.e. vreplace-janssen-version to:

      • import all the global configurations from the new installation using terraform import
      • define all the custom IDP configurations and apply them using terraform apply
    4. -

      At this point there should be two versions up, old version and nightly.

      +

      At this point there should be two versions up, old version and vreplace-janssen-version.

    5. Traffic should be switched gradually from the old setup to the new setup. diff --git a/nightly/script-catalog/client_registration/OpenBanking/Registration.py b/nightly/script-catalog/client_registration/OpenBanking/Registration.py index bc64e62219d..4facf6d03aa 100644 --- a/nightly/script-catalog/client_registration/OpenBanking/Registration.py +++ b/nightly/script-catalog/client_registration/OpenBanking/Registration.py @@ -141,7 +141,7 @@ def destroy(self, configurationAttributes): print "Client registration. Destroyed successfully" return True - # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/nightly/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 + # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/vreplace-janssen-version/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 def createClient(self, context): print "Client registration. CreateClient method" client = context.getClient() @@ -207,7 +207,7 @@ def validateDCR(self, registerRequest, client, configurationAttributes): - # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/nightly/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 + # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/vreplace-janssen-version/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 def updateClient(self, context): print "Client registration. UpdateClient method" return True @@ -219,7 +219,7 @@ def getSoftwareStatementHmacSecret(self, context): return "" # cert - java.security.cert.X509Certificate - # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/nightly/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 + # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/vreplace-janssen-version/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 def isCertValidForClient(self, cert, context): return False diff --git a/nightly/script-catalog/client_registration/OpenBanking/client-registration/index.html b/nightly/script-catalog/client_registration/OpenBanking/client-registration/index.html index e3939d814a0..e7a7355bf3b 100644 --- a/nightly/script-catalog/client_registration/OpenBanking/client-registration/index.html +++ b/nightly/script-catalog/client_registration/OpenBanking/client-registration/index.html @@ -8548,7 +8548,7 @@

      OverviewConfiguration Prerequisites#

      • A Janssen Authorization Server installation
      • -
      • Client Registration script - included in the default Janssen OpenBanking distribution
      • +
      • Client Registration script - included in the default Janssen OpenBanking distribution
      • Setting configuration parameters
      • Setting third party library (Jose4j) in classpath
      diff --git a/nightly/script-catalog/client_registration/sample-script/SampleScript.py b/nightly/script-catalog/client_registration/sample-script/SampleScript.py index 69ecc8b7304..86f979005cb 100644 --- a/nightly/script-catalog/client_registration/sample-script/SampleScript.py +++ b/nightly/script-catalog/client_registration/sample-script/SampleScript.py @@ -30,7 +30,7 @@ def destroy(self, configurationAttributes): return True # Update client entry before persistent it - # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/nightly/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 + # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/vreplace-janssen-version/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 def createClient(self, context): print "Client registration. CreateClient method" registerRequest = context.getRegisterRequest() @@ -62,7 +62,7 @@ def createClient(self, context): return True # Update client entry before persistent it - # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/nightly/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 + # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/vreplace-janssen-version/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 def updateClient(self, context): print "Client registration. UpdateClient method" return True @@ -106,7 +106,7 @@ def getSoftwareStatementJwks(self, context): return "" # cert - java.security.cert.X509Certificate - # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/nightly/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 + # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/vreplace-janssen-version/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 def isCertValidForClient(self, cert, context): return False diff --git a/nightly/script-catalog/consent_gathering/sample-script/ConsentGatheringSample.py b/nightly/script-catalog/consent_gathering/sample-script/ConsentGatheringSample.py index 40576be19b1..f0a48a0a49d 100644 --- a/nightly/script-catalog/consent_gathering/sample-script/ConsentGatheringSample.py +++ b/nightly/script-catalog/consent_gathering/sample-script/ConsentGatheringSample.py @@ -30,7 +30,7 @@ def destroy(self, configurationAttributes): return True def getApiVersion(self): - return 1 + return 11 # Main consent-gather method. Must return True (if gathering performed successfully) or False (if fail). # All user entered values can be access via Map context.getPageAttributes() diff --git a/nightly/script-catalog/idp/idp-extension/index.html b/nightly/script-catalog/idp/idp-extension/index.html index 8141995f244..69cc7ac9e79 100644 --- a/nightly/script-catalog/idp/idp-extension/index.html +++ b/nightly/script-catalog/idp/idp-extension/index.html @@ -8734,7 +8734,7 @@

      Script Type: Pythonreturn False # Update attributes before releasing them - # context is io.jans.idp.consent.processor.PostProcessAttributesContext (https://github.com/JanssenProject/shib-oxauth-authn3/blob/nightly/src/main/java/io.jans.idp/consent/processor/PostProcessAttributesContext.java) + # context is io.jans.idp.consent.processor.PostProcessAttributesContext (https://github.com/JanssenProject/shib-oxauth-authn3/blob/vreplace-janssen-version/src/main/java/io.jans.idp/consent/processor/PostProcessAttributesContext.java) # configurationAttributes is java.util.Map<String, SimpleCustomProperty> def updateAttributes(self, context, configurationAttributes): print "Idp extension. Method: updateAttributes" diff --git a/nightly/script-catalog/idp/sample-script/SampleScript.py b/nightly/script-catalog/idp/sample-script/SampleScript.py index cdec27db7d2..80f8e5c304e 100644 --- a/nightly/script-catalog/idp/sample-script/SampleScript.py +++ b/nightly/script-catalog/idp/sample-script/SampleScript.py @@ -94,7 +94,7 @@ def translateAttributes(self, context, configurationAttributes): return False # Update attributes before releasing them - # context is io.jans.idp.consent.processor.PostProcessAttributesContext (https://github.com/JanssenProject/shib-oxauth-authn3/blob/nightly/src/main/java/io.jans.idp/consent/processor/PostProcessAttributesContext.java) + # context is io.jans.idp.consent.processor.PostProcessAttributesContext (https://github.com/JanssenProject/shib-oxauth-authn3/blob/vreplace-janssen-version/src/main/java/io.jans.idp/consent/processor/PostProcessAttributesContext.java) # configurationAttributes is java.util.Map def updateAttributes(self, context, configurationAttributes): print "Idp extension. Method: updateAttributes" diff --git a/nightly/script-catalog/persistence_extension/persistence/index.html b/nightly/script-catalog/persistence_extension/persistence/index.html index 9a800f11678..878db8c1dde 100644 --- a/nightly/script-catalog/persistence_extension/persistence/index.html +++ b/nightly/script-catalog/persistence_extension/persistence/index.html @@ -8639,7 +8639,7 @@

      Persistence Script#

      -

      By overriding the interface methods in PersistenceType inside a custom script you can

      +

      By overriding the interface methods in PersistenceType inside a custom script you can

      1. Load initialization data from DB or initialize services after the creation of Entry Manager.
      2. Release resources, terminate services etc. after the destruction of Entry Manager.
      3. @@ -8653,7 +8653,7 @@

        Persistence ScriptUsage#

        -

        The Jans-Auth server contains a PeristenceType script.

        +

        The Jans-Auth server contains a PeristenceType script.

        Hashed Passwords#

        Hashed passwords can be created using any method from this enum, instead of the native/default SSHA256. The ORM module of the Janssen server does the following:

        diff --git a/nightly/script-catalog/person_authentication/apple-external-authenticator/index.html b/nightly/script-catalog/person_authentication/apple-external-authenticator/index.html index fc5a54f2007..11dd332e1ba 100644 --- a/nightly/script-catalog/person_authentication/apple-external-authenticator/index.html +++ b/nightly/script-catalog/person_authentication/apple-external-authenticator/index.html @@ -8610,7 +8610,7 @@

        Propertieslink

        +

        To update this setting in Jans persistence, follow this link

        Enable Sign-in with Apple Authentication script#

        By default, users will get the default authentication mechanism as specified above. However, using the OpenID Connect acr_values parameter, web and mobile clients can request any enabled authentication mechanism.

        Obtain the json contents of apple custom script by using a jans-cli command like get-config-scripts-by-type, get-config-scripts-by-inum etc. @@ -8620,7 +8620,7 @@

        Enable Sign-in with App Now Sign-in with Apple is an available authentication mechanism for your Janssen Server. This means that, using OpenID Connect acr_values, applications can now request Apple authentication for users.

        !!! Note To make sure apple has been enabled successfully, you can check your Janssen's Auth Server OpenID Connect configuration by navigating to the following URL: https:///.well-known/openid-configuration. Find "acr_values_supported": and you should see "apple".

        Make Sign-in with Apple Script as default authentication script:#

        -

        Use this link as a reference.

        +

        Use this link as a reference.

        Steps: 1. Create a file say apple-auth-default.json with the following contents

        {
        diff --git a/nightly/script-catalog/person_authentication/duo-external-authenticator/index.html b/nightly/script-catalog/person_authentication/duo-external-authenticator/index.html
        index 4d8a7e3e833..e8da3a15253 100644
        --- a/nightly/script-catalog/person_authentication/duo-external-authenticator/index.html
        +++ b/nightly/script-catalog/person_authentication/duo-external-authenticator/index.html
        @@ -8571,7 +8571,7 @@
           

        Index

        Integrating DUO's Universal Prompt as an authentication method in Janssen server#

        -

        Duo Security is a SaaS authentication provider. This document will explain how to use Janssen's Duo interception script to configure the Janssen Server for a two-step authentication process with username and password as the first step, and Duo as the second step. The script invokes the Universal Prompt which is a redesign of Duo’s traditional authentication prompt.

        +

        Duo Security is a SaaS authentication provider. This document will explain how to use Janssen's Duo interception script to configure the Janssen Server for a two-step authentication process with username and password as the first step, and Duo as the second step. The script invokes the Universal Prompt which is a redesign of Duo’s traditional authentication prompt.

        Authentication flow#

        sequenceDiagram
         title Integrating DUO's Universal Prompt as an authentication method in Janssen server
        @@ -8595,7 +8595,7 @@ 

        Authentication flowAdministrator prerequisites#

        User prerequisites#

        @@ -8710,7 +8710,7 @@

        2. Add custom script and you should see "duo".

        Make Duo the Default Authentication Mechanism#

        -

        For CURL commands, use this link as a reference.

        +

        For CURL commands, use this link as a reference.

        Steps: 1. Create a file say duo-auth-default.json with the following contents

        {
        diff --git a/nightly/script-catalog/person_authentication/fido2-external-authenticator/index.html b/nightly/script-catalog/person_authentication/fido2-external-authenticator/index.html
        index 8ddc8b55fd2..9bfe4f760d7 100644
        --- a/nightly/script-catalog/person_authentication/fido2-external-authenticator/index.html
        +++ b/nightly/script-catalog/person_authentication/fido2-external-authenticator/index.html
        @@ -8608,12 +8608,12 @@ 

        OverviewFIDO 2.0 (FIDO2) , an open authentication standard that enables people to leverage common devices to authenticate to online services in both mobile and desktop environments. The Janssen server includes a FIDO2 server implementation. This enables authentications by using platform authenticators embedded into a person's device or physical USB, NFC or Bluetooth security keys that are inserted into a USB slot of a computer.

        FIDO2 is comprised of the W3C’s Web Authentication specification (WebAuthn) and FIDO’s corresponding Client-to-Authenticator Protocol (CTAP). WebAuthn defines a standard web API that can be built into browsers and related web platform infrastructure to enable online services to use FIDO Authentication. CTAP enables external devices such as mobile handsets or FIDO Security Keys to work with WebAuthn and serve as authenticators to desktop applications and web services.

        This document explains how to use the Janssen Auth Server's built-in -FIDO2 interception script +FIDO2 interception script to implement a two-step, two-factor authentication (2FA) with username / password as the first step, and any FIDO2 device as the second step.

        Prerequisites#

        FIDO2 devices#

        @@ -8662,7 +8662,7 @@

        Enable FIDO2 script and you should see "fido2".

        Enable FIDO2 Script as default authentication script:#

        -

        Use this link as a reference. +

        Use this link as a reference. Follow the steps below to enable FIDO2 authentication: 1. Create a file say fido2-auth-default.json with the following contents

        {
        @@ -8683,8 +8683,8 @@ 

        Test the featureFIDO2 login page#

        Below is an illustration of the Janssen Server's default FIDO2 login page:

        -

        fido2

        -

        The design is being rendered from the FIDO2 xhtml page. To customize the look and feel of this page, follow the customization guide.

        +

        fido2

        +

        The design is being rendered from the FIDO2 xhtml page. To customize the look and feel of this page, follow the customization guide.

        Using FIDO2 tokens#

        Credential enrollment#

        FIDO2 device enrollment happens during the first authentication attempt.

        @@ -8692,7 +8692,7 @@

        Subsequent authentications#

        A user's FIDO2 devices can be removed by a Janssen administrator in LDAP under the user entry as shown in the below screenshot.

        -

        fido2 +

        fido2 Diagram source in mermaid.live

        graph TD
         
        diff --git a/nightly/script-catalog/person_authentication/google-external-authenticator/index.html b/nightly/script-catalog/person_authentication/google-external-authenticator/index.html
        index de2bb3df38e..139b0e100e0 100644
        --- a/nightly/script-catalog/person_authentication/google-external-authenticator/index.html
        +++ b/nightly/script-catalog/person_authentication/google-external-authenticator/index.html
        @@ -8588,8 +8588,8 @@ 

        Social Login with GoogleAn out-of-the-box feature, the Google Authentication script is a PersonAuthenticationType script which enables a user to sign-in using Google credentials. Google's OAuth 2.0 APIs are used for this. After users authenticate using their Google credentials, their Google credentials are provisioned into the Jans-auth server.

        Prerequisites#

        @@ -8645,7 +8645,7 @@

        Propertieslink

        +

        To update this setting in Jans persistence, follow this link

        Enable Sign-in with Google Authentication script#

        By default, users will get the default authentication mechanism as specified above. However, using the OpenID Connect acr_values parameter, web and mobile clients can request any enabled authentication mechanism.

        Obtain the json contents of google custom script by using a jans-cli command like get-config-scripts-by-type, get-config-scripts-by-inum etc. @@ -8655,7 +8655,7 @@

        Enable Sign-in with Go Now Google is an available authentication mechanism for your Janssen Server. This means that, using OpenID Connect acr_values, applications can now request Google authentication for users.

        !!! Note To make sure google has been enabled successfully, you can check your Janssen's Auth Server OpenID Connect configuration by navigating to the following URL: https:///.well-known/openid-configuration. Find "acr_values_supported": and you should see "google".

        Make Sign-in with Google Script as default authentication script:#

        -

        Use this link as a reference.

        +

        Use this link as a reference.

        Steps: 1. Create a file say google-auth-default.json with the following contents

        {
        diff --git a/nightly/script-catalog/person_authentication/other/obconnect/README.me b/nightly/script-catalog/person_authentication/other/obconnect/README.me
        index 4ee65887df3..f83fecb1582 100644
        --- a/nightly/script-catalog/person_authentication/other/obconnect/README.me
        +++ b/nightly/script-catalog/person_authentication/other/obconnect/README.me
        @@ -74,4 +74,4 @@ The mandatory properties in the obconnect authentication script are as follows
         
         Now applications can request obconnect's authentication and consent flow. To make obconnect your default authentication mechanism, follow these instructions in this document set the default authentication mechanism to "obconnect" 
         
        -https://github.com/JanssenProject/jans-cli-tui/blob/nightly/README.md
        \ No newline at end of file
        +https://github.com/JanssenProject/jans-cli-tui/blob/vreplace-janssen-version/README.md
        \ No newline at end of file
        diff --git a/nightly/script-catalog/person_authentication/other/obconnect/documentation/README.txt b/nightly/script-catalog/person_authentication/other/obconnect/documentation/README.txt
        index 4ee65887df3..f83fecb1582 100644
        --- a/nightly/script-catalog/person_authentication/other/obconnect/documentation/README.txt
        +++ b/nightly/script-catalog/person_authentication/other/obconnect/documentation/README.txt
        @@ -74,4 +74,4 @@ The mandatory properties in the obconnect authentication script are as follows
         
         Now applications can request obconnect's authentication and consent flow. To make obconnect your default authentication mechanism, follow these instructions in this document set the default authentication mechanism to "obconnect" 
         
        -https://github.com/JanssenProject/jans-cli-tui/blob/nightly/README.md
        \ No newline at end of file
        +https://github.com/JanssenProject/jans-cli-tui/blob/vreplace-janssen-version/README.md
        \ No newline at end of file
        diff --git a/nightly/script-catalog/person_authentication/other/uaf/Properties description/index.html b/nightly/script-catalog/person_authentication/other/uaf/Properties description/index.html
        index 8efc490e387..fb8650f62a1 100644
        --- a/nightly/script-catalog/person_authentication/other/uaf/Properties description/index.html	
        +++ b/nightly/script-catalog/person_authentication/other/uaf/Properties description/index.html	
        @@ -8481,7 +8481,7 @@
         
           

        Properties description

        -

        Script contents here

        +

        Script contents here

        This is a person authentication script for jans-auth-server that enables UAF for user authentication.

        The module has a few properties:

        1) uaf_server_uri - It's mandatory property. It's URL to UAF server. diff --git a/nightly/script-catalog/person_authentication/other/uaf/index.html b/nightly/script-catalog/person_authentication/other/uaf/index.html index 6241bdaf6b8..3e38f82e575 100644 --- a/nightly/script-catalog/person_authentication/other/uaf/index.html +++ b/nightly/script-catalog/person_authentication/other/uaf/index.html @@ -8481,7 +8481,7 @@

        Index

        -

        Script contents here

        +

        Script contents here

        This is a person authentication script for jans-auth-server that enables UAF for user authentication.

        The module has a few properties:

        1) uaf_server_uri - It's mandatory property. It's URL to UAF server. diff --git a/nightly/script-catalog/person_authentication/super-gluu-external-authenticator/index.html b/nightly/script-catalog/person_authentication/super-gluu-external-authenticator/index.html index 5762a03eebb..3e63e4fc0fa 100644 --- a/nightly/script-catalog/person_authentication/super-gluu-external-authenticator/index.html +++ b/nightly/script-catalog/person_authentication/super-gluu-external-authenticator/index.html @@ -8942,7 +8942,7 @@

        Enable Sign-in wit

      !!! Note To make sure super_gluu has been enabled successfully, you can check your Janssen's Auth Server OpenID Connect configuration by navigating to the following URL: https:///.well-known/openid-configuration. Find "acr_values_supported": and you should see "super_gluu".

      Make Sign-in with Super-Gluu Script as default authentication script:#

      -

      Use this link as a reference.

      +

      Use this link as a reference.

      Steps: 1. Create a file say sg-auth-default.json with the following contents

      Customizations to Super Gluu Login Pages#

      -

      The Gluu Server includes a default public-facing pages for Super Gluu for enrollment and authentication.

      -

      To customize the look and feel of the pages, follow the customization guide.

      +

      The Gluu Server includes a default public-facing pages for Super Gluu for enrollment and authentication.

      +

      To customize the look and feel of the pages, follow the customization guide.

      Self-service#

      To offer end-users a portal where they can manage their own account security preferences, including two-factor authentication credentials like Super Gluu, check out our new app, Gluu Casa.

      Manual Device Management#

      diff --git a/nightly/script-catalog/person_authentication/twilio-2fa/index.html b/nightly/script-catalog/person_authentication/twilio-2fa/index.html index ce735587bf1..94aa2667f33 100644 --- a/nightly/script-catalog/person_authentication/twilio-2fa/index.html +++ b/nightly/script-catalog/person_authentication/twilio-2fa/index.html @@ -8680,7 +8680,7 @@

      Enable twilio_sms script

      e.g : /opt/jans/jans-cli/config-cli.py --operation-id get-config-scripts-by-type --url-suffix type:PERSON_AUTHENTICATION , /opt/jans/jans-cli/config-cli.py --operation-id get-config-scripts-by-inum --url-suffix inum:6122281b-b55d-4dd0-8115-b098eeeee2b7

        -
      1. Update the custom script and change the enabled attribute to true
      2. +
      3. Update the custom script and change the enabled attribute to true

      Now twilio_sms is an available authentication mechanism for your Janssen Server. This means that, using OpenID Connect acr_values, applications can now request twilio_sms authentication for users.

      @@ -8690,7 +8690,7 @@

      Enable twilio_sms script"acr_values_supported": and you should see twilio_sms .

      Enable twilio_sms Script as default authentication script:#

      -

      Use this link as a reference. +

      Use this link as a reference. Follow the steps below to enable twilio_sms authentication: 1. Create a file say twilio_sms -auth-default.jsonwith the following contents

      {
      diff --git a/nightly/script-catalog/resource_owner_password_credentials/ropc/index.html b/nightly/script-catalog/resource_owner_password_credentials/ropc/index.html
      index c0810acf5bc..74a221ef20b 100644
      --- a/nightly/script-catalog/resource_owner_password_credentials/ropc/index.html
      +++ b/nightly/script-catalog/resource_owner_password_credentials/ropc/index.html
      @@ -8710,7 +8710,7 @@ 

      OverviewRFC 6749).

      The script is invoked after normal authentication and can either leave current result or change it - authenticate if not authenticated - it should return True and optionally set user (via context.setUser(user)).

      Interface#

      -

      The ROPC script implements the ResourceOwnerPasswordCredentialsType interface. This extends methods from the base script type in addition to adding new method:

      +

      The ROPC script implements the ResourceOwnerPasswordCredentialsType interface. This extends methods from the base script type in addition to adding new method:

      Inherited Methods#

      @@ -8760,7 +8760,7 @@

      ObjectscustomScript -

      + @@ -8768,11 +8768,11 @@

      ObjectsSimpleCustomProperty -

      + - +
      The custom script object. ReferenceThe custom script object. Reference
      configurationAttributesMap of configuration properties. ReferenceMap of configuration properties. Reference
      contextReferenceReference
      diff --git a/nightly/search/search_index.json b/nightly/search/search_index.json index 892782bb1bf..bc8c783600e 100644 --- a/nightly/search/search_index.json +++ b/nightly/search/search_index.json @@ -1 +1 @@ -{"config": {"indexing": "full", "lang": ["en"], "min_search_length": 3, "prebuild_index": false, "separator": "[\\s\\-]+"}, "docs": [{"location": "", "text": "Janssen Project Documentation # Introduction # Janssen is a distribution of open source identity components which organizations can use to build a scalable federated authentication and authorization service. This documentation is always work in progress. Please help to make it better by submitting a PR if you can think of any way to improve it! Administration Guide # Read the Administration guide to learn how to deploy, operate and maintain the Janssen components. Planning your solution using the Deployment Guide . An easy way to get started is to try Janssen on an VM, see Installation or check the other docs for Kubernetes based installation. Contribution Guide # There are many ways the community can contribute to the Janssen Project. Of course, you can contribute code. But we also need people to write documentation and guides, to help us with testing, to answer questions on the forums and chat, to review PRs, to help us with devops and CI/CD, to provide feedback on usability, and to promote the project through outreach. Also, by sharing metrics with us, we can gain valuable insights into how the software performs in the wild. Resources to get started are available here . Governance Guide # The Janssen Project is chartered under the Linux Foundation. Information about the project's governance can be found here . Script Catalog # Interception scripts (or custom scripts) allow you to define custom business logic for various features in Janssen without forking the Jans Server core project. Interceptions scripts are available for many components, including Auth Server, SCIM, FIDO, and Link. The definitive location for scripts and their documentation is the Script Catalog . Agama # Agama is a domain specific language (\"DSL\") designed for writing web flows, and a project archive format (\".gama\") which stores all the code and web assets required for deployment of an Agama project by an identity provider. Although invented by Janssen, we envision many IDP's using Agama as a cross-vendor standard for identity orchestration. Support # If you have any questions about usage, post on Jans Discussions or try community chat on Gitter . If you find a bug in a Janssen project, or you would like to suggest a new feature, you should also post on GitHub Discussions first. The Jans team will try to replicate the bug, or weigh the feature request versus current priorities. License # Most Janssen Project components are licensed under the Apache License 2.0 . Janssen has some third party components, so it's always best to check the license for each component. We won't include any component in the distribution that has a non- OSI approved license, or a commercial trademark. Looking for older documentation versions? # The Janssen Project posts the last five versions of the documentation. If you are looking for older versions, you can find them unprocessed in the docs folder. Select the version of choice from the tag dropdown in GitHub. If you want to process them you may do so following the steps here .", "title": "Janssen Project Documentation"}, {"location": "#janssen-project-documentation", "text": "", "title": "Janssen Project Documentation"}, {"location": "#introduction", "text": "Janssen is a distribution of open source identity components which organizations can use to build a scalable federated authentication and authorization service. This documentation is always work in progress. Please help to make it better by submitting a PR if you can think of any way to improve it!", "title": "Introduction"}, {"location": "#administration-guide", "text": "Read the Administration guide to learn how to deploy, operate and maintain the Janssen components. Planning your solution using the Deployment Guide . An easy way to get started is to try Janssen on an VM, see Installation or check the other docs for Kubernetes based installation.", "title": "Administration Guide"}, {"location": "#contribution-guide", "text": "There are many ways the community can contribute to the Janssen Project. Of course, you can contribute code. But we also need people to write documentation and guides, to help us with testing, to answer questions on the forums and chat, to review PRs, to help us with devops and CI/CD, to provide feedback on usability, and to promote the project through outreach. Also, by sharing metrics with us, we can gain valuable insights into how the software performs in the wild. Resources to get started are available here .", "title": "Contribution Guide"}, {"location": "#governance-guide", "text": "The Janssen Project is chartered under the Linux Foundation. Information about the project's governance can be found here .", "title": "Governance Guide"}, {"location": "#script-catalog", "text": "Interception scripts (or custom scripts) allow you to define custom business logic for various features in Janssen without forking the Jans Server core project. Interceptions scripts are available for many components, including Auth Server, SCIM, FIDO, and Link. The definitive location for scripts and their documentation is the Script Catalog .", "title": "Script Catalog"}, {"location": "#agama", "text": "Agama is a domain specific language (\"DSL\") designed for writing web flows, and a project archive format (\".gama\") which stores all the code and web assets required for deployment of an Agama project by an identity provider. Although invented by Janssen, we envision many IDP's using Agama as a cross-vendor standard for identity orchestration.", "title": "Agama"}, {"location": "#support", "text": "If you have any questions about usage, post on Jans Discussions or try community chat on Gitter . If you find a bug in a Janssen project, or you would like to suggest a new feature, you should also post on GitHub Discussions first. The Jans team will try to replicate the bug, or weigh the feature request versus current priorities.", "title": "Support"}, {"location": "#license", "text": "Most Janssen Project components are licensed under the Apache License 2.0 . Janssen has some third party components, so it's always best to check the license for each component. We won't include any component in the distribution that has a non- OSI approved license, or a commercial trademark.", "title": "License"}, {"location": "#looking-for-older-documentation-versions", "text": "The Janssen Project posts the last five versions of the documentation. If you are looking for older versions, you can find them unprocessed in the docs folder. Select the version of choice from the tag dropdown in GitHub. If you want to process them you may do so following the steps here .", "title": "Looking for older documentation versions?"}, {"location": "CODE_OF_CONDUCT/", "text": "Janssen Code of Conduct v1.0 # Our Pledge # In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. Our Standards # Examples of behavior that contributes to creating a positive environment include: Using welcoming and inclusive language Being respectful of differing viewpoints and experiences Gracefully accepting constructive criticism Focusing on what is best for the community Showing empathy towards other community members Examples of unacceptable behavior by participants include: The use of sexualized language or imagery and unwelcome sexual attention or advances Trolling, insulting/derogatory comments, and personal or political attacks Public or private harassment Publishing others\u2019 private information, such as a physical or electronic address, without explicit permission Other conduct which could reasonably be considered inappropriate in a professional setting Our Responsibilities # Janssen Project members, project participants and contributors (collectively, \"participants\") are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. The Technical Steering Committee (\"TSC\") of the Janssen Project has the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any participant for other behaviors that they deem inappropriate, threatening, offensive, or harmful. All participants have determined that The Linux Foundation is the most optimal organization to shepherd the development of this project. Participants acknowledge and agree to The Linux Foundation's exclusive right to use \"Janssen Project\" and any other names and trademarks associated with the open source project and Janssen Project and to authorize others\u2019 use of the marks, establish guidelines for such use, and to delegate these responsibilities. Participants agree not to take any action inconsistent with such rights and to cooperate in any action which The Linux Foundation deems necessary or desirable to prevent confusion or establish or preserve these rights. Participants will not independently adopt, use, or attempt to register any trademarks or trade names that are confusingly similar to these names. Scope # This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. Enforcement # Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Executive Director, or, if the complaint involves the Executive Director, a member of the steering committee. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Participants who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by the steering committee. Attribution # This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html . For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq", "title": "Code of Conduct"}, {"location": "CODE_OF_CONDUCT/#janssen-code-of-conduct-v10", "text": "", "title": "Janssen Code of Conduct v1.0"}, {"location": "CODE_OF_CONDUCT/#our-pledge", "text": "In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.", "title": "Our Pledge"}, {"location": "CODE_OF_CONDUCT/#our-standards", "text": "Examples of behavior that contributes to creating a positive environment include: Using welcoming and inclusive language Being respectful of differing viewpoints and experiences Gracefully accepting constructive criticism Focusing on what is best for the community Showing empathy towards other community members Examples of unacceptable behavior by participants include: The use of sexualized language or imagery and unwelcome sexual attention or advances Trolling, insulting/derogatory comments, and personal or political attacks Public or private harassment Publishing others\u2019 private information, such as a physical or electronic address, without explicit permission Other conduct which could reasonably be considered inappropriate in a professional setting", "title": "Our Standards"}, {"location": "CODE_OF_CONDUCT/#our-responsibilities", "text": "Janssen Project members, project participants and contributors (collectively, \"participants\") are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. The Technical Steering Committee (\"TSC\") of the Janssen Project has the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any participant for other behaviors that they deem inappropriate, threatening, offensive, or harmful. All participants have determined that The Linux Foundation is the most optimal organization to shepherd the development of this project. Participants acknowledge and agree to The Linux Foundation's exclusive right to use \"Janssen Project\" and any other names and trademarks associated with the open source project and Janssen Project and to authorize others\u2019 use of the marks, establish guidelines for such use, and to delegate these responsibilities. Participants agree not to take any action inconsistent with such rights and to cooperate in any action which The Linux Foundation deems necessary or desirable to prevent confusion or establish or preserve these rights. Participants will not independently adopt, use, or attempt to register any trademarks or trade names that are confusingly similar to these names.", "title": "Our Responsibilities"}, {"location": "CODE_OF_CONDUCT/#scope", "text": "This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.", "title": "Scope"}, {"location": "CODE_OF_CONDUCT/#enforcement", "text": "Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Executive Director, or, if the complaint involves the Executive Director, a member of the steering committee. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Participants who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by the steering committee.", "title": "Enforcement"}, {"location": "CODE_OF_CONDUCT/#attribution", "text": "This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html . For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq", "title": "Attribution"}, {"location": "CONTRIBUTING/", "text": "Contributing to Janssen Project # Purpose of this guide is to provide necessary information and resources to community in order to make successful contribution to the Janssen Project. There are many ways you can contribute. Of course you can contribute code. But we also need people to write documentation and guides, to help us with testing, to answer questions on the forums and chat, to review PR's, to help us with devops and CI/CD, to provide feedback on usability, and to promote the project through outreach. Also, by sharing metrics with us, we can gain valuable insights into how the software performs in the wild. Join the Community First Time Contributors Contribution Guidelines Code of Conduct About Issues Triaging Code Conventions and Guidelines Commits Branches PRs Issues Contributing to the documentation Contribution Workflow Find Something To Work On Start a Discussion Implement the Change Document Raise a PR Follow Through Join the Community # Repo : Watch and Star Janssen repository on Github Discussions : Join interesting discussions at Github Discussions Chat : We have an active community chat on Gitter . You can register for free their with your Github identity. Tweet : Janssen is on Twitter too. Follow us there to stay up to date on release announcements and news around Janssen. First Time Contributors # In case you are first-time contributor, then you can start with our good first issues list These are issues where you can easily contribute and community members will guide and support your contribution as always. If you need Janssen installation to test out your fix, here are the steps . Contribution Guidelines # We are really glad you are reading this, because we need volunteer developers to help this project come to fruition. Code of Conduct Issues Triaging Coding Conventions Code of Conduct # Janssen project has a Code of Conduct to which all contributors must adhere, please read it before interacting with the repository or the community in any way. About Issues # There are four kinds of issues you can open: Bug report : you believe you found a problem in a project and you want to discuss and get it fixed, creating an issue with the bug report template is the best way to do so. Feature Request : any kind of new feature need to be discussed in this kind of issue, do you want a new rule or a new feature? This is the kind of issue you want to open. Be very good at explaining your intent, it's always important that others can understand what you mean in order to discuss, be open and collaborative in letting others help you getting this done! Security Vulnerability : If you identify a security problem, please report it immediately, providing details about the nature, and if applicable, how to reproduce it. If you want to report an issue privately, you can email security@gluu.org Failing tests : you noticed a flaky test or a problem with a build? This is the kind of issue to triage that! The best way to get involved in the project is through issues, you can help in many ways: Issues triaging: participating in the discussion and adding details to open issues is always a good thing, sometimes issues need to be verified, you could be the one writing a test case to fix a bug! Fix an issue: you can help in getting issue fixed in many ways. More often by opening a pull request. In case you are first-time contributor, then you can start with our good first issues list These are issues where you can easily contribute and community members will guide and support your contribution as always. Triaging # Triage is a process of evaluating issues and PRs in order to determine their characteristics and take quick actions if possible. When you triage an issue, you: assess whether it has merit or not quickly close it by correctly answering a question point the reporter to a resource or documentation answering the issue tag it via labels, projects, or milestones take ownership submitting a PR for it, in case you want \ud83d\ude07 Here is how we continously triage new issues and PRs so that contributors can contribute faster and better. Code Conventions and Guidelines # Commits # Janssen Project mandates all commits to follow guidelines as below. Commit messages As commit convention, we adopt Conventional Commits v1.0.0 , we have an history of commits that do not adopt the convention but any new commit must follow it to be eligible for merge. Add GPG signature to your commit To ensure that contribution is coming for a trusted source, all commits should be signed using GPG key and verified by Github. If you have GPG key setup already then just use -S switch with you commit to sign it. If you need to setup your GPG key and verification, then you can find detailed instructions here Add DCO sign-off The Developer Certificate of Origin (DCO) is a lightweight way for contributors to certify that they wrote or otherwise have the right to submit the code they are contributing to the project. Contributors to the Janssen project sign-off that they adhere to these requirements by adding a Signed-off-by line to commit messages. This is a commit message Signed-off-by: Foo Bar Git even has a -s command line option to append this automatically to your commit message: $ git commit -s -m 'This is my commit message' In all, if you have your GPG verification setup, your commit command should look like git commit -S -s -m 'message that follows conventional commit style' Branches # Branch name should have component name as prefix, eg jans-core-mybranch PRs # PR titles should also follow Conventional Commits v1.0.0 . This will help in keeping merge commit messages inline with commit message standards Squash commits into small number of cohesive commits before raising a PR PR should be rebased on main branch so that there are minimal or no conflicts at the time of merge PR should only have changes related to target feature or issue. Create a separate PR for formatting or other quick bug fixes PR should include relevent documentaton changes PR should include unit and integration tests Issues # Issue titles should follow Conventional Commits v1.0.0 Backport changes to a different version # Backport changes are now supported through a workflow through labels prefixed with backport/ . For-example to backport changes in a certain PR to version v1.0.0 a label to that PR matching the version must be added i.e backport/v1.0.0 . The flow consists of creating a new branch, cherry-picking the changes of the original PR and creating a new PR to merge them. License Header # The Janssen Project uses Apache-2.0 license. Any existing or new code file has to start with the license header as shown below: /* * This software is available under the Apache-2.0 license. * See https://www.apache.org/licenses/LICENSE-2.0.txt for full text. * * Copyright (c) 2024, Gluu, Inc. */ If the developers sign a CLA(Contributor License Agreement) they can retain the copyright. Once the CLA has been signed, contributions can be accepted from the contributor with the License header as below. Make sure to replace [github-username] with contributor's GitHub username: /* * This software is available under the Apache-2.0 license. * See https://www.apache.org/licenses/LICENSE-2.0.txt for full text. * * Copyright (c) 2024, [github-username]. */ Signing the CLA # The current version of CLA can be found here . This is just for your reference. This same CLA will be signed digitally by following the steps below: The contributor sends an e-mail expressing willingness to contribute and sign the CLA. In the email, mention your GitHub account username from which the contributions will be made. If contributions will be made on behalf of an organization, then along with the GitHub username, mention the job title and organization's name in the email. Contributor receives an email with CLA and instructions on how to sign digitally. Follow the instructions and complete the signing process. Contributing to the documentation # Great documentation is a reflection of software's maturity and the great community that stands behind it. Contributing to the Janssen Project documentation is the easiest way to learn about the Janssen Project and to get involved in the community process. In order to ensure consistency of style, language, format, and terminology across all documents, please follow the guidelines below: Glossary of terms # This glossary helps to keep terms and their meanings consistent across documentation. Janssen Project or Jans : Refers to the official project name under Linux Foundation that seeks to build the world\u2019s fastest and most comprehensive cloud native identity and access management software platform Janssen Server : Refers to a set of software components developed under the Janssen Project . Components of the Janssen Server include client and server implementations of the OAuth, OpenID Connect, SCIM and FIDO standards. The term Janssen Server is used to refer to these components as a group. jans-auth-server : Refers to a module within the Janssen Server named jans-auth-server . This is one of the significant modules of the Janssen Server that has an implementation for OAuth and OpenId Connect. Janssen Server module names: For correct naming of other modules of the Janssen Server, please refer to README Documentation Style Guide # Janssen Project documentation uses Markdown. Guidelines below are intended to bring consistency in writing and formatting documents. Testing Janssen Project documentation site is published using MkDocs. Markdown parsers used by Github and the one used by MkDocs may have slight variations in how they generate HTML. So, for a small number of cases, document may look different between Github and Janssen Project documentation site . Hence it is critical to test documentation changes locally before pushing to repository. This will ensure that final HTML rendering of documents by MkDocs is as desired. Document Title # The document title summarises what the document aims to achieve and at the same time, it plays a critical role in making the document easy to find via search. Below are a few guidelines to write good titles for documents. Every document must start with a title. Meaning, # Title should summarise what the document is trying to achieve. For examples: Integrating with the Apache mod_auth_openidc module , Integrating DUO's Universal Prompt as an authentication method , Install using Ubuntu Linux Package Title should include its context. For example, the document under Installation > VM Installation > Ubuntu should not be titled as just Ubuntu but it should have a more detailed title similar to Install using Ubuntu Linux Package . When required, to keep the title from becoming too long, assume that Janssen Server is already understood as context. Titles should be written using title case Document Tags # Janssen Project documentation uses tags to make the search more accurate and add context to search results. Following are guidelines and examples to follow while adding tags to a document. Maximum 6 tags First three should establish the context of the section hierarchy under which the document belongs. See the example below. Remaining tags can be based on the content of the document. Each tag should be a single word (no spaces, hyphens or commas, etc) All tags should be in lowercase Example: Let's look at how to add tags to a document that is located on documentation site at path Administration -> Installation -> VM installation . Also, assume that the document describes the steps to install Janssen Project on the Ubuntu platform. Tags below would be recommended: --- ta gs : - admi n is trat io n - i nstallat io n - vm - ubu ntu --- Referencing Janssen Project Release in Documents # We often need to reference release numbers in the documentation. For example, Ubuntu package installation guide . In this guide, the following command is documented: wget https://github.com/JanssenProject/jans/releases/download/v1.1.4/jans_1.1.4.ubuntu20.04_amd64.deb -P /tmp Above command contains references to the release number at two places. v1.1.4 in the URL and 1.1.4 as part of the file name. There are many such places throughout the documentation when release numbers need to be mentioned. Whenever we make a new release, these numbers need to change as they point to the latest release number. This becomes a manual task. To avoid this manual, error-prone approach the Janssen Project uses a release marker, 0.0.0-nightly instead of writing actual release numbers in the head (latest) documentation branch. So, when there is a need to mention the release number, instead of writing the actual release number, use the release marker. Let's see how to document the above command (at the head version) so that it stays up-to-date release after release. wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly.ubuntu20.04_amd64.deb -P /tmp Warning head version of documentation may contain the release marker at various places. URLs, commands etc. So, URLs, and commands might not work as it is. Users will have to manually replace the marker or use the most recent stable release documentation. Release marker should be used only when contributing to the latest documentation. Not when updating documentation for previous releases. General Text # Allow long lines to wrap, rather than manually breaking them. For example, the Introduction paragraph is a single line Keep explanations short and clear Use complete sentences when possible To make text italicised , put an _ on each side, like this: _word_ To bold text, put a double * on each end, like this: **word** Leave a blank line between paragraphs. Count a header as a paragraph for this purpose Avoid passive voice as much as possible. It's clearer to say that a subject does something than to say a result was done Avoid using you in statements as much as possible. For example, instead of saying You can navigate to... simply say Navigate to... Page Setup # Start your page with a title on the first line Follow with a concise overview of the document / product's purpose Organize the information in the document from least technical to most technical if possible. Start conceptual, then get detailed Lists # Leave a blank line between text and first item in the list Only use a numbered list if the order of the list matters A line of a list should not end with a period. If it's multiple sentences, like this one, drop the last period Start each item in the list with a capital letter End each item in the list with at least three spaces. This makes sure the line breaks properly To make a bulleted list, start each line with - To make a numbered list, start each line with 1. For example: 1. This is the first item 1. This is the second item 1. This is the third item It will look like this: 1. This is the first item 2. This is the second item 3. This is the third item To include additional lines in a list item, start the sub-line with four spaces. For example: 1. This is the first item in a list There are four spaces to start this line Another four spaces here This keeps all text inside the numbered list item, before starting... 1. The following list item It will look like this: This is the first item in a list There are four spaces to start this line Another four spaces here This keeps all text inside the list, before starting... The following list item Other formatting considerations # Admonitions cannot be nested inside a list. They must be aligned all the way left. Inserting them within a list will break the list sequence (starting back over from 1). Nesting a fenced block of code in a numbered list is more challenging, as the list and code block syntaxes clash. To nest a code block into a list, insert four spaces to the left of all lines of the formatting. For example: 1. This is the first item ``` This is code This is also code. ``` 1. This is the second item It will look like this: This is the first item This is code This is also code. This is the second item Headings # Headings should be in title format. All important words should be capitalized The main title of the page should start with a single # , then each level of subheading should add one. For example, the first subheading should start with ## , a subheading of that should use ### , and so on Code Formatting # To format text as code within a line of normal text, surround the code with a single backtick (`). If the code is to be on its own line, it should be a fenced code block. To make a fenced code block, make a line before and after the code with three backticks: ``` This is code ``` We use the SuperFences plugin to enhance this functionality. Examples & Navigation # When possible, provide an example in the form of code output or a screenshot To instruct a user to click a button, or navigate to a certain page or through a menu, use the following style: Navigate to `Configuration` > `Authentication` and click the `Passport` tab It will look like this: Navigate to Configuration > Authentication and click the Passport tab Linking # We recommend using relative linking syntax when linking to other artifacts in repository. Linking to a page within the same repo use this format: [text for the link](../where/the/link/goes.md) - You must link to the .md file on GitHub for it to work properly - As an example, to make text this link link to a Markdown document named example.md in the same directory, you'd type it as [this link](./example.md) Service Commands # The Janssen Server supports many different Operating Systems (e.g. Ubuntu, SUSE etc.). Service commands can vary. Rather than \"hard coding\" service commands into documentation, please instead reference the dedicated documentation page for Service Commands . In documenting a process that involves a service restart, the Service Command documentation is linked: ## Add the attribute to MySQL - Add custom attribute - [Restart](https://jans.io/docs/vm-ops/restarting-services/) the `jans-auth.service` service. The word Restart is simply linked to the dedicated doc for Service Commands. Tables # Try to make tables visually readable by spacing to make distinct columns The header for each column must be separated by at least three dashes Use outer pipes for consistency If an entry is too long to fit in the neat boxes, that's fine, just try to keep it legible An example table follows: |This |Is |A |Table | |--------|-------|------|---------| |1 |2 |3 |4 | |Word |Code |Text |Table | It looks like this: This Is A Table 1 2 3 4 Word Code Text Table Help On Technical Writing # It is essential for everyone in the community to actively participate in the documentation. At the same time, not everyone is formally trained or experienced in writing technical documents. To help everyone understand the basics of good technical writing, we have listed a few resources below. Going through these resources will not take a lot of time and will help in writing better technical documents. Introduction to Technical Writing (part-1) Introduction to Technical Writing (part-2) Contribution Workflow # Find something to work on # Best place to find something to work on is to look at currently open issues . If you are a first time contributor then starting with list of good first issues is best. Start a discussion # Start a Github Discussion about what you are planning to contribute. Explain the feature or issue that you are planning to contribute and what your solution or implementation approach. Janssen is a community driven project and it'll be helpful to get community's view about it. Create an issue # Take your time to write a proper issue including a good summary and description. Outcome of Github discussion about your contribution can help you create good content for the issue. As a first step when creating a new issue, an issue template has to be selected. Select appropriate issue template and it'll help you create an issue with right content. Remember that issue may be the first thing a reviewer of your PR will look at to get an idea of what you are proposing. It will also be used by the community in the future to find about what new features and enhancements are included in new releases. Implement the change # All contributions to Janssen Project should be made via Github pull requests(PR). New to PR workflow?? Learn and practice it at first-contributions Create a Fork # Fork Janssen repository . And create a clone. Implement the Change # Start working on changes as required. Make sure the code conventions are being followed. Use static code analysis and linting tools to make sure the code is high-quality. Write tests first and then code. Ensure that integration tests that cover your code are appropriately updated and reviewed. Create PR early and push often. Janssen uses Github actions to run automated checks on PR changes. Ensure that these checks are passing with every push. Engage PR reviewers at the start so that they can continue to reivew code as it is developed and in small chunks. For a change that is non-trivial(an enhancement or a new feature), design should be reviewed. This should be done via PR by adding appropriate code owners. Document # PR should include changes in relevant documentation along with code changes. PR is checked by bot to have either one of the following : A commit that follows commit guidelines with docs: message Changes in artifacts under jans/docs If PR does not need any documentation changes, then the developer needs to acknowledge that in one of two ways: Add an empty commit to the PR (using --allow-empty git flag) with docs: message (i.e docs: no doc changes required ) Add footer to the commit message of one of the code commits with docs: message e.g fix: typo on class name More details here. docs: no docs modification Raise a PR # Make sure that PR title follows these guidelines Janssen uses Github PR template. Template provides helpful instructions to ensure new PRs are complete in details and easy to review. Github will populate new PR's description with these instructions. You can edit PR description as per your requirements. When PR is raised, Github will automatically assign reviewer to the PR based changed files and CODEOWNERS list. Once PR is raised, ensure that PR passes all the mandatory Github actions checks available on Github PR page. Github will not allow PR to be merged if any of the mandatory check is failing. Follow Through # Once the PR is raised, wait for reviewers to start review. Reviewers will start review at the first opportunity available. If you want to draw attention, give a gentle reminder in PR comments. But please be patient. Follow activities on your PR closely till the time PR is merged. PR reviewer may want to suggest a change or may need to ask a question to get more clarity. Make sure you are actively collaborating. Once Reviewer has completed the review and approved the changes, the PR will be merged. Thats it!! Congratulations on successful contribution. \ud83e\udd73 \ud83e\udd1f", "title": "Contribution Guidelines"}, {"location": "CONTRIBUTING/#contributing-to-janssen-project", "text": "Purpose of this guide is to provide necessary information and resources to community in order to make successful contribution to the Janssen Project. There are many ways you can contribute. Of course you can contribute code. But we also need people to write documentation and guides, to help us with testing, to answer questions on the forums and chat, to review PR's, to help us with devops and CI/CD, to provide feedback on usability, and to promote the project through outreach. Also, by sharing metrics with us, we can gain valuable insights into how the software performs in the wild. Join the Community First Time Contributors Contribution Guidelines Code of Conduct About Issues Triaging Code Conventions and Guidelines Commits Branches PRs Issues Contributing to the documentation Contribution Workflow Find Something To Work On Start a Discussion Implement the Change Document Raise a PR Follow Through", "title": "Contributing to Janssen Project"}, {"location": "CONTRIBUTING/#join-the-community", "text": "Repo : Watch and Star Janssen repository on Github Discussions : Join interesting discussions at Github Discussions Chat : We have an active community chat on Gitter . You can register for free their with your Github identity. Tweet : Janssen is on Twitter too. Follow us there to stay up to date on release announcements and news around Janssen.", "title": "Join the Community"}, {"location": "CONTRIBUTING/#first-time-contributors", "text": "In case you are first-time contributor, then you can start with our good first issues list These are issues where you can easily contribute and community members will guide and support your contribution as always. If you need Janssen installation to test out your fix, here are the steps .", "title": "First Time Contributors"}, {"location": "CONTRIBUTING/#contribution-guidelines", "text": "We are really glad you are reading this, because we need volunteer developers to help this project come to fruition. Code of Conduct Issues Triaging Coding Conventions", "title": "Contribution Guidelines"}, {"location": "CONTRIBUTING/#code-of-conduct", "text": "Janssen project has a Code of Conduct to which all contributors must adhere, please read it before interacting with the repository or the community in any way.", "title": "Code of Conduct"}, {"location": "CONTRIBUTING/#about-issues", "text": "There are four kinds of issues you can open: Bug report : you believe you found a problem in a project and you want to discuss and get it fixed, creating an issue with the bug report template is the best way to do so. Feature Request : any kind of new feature need to be discussed in this kind of issue, do you want a new rule or a new feature? This is the kind of issue you want to open. Be very good at explaining your intent, it's always important that others can understand what you mean in order to discuss, be open and collaborative in letting others help you getting this done! Security Vulnerability : If you identify a security problem, please report it immediately, providing details about the nature, and if applicable, how to reproduce it. If you want to report an issue privately, you can email security@gluu.org Failing tests : you noticed a flaky test or a problem with a build? This is the kind of issue to triage that! The best way to get involved in the project is through issues, you can help in many ways: Issues triaging: participating in the discussion and adding details to open issues is always a good thing, sometimes issues need to be verified, you could be the one writing a test case to fix a bug! Fix an issue: you can help in getting issue fixed in many ways. More often by opening a pull request. In case you are first-time contributor, then you can start with our good first issues list These are issues where you can easily contribute and community members will guide and support your contribution as always.", "title": "About Issues"}, {"location": "CONTRIBUTING/#triaging", "text": "Triage is a process of evaluating issues and PRs in order to determine their characteristics and take quick actions if possible. When you triage an issue, you: assess whether it has merit or not quickly close it by correctly answering a question point the reporter to a resource or documentation answering the issue tag it via labels, projects, or milestones take ownership submitting a PR for it, in case you want \ud83d\ude07 Here is how we continously triage new issues and PRs so that contributors can contribute faster and better.", "title": "Triaging"}, {"location": "CONTRIBUTING/#code-conventions-and-guidelines", "text": "", "title": "Code Conventions and Guidelines"}, {"location": "CONTRIBUTING/#commits", "text": "Janssen Project mandates all commits to follow guidelines as below. Commit messages As commit convention, we adopt Conventional Commits v1.0.0 , we have an history of commits that do not adopt the convention but any new commit must follow it to be eligible for merge. Add GPG signature to your commit To ensure that contribution is coming for a trusted source, all commits should be signed using GPG key and verified by Github. If you have GPG key setup already then just use -S switch with you commit to sign it. If you need to setup your GPG key and verification, then you can find detailed instructions here Add DCO sign-off The Developer Certificate of Origin (DCO) is a lightweight way for contributors to certify that they wrote or otherwise have the right to submit the code they are contributing to the project. Contributors to the Janssen project sign-off that they adhere to these requirements by adding a Signed-off-by line to commit messages. This is a commit message Signed-off-by: Foo Bar <foobar@spam.org> Git even has a -s command line option to append this automatically to your commit message: $ git commit -s -m 'This is my commit message' In all, if you have your GPG verification setup, your commit command should look like git commit -S -s -m 'message that follows conventional commit style'", "title": "Commits"}, {"location": "CONTRIBUTING/#branches", "text": "Branch name should have component name as prefix, eg jans-core-mybranch", "title": "Branches"}, {"location": "CONTRIBUTING/#prs", "text": "PR titles should also follow Conventional Commits v1.0.0 . This will help in keeping merge commit messages inline with commit message standards Squash commits into small number of cohesive commits before raising a PR PR should be rebased on main branch so that there are minimal or no conflicts at the time of merge PR should only have changes related to target feature or issue. Create a separate PR for formatting or other quick bug fixes PR should include relevent documentaton changes PR should include unit and integration tests", "title": "PRs"}, {"location": "CONTRIBUTING/#issues", "text": "Issue titles should follow Conventional Commits v1.0.0", "title": "Issues"}, {"location": "CONTRIBUTING/#backport-changes-to-a-different-version", "text": "Backport changes are now supported through a workflow through labels prefixed with backport/ . For-example to backport changes in a certain PR to version v1.0.0 a label to that PR matching the version must be added i.e backport/v1.0.0 . The flow consists of creating a new branch, cherry-picking the changes of the original PR and creating a new PR to merge them.", "title": "Backport changes to a different version"}, {"location": "CONTRIBUTING/#license-header", "text": "The Janssen Project uses Apache-2.0 license. Any existing or new code file has to start with the license header as shown below: /* * This software is available under the Apache-2.0 license. * See https://www.apache.org/licenses/LICENSE-2.0.txt for full text. * * Copyright (c) 2024, Gluu, Inc. */ If the developers sign a CLA(Contributor License Agreement) they can retain the copyright. Once the CLA has been signed, contributions can be accepted from the contributor with the License header as below. Make sure to replace [github-username] with contributor's GitHub username: /* * This software is available under the Apache-2.0 license. * See https://www.apache.org/licenses/LICENSE-2.0.txt for full text. * * Copyright (c) 2024, [github-username]. */", "title": "License Header"}, {"location": "CONTRIBUTING/#signing-the-cla", "text": "The current version of CLA can be found here . This is just for your reference. This same CLA will be signed digitally by following the steps below: The contributor sends an e-mail expressing willingness to contribute and sign the CLA. In the email, mention your GitHub account username from which the contributions will be made. If contributions will be made on behalf of an organization, then along with the GitHub username, mention the job title and organization's name in the email. Contributor receives an email with CLA and instructions on how to sign digitally. Follow the instructions and complete the signing process.", "title": "Signing the CLA"}, {"location": "CONTRIBUTING/#contributing-to-the-documentation", "text": "Great documentation is a reflection of software's maturity and the great community that stands behind it. Contributing to the Janssen Project documentation is the easiest way to learn about the Janssen Project and to get involved in the community process. In order to ensure consistency of style, language, format, and terminology across all documents, please follow the guidelines below:", "title": "Contributing to the documentation"}, {"location": "CONTRIBUTING/#glossary-of-terms", "text": "This glossary helps to keep terms and their meanings consistent across documentation. Janssen Project or Jans : Refers to the official project name under Linux Foundation that seeks to build the world\u2019s fastest and most comprehensive cloud native identity and access management software platform Janssen Server : Refers to a set of software components developed under the Janssen Project . Components of the Janssen Server include client and server implementations of the OAuth, OpenID Connect, SCIM and FIDO standards. The term Janssen Server is used to refer to these components as a group. jans-auth-server : Refers to a module within the Janssen Server named jans-auth-server . This is one of the significant modules of the Janssen Server that has an implementation for OAuth and OpenId Connect. Janssen Server module names: For correct naming of other modules of the Janssen Server, please refer to README", "title": "Glossary of terms"}, {"location": "CONTRIBUTING/#documentation-style-guide", "text": "Janssen Project documentation uses Markdown. Guidelines below are intended to bring consistency in writing and formatting documents. Testing Janssen Project documentation site is published using MkDocs. Markdown parsers used by Github and the one used by MkDocs may have slight variations in how they generate HTML. So, for a small number of cases, document may look different between Github and Janssen Project documentation site . Hence it is critical to test documentation changes locally before pushing to repository. This will ensure that final HTML rendering of documents by MkDocs is as desired.", "title": "Documentation Style Guide"}, {"location": "CONTRIBUTING/#document-title", "text": "The document title summarises what the document aims to achieve and at the same time, it plays a critical role in making the document easy to find via search. Below are a few guidelines to write good titles for documents. Every document must start with a title. Meaning, #<space><title text> Title should summarise what the document is trying to achieve. For examples: Integrating with the Apache mod_auth_openidc module , Integrating DUO's Universal Prompt as an authentication method , Install using Ubuntu Linux Package Title should include its context. For example, the document under Installation > VM Installation > Ubuntu should not be titled as just Ubuntu but it should have a more detailed title similar to Install using Ubuntu Linux Package . When required, to keep the title from becoming too long, assume that Janssen Server is already understood as context. Titles should be written using title case", "title": "Document Title"}, {"location": "CONTRIBUTING/#document-tags", "text": "Janssen Project documentation uses tags to make the search more accurate and add context to search results. Following are guidelines and examples to follow while adding tags to a document. Maximum 6 tags First three should establish the context of the section hierarchy under which the document belongs. See the example below. Remaining tags can be based on the content of the document. Each tag should be a single word (no spaces, hyphens or commas, etc) All tags should be in lowercase Example: Let's look at how to add tags to a document that is located on documentation site at path Administration -> Installation -> VM installation . Also, assume that the document describes the steps to install Janssen Project on the Ubuntu platform. Tags below would be recommended: --- ta gs : - admi n is trat io n - i nstallat io n - vm - ubu ntu ---", "title": "Document Tags"}, {"location": "CONTRIBUTING/#referencing-janssen-project-release-in-documents", "text": "We often need to reference release numbers in the documentation. For example, Ubuntu package installation guide . In this guide, the following command is documented: wget https://github.com/JanssenProject/jans/releases/download/v1.1.4/jans_1.1.4.ubuntu20.04_amd64.deb -P /tmp Above command contains references to the release number at two places. v1.1.4 in the URL and 1.1.4 as part of the file name. There are many such places throughout the documentation when release numbers need to be mentioned. Whenever we make a new release, these numbers need to change as they point to the latest release number. This becomes a manual task. To avoid this manual, error-prone approach the Janssen Project uses a release marker, 0.0.0-nightly instead of writing actual release numbers in the head (latest) documentation branch. So, when there is a need to mention the release number, instead of writing the actual release number, use the release marker. Let's see how to document the above command (at the head version) so that it stays up-to-date release after release. wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly.ubuntu20.04_amd64.deb -P /tmp Warning head version of documentation may contain the release marker at various places. URLs, commands etc. So, URLs, and commands might not work as it is. Users will have to manually replace the marker or use the most recent stable release documentation. Release marker should be used only when contributing to the latest documentation. Not when updating documentation for previous releases.", "title": "Referencing Janssen Project Release in Documents"}, {"location": "CONTRIBUTING/#general-text", "text": "Allow long lines to wrap, rather than manually breaking them. For example, the Introduction paragraph is a single line Keep explanations short and clear Use complete sentences when possible To make text italicised , put an _ on each side, like this: _word_ To bold text, put a double * on each end, like this: **word** Leave a blank line between paragraphs. Count a header as a paragraph for this purpose Avoid passive voice as much as possible. It's clearer to say that a subject does something than to say a result was done Avoid using you in statements as much as possible. For example, instead of saying You can navigate to... simply say Navigate to...", "title": "General Text"}, {"location": "CONTRIBUTING/#page-setup", "text": "Start your page with a title on the first line Follow with a concise overview of the document / product's purpose Organize the information in the document from least technical to most technical if possible. Start conceptual, then get detailed", "title": "Page Setup"}, {"location": "CONTRIBUTING/#lists", "text": "Leave a blank line between text and first item in the list Only use a numbered list if the order of the list matters A line of a list should not end with a period. If it's multiple sentences, like this one, drop the last period Start each item in the list with a capital letter End each item in the list with at least three spaces. This makes sure the line breaks properly To make a bulleted list, start each line with - To make a numbered list, start each line with 1. For example: 1. This is the first item 1. This is the second item 1. This is the third item It will look like this: 1. This is the first item 2. This is the second item 3. This is the third item To include additional lines in a list item, start the sub-line with four spaces. For example: 1. This is the first item in a list There are four spaces to start this line Another four spaces here This keeps all text inside the numbered list item, before starting... 1. The following list item It will look like this: This is the first item in a list There are four spaces to start this line Another four spaces here This keeps all text inside the list, before starting... The following list item", "title": "Lists"}, {"location": "CONTRIBUTING/#other-formatting-considerations", "text": "Admonitions cannot be nested inside a list. They must be aligned all the way left. Inserting them within a list will break the list sequence (starting back over from 1). Nesting a fenced block of code in a numbered list is more challenging, as the list and code block syntaxes clash. To nest a code block into a list, insert four spaces to the left of all lines of the formatting. For example: 1. This is the first item ``` This is code This is also code. ``` 1. This is the second item It will look like this: This is the first item This is code This is also code. This is the second item", "title": "Other formatting considerations"}, {"location": "CONTRIBUTING/#headings", "text": "Headings should be in title format. All important words should be capitalized The main title of the page should start with a single # , then each level of subheading should add one. For example, the first subheading should start with ## , a subheading of that should use ### , and so on", "title": "Headings"}, {"location": "CONTRIBUTING/#code-formatting", "text": "To format text as code within a line of normal text, surround the code with a single backtick (`). If the code is to be on its own line, it should be a fenced code block. To make a fenced code block, make a line before and after the code with three backticks: ``` This is code ``` We use the SuperFences plugin to enhance this functionality.", "title": "Code Formatting"}, {"location": "CONTRIBUTING/#examples-navigation", "text": "When possible, provide an example in the form of code output or a screenshot To instruct a user to click a button, or navigate to a certain page or through a menu, use the following style: Navigate to `Configuration` > `Authentication` and click the `Passport` tab It will look like this: Navigate to Configuration > Authentication and click the Passport tab", "title": "Examples & Navigation"}, {"location": "CONTRIBUTING/#linking", "text": "We recommend using relative linking syntax when linking to other artifacts in repository. Linking to a page within the same repo use this format: [text for the link](../where/the/link/goes.md) - You must link to the .md file on GitHub for it to work properly - As an example, to make text this link link to a Markdown document named example.md in the same directory, you'd type it as [this link](./example.md)", "title": "Linking"}, {"location": "CONTRIBUTING/#service-commands", "text": "The Janssen Server supports many different Operating Systems (e.g. Ubuntu, SUSE etc.). Service commands can vary. Rather than \"hard coding\" service commands into documentation, please instead reference the dedicated documentation page for Service Commands . In documenting a process that involves a service restart, the Service Command documentation is linked: ## Add the attribute to MySQL - Add custom attribute - [Restart](https://jans.io/docs/vm-ops/restarting-services/) the `jans-auth.service` service. The word Restart is simply linked to the dedicated doc for Service Commands.", "title": "Service Commands"}, {"location": "CONTRIBUTING/#tables", "text": "Try to make tables visually readable by spacing to make distinct columns The header for each column must be separated by at least three dashes Use outer pipes for consistency If an entry is too long to fit in the neat boxes, that's fine, just try to keep it legible An example table follows: |This |Is |A |Table | |--------|-------|------|---------| |1 |2 |3 |4 | |Word |Code |Text |Table | It looks like this: This Is A Table 1 2 3 4 Word Code Text Table", "title": "Tables"}, {"location": "CONTRIBUTING/#help-on-technical-writing", "text": "It is essential for everyone in the community to actively participate in the documentation. At the same time, not everyone is formally trained or experienced in writing technical documents. To help everyone understand the basics of good technical writing, we have listed a few resources below. Going through these resources will not take a lot of time and will help in writing better technical documents. Introduction to Technical Writing (part-1) Introduction to Technical Writing (part-2)", "title": "Help On Technical Writing"}, {"location": "CONTRIBUTING/#contribution-workflow", "text": "", "title": "Contribution Workflow"}, {"location": "CONTRIBUTING/#find-something-to-work-on", "text": "Best place to find something to work on is to look at currently open issues . If you are a first time contributor then starting with list of good first issues is best.", "title": "Find something to work on"}, {"location": "CONTRIBUTING/#start-a-discussion", "text": "Start a Github Discussion about what you are planning to contribute. Explain the feature or issue that you are planning to contribute and what your solution or implementation approach. Janssen is a community driven project and it'll be helpful to get community's view about it.", "title": "Start a discussion"}, {"location": "CONTRIBUTING/#create-an-issue", "text": "Take your time to write a proper issue including a good summary and description. Outcome of Github discussion about your contribution can help you create good content for the issue. As a first step when creating a new issue, an issue template has to be selected. Select appropriate issue template and it'll help you create an issue with right content. Remember that issue may be the first thing a reviewer of your PR will look at to get an idea of what you are proposing. It will also be used by the community in the future to find about what new features and enhancements are included in new releases.", "title": "Create an issue"}, {"location": "CONTRIBUTING/#implement-the-change", "text": "All contributions to Janssen Project should be made via Github pull requests(PR). New to PR workflow?? Learn and practice it at first-contributions", "title": "Implement the change"}, {"location": "CONTRIBUTING/#create-a-fork", "text": "Fork Janssen repository . And create a clone.", "title": "Create a Fork"}, {"location": "CONTRIBUTING/#implement-the-change_1", "text": "Start working on changes as required. Make sure the code conventions are being followed. Use static code analysis and linting tools to make sure the code is high-quality. Write tests first and then code. Ensure that integration tests that cover your code are appropriately updated and reviewed. Create PR early and push often. Janssen uses Github actions to run automated checks on PR changes. Ensure that these checks are passing with every push. Engage PR reviewers at the start so that they can continue to reivew code as it is developed and in small chunks. For a change that is non-trivial(an enhancement or a new feature), design should be reviewed. This should be done via PR by adding appropriate code owners.", "title": "Implement the Change"}, {"location": "CONTRIBUTING/#document", "text": "PR should include changes in relevant documentation along with code changes. PR is checked by bot to have either one of the following : A commit that follows commit guidelines with docs: message Changes in artifacts under jans/docs If PR does not need any documentation changes, then the developer needs to acknowledge that in one of two ways: Add an empty commit to the PR (using --allow-empty git flag) with docs: message (i.e docs: no doc changes required ) Add footer to the commit message of one of the code commits with docs: message e.g fix: typo on class name More details here. docs: no docs modification", "title": "Document"}, {"location": "CONTRIBUTING/#raise-a-pr", "text": "Make sure that PR title follows these guidelines Janssen uses Github PR template. Template provides helpful instructions to ensure new PRs are complete in details and easy to review. Github will populate new PR's description with these instructions. You can edit PR description as per your requirements. When PR is raised, Github will automatically assign reviewer to the PR based changed files and CODEOWNERS list. Once PR is raised, ensure that PR passes all the mandatory Github actions checks available on Github PR page. Github will not allow PR to be merged if any of the mandatory check is failing.", "title": "Raise a PR"}, {"location": "CONTRIBUTING/#follow-through", "text": "Once the PR is raised, wait for reviewers to start review. Reviewers will start review at the first opportunity available. If you want to draw attention, give a gentle reminder in PR comments. But please be patient. Follow activities on your PR closely till the time PR is merged. PR reviewer may want to suggest a change or may need to ask a question to get more clarity. Make sure you are actively collaborating. Once Reviewer has completed the review and approved the changes, the PR will be merged. Thats it!! Congratulations on successful contribution. \ud83e\udd73 \ud83e\udd1f", "title": "Follow Through"}, {"location": "agama/execution-rules/", "tags": ["administration", "developer", "agama"], "text": "Flows execution rules # This document regards flow execution details. Engines implementing the Agama framework must account these aspects fully. Important The concept of \" top-level \" flow is used in several places throughout this page. It refers to a flow which has been directly launched from the user browser and hence has no parents (no callers). Flows lifecycle # From a programming perspective, a flow is a lot like a function or subroutine in a regular program. Once a flow is triggered, it must be executed from top to bottom until a Finish statement is encountered. There are no special requirements on flow initialization or flow structure either. In some cases, the Finish instruction is not reached because the flow: has crashed has been cancelled has timed out More on these conditions below. Otherwise, the flow is said to have finished and depending on the actual arguments passed to Finish , it can be said the flow finished successfully or the flow failed . Successful flows # When a flow finishes successfully, control returns to the caller (parent flow) and execution continues. In the case of a top-level flow, it is up to the concrete engine what to do next. Normally, the arguments passed to the Finish directive will drive the specific behavior, which could for instance authenticate a person. Failed flows # When a flow fails, control returns to the caller (parent flow) and execution continues. In the case of a top-level flow, it is up to the concrete engine what to do next. Displaying an error page would be generally appropriate. The arguments passed to the Finish directive could be of use here. Crashed flows # A flow is said to have crashed if any of the below occur: Invalid code (syntactically wrong) was tried to be executed The last instruction was reached and Finish was not encountered An attempt to access a property or index of a null variable was made The invocation of a foreign routine, i.e. through Call , raised an error condition, and the error was not caught Any unexpected runtime error was raised When a flow crashes, the caller flow (if any) is said to have crashed too if it did not catch the given error. This rule applies recursively until the top-level flow is reached. When a top-level flow crashes, engines must: Show an error with a concise descriptive error description Append a fuller error message to whatever logging system is in place Terminate the flow execution to allow the user start again the flow later in a safe manner Flows timeout # The Timeout directive specifies a maximum allowable execution time for a top-level flow. When a flow exceeds this execution time, engines should display an error page accordingly. Cancelled flows # Cancellation allows a flow to early interrupt the execution of a given subflow thus enabling the implementation of alternative routing without the need of re-writing subflows. It can only take place upon the execution of a given RRF instruction part of a subflow that has been Trigger ed. This feature is better understood via examples - note the link provided is specific to the Janssen Server engine only. Other engines may implement cancellation in a different way, the only requirement is to preserve the convention that the returned value of a cancelled flow must be of the form: { aborted: true, data: ..., url: ... } . Launching flows # Engines must provide specific mechanisms to launch a given flow in the user's browser and document how to pass input parameters to it and the formats allowed. Logging # Engines must maintain at least one logging destination (file, stream, etc.) to accumulate the messages passed in Log directives. Additionally, it should advertise the logging levels supported, their abbreviations if any, and the default logging level. RFAC and Callback URL # Engines must provide and maintain a fixed single URL that \"users\" of RFAC can supply to external systems in order to implement integrations with third-party sites that employ browser redirections. This URL should only be available for a given browser session while RFAC is in execution. Once the callback is visited or the flow times out (whichever occurs first), subsequent requests will respond with an HTTP 404 error. The mechanism used by the engine to make the redirect to the external site is implementation specific. Assets management # Engines must have an internal mechanism to store assets following a hierarchical (filesystem-like) structure. Such structure must have a defined \"root\" that in conjunction with a flow Basepath will allow the engine to resolve (locate) the paths to specific flow assets. Engines may support one or more templating technologies and file formats for rendering the UI pages. Foreign calls # Languages support # At least one programming language should be supported by an engine. This feature is critical because Agama DSL was designed to force developers use a distinct, more powerful language when the task at hand cannot be implemented by simple data manipulation or comparison of values. Routines lookup # Engines should define a clear mechanism to lookup the specific routine to be invoked when using the Call directive. Actually, the syntax of Call fits well into an object-oriented style. The table bellow illustrates this fact: Example Potential semantics Call a B c d On object instance a , invoke method B passing c and d as parameters Call x.y.z#S d Invoke method S belonging to class x.y.z passing d as parameter. This variant maps to a \"static\" method invocation, where S does not require a specific instance to run on In OOP, it is not uncommon to have a method S with several different signatures. The lookup mechanism should account disambiguation techniques, if possible. Errors # In the execution of the call, if an error occurs, the engine should raise an error catchable in Agama code. The structure or data type of this error is an engine-specific detail. Ideally the error should be easily inspected in Agama code so any required further processing is feasible in a flow. Types compatibility # The arguments conversion/compatibility is also an important topic. Most likely Agama types will not match the (foreign) target language types. This means passing a \"native\" Agama value as parameter in a method Call requires some form of compatibility with the target type in the routine (method) signature. When compatibility does not make sense, seems too complex, or impossible, invocation should \"crash\" by raising some form of error. The same analysis has to be done in the other direction: from the target language to Agama. This is for the case where the Call returns a value. Such value should be \"manipulable\" in Agama code. Other considerations # Engine implementers may consider to offer the ability for developers to supply routines without the need of engine restarts. This aims for an agile development experience.", "title": "Execution rules"}, {"location": "agama/execution-rules/#flows-execution-rules", "text": "This document regards flow execution details. Engines implementing the Agama framework must account these aspects fully. Important The concept of \" top-level \" flow is used in several places throughout this page. It refers to a flow which has been directly launched from the user browser and hence has no parents (no callers).", "title": "Flows execution rules"}, {"location": "agama/execution-rules/#flows-lifecycle", "text": "From a programming perspective, a flow is a lot like a function or subroutine in a regular program. Once a flow is triggered, it must be executed from top to bottom until a Finish statement is encountered. There are no special requirements on flow initialization or flow structure either. In some cases, the Finish instruction is not reached because the flow: has crashed has been cancelled has timed out More on these conditions below. Otherwise, the flow is said to have finished and depending on the actual arguments passed to Finish , it can be said the flow finished successfully or the flow failed .", "title": "Flows lifecycle"}, {"location": "agama/execution-rules/#successful-flows", "text": "When a flow finishes successfully, control returns to the caller (parent flow) and execution continues. In the case of a top-level flow, it is up to the concrete engine what to do next. Normally, the arguments passed to the Finish directive will drive the specific behavior, which could for instance authenticate a person.", "title": "Successful flows"}, {"location": "agama/execution-rules/#failed-flows", "text": "When a flow fails, control returns to the caller (parent flow) and execution continues. In the case of a top-level flow, it is up to the concrete engine what to do next. Displaying an error page would be generally appropriate. The arguments passed to the Finish directive could be of use here.", "title": "Failed flows"}, {"location": "agama/execution-rules/#crashed-flows", "text": "A flow is said to have crashed if any of the below occur: Invalid code (syntactically wrong) was tried to be executed The last instruction was reached and Finish was not encountered An attempt to access a property or index of a null variable was made The invocation of a foreign routine, i.e. through Call , raised an error condition, and the error was not caught Any unexpected runtime error was raised When a flow crashes, the caller flow (if any) is said to have crashed too if it did not catch the given error. This rule applies recursively until the top-level flow is reached. When a top-level flow crashes, engines must: Show an error with a concise descriptive error description Append a fuller error message to whatever logging system is in place Terminate the flow execution to allow the user start again the flow later in a safe manner", "title": "Crashed flows"}, {"location": "agama/execution-rules/#flows-timeout", "text": "The Timeout directive specifies a maximum allowable execution time for a top-level flow. When a flow exceeds this execution time, engines should display an error page accordingly.", "title": "Flows timeout"}, {"location": "agama/execution-rules/#cancelled-flows", "text": "Cancellation allows a flow to early interrupt the execution of a given subflow thus enabling the implementation of alternative routing without the need of re-writing subflows. It can only take place upon the execution of a given RRF instruction part of a subflow that has been Trigger ed. This feature is better understood via examples - note the link provided is specific to the Janssen Server engine only. Other engines may implement cancellation in a different way, the only requirement is to preserve the convention that the returned value of a cancelled flow must be of the form: { aborted: true, data: ..., url: ... } .", "title": "Cancelled flows"}, {"location": "agama/execution-rules/#launching-flows", "text": "Engines must provide specific mechanisms to launch a given flow in the user's browser and document how to pass input parameters to it and the formats allowed.", "title": "Launching flows"}, {"location": "agama/execution-rules/#logging", "text": "Engines must maintain at least one logging destination (file, stream, etc.) to accumulate the messages passed in Log directives. Additionally, it should advertise the logging levels supported, their abbreviations if any, and the default logging level.", "title": "Logging"}, {"location": "agama/execution-rules/#rfac-and-callback-url", "text": "Engines must provide and maintain a fixed single URL that \"users\" of RFAC can supply to external systems in order to implement integrations with third-party sites that employ browser redirections. This URL should only be available for a given browser session while RFAC is in execution. Once the callback is visited or the flow times out (whichever occurs first), subsequent requests will respond with an HTTP 404 error. The mechanism used by the engine to make the redirect to the external site is implementation specific.", "title": "RFAC and Callback URL"}, {"location": "agama/execution-rules/#assets-management", "text": "Engines must have an internal mechanism to store assets following a hierarchical (filesystem-like) structure. Such structure must have a defined \"root\" that in conjunction with a flow Basepath will allow the engine to resolve (locate) the paths to specific flow assets. Engines may support one or more templating technologies and file formats for rendering the UI pages.", "title": "Assets management"}, {"location": "agama/execution-rules/#foreign-calls", "text": "", "title": "Foreign calls"}, {"location": "agama/execution-rules/#languages-support", "text": "At least one programming language should be supported by an engine. This feature is critical because Agama DSL was designed to force developers use a distinct, more powerful language when the task at hand cannot be implemented by simple data manipulation or comparison of values.", "title": "Languages support"}, {"location": "agama/execution-rules/#routines-lookup", "text": "Engines should define a clear mechanism to lookup the specific routine to be invoked when using the Call directive. Actually, the syntax of Call fits well into an object-oriented style. The table bellow illustrates this fact: Example Potential semantics Call a B c d On object instance a , invoke method B passing c and d as parameters Call x.y.z#S d Invoke method S belonging to class x.y.z passing d as parameter. This variant maps to a \"static\" method invocation, where S does not require a specific instance to run on In OOP, it is not uncommon to have a method S with several different signatures. The lookup mechanism should account disambiguation techniques, if possible.", "title": "Routines lookup"}, {"location": "agama/execution-rules/#errors", "text": "In the execution of the call, if an error occurs, the engine should raise an error catchable in Agama code. The structure or data type of this error is an engine-specific detail. Ideally the error should be easily inspected in Agama code so any required further processing is feasible in a flow.", "title": "Errors"}, {"location": "agama/execution-rules/#types-compatibility", "text": "The arguments conversion/compatibility is also an important topic. Most likely Agama types will not match the (foreign) target language types. This means passing a \"native\" Agama value as parameter in a method Call requires some form of compatibility with the target type in the routine (method) signature. When compatibility does not make sense, seems too complex, or impossible, invocation should \"crash\" by raising some form of error. The same analysis has to be done in the other direction: from the target language to Agama. This is for the case where the Call returns a value. Such value should be \"manipulable\" in Agama code.", "title": "Types compatibility"}, {"location": "agama/execution-rules/#other-considerations", "text": "Engine implementers may consider to offer the ability for developers to supply routines without the need of engine restarts. This aims for an agile development experience.", "title": "Other considerations"}, {"location": "agama/gama-format/", "tags": ["administration", "developer", "agama"], "text": "The .gama file format # In practice, a web flow will make use of a bunch of artifacts, like UI pages, images, stylesheets, and source code. Actually, to solve a real-world problem several flows are needed to be able to keep flexibility and complexity at acceptable levels. Here is where the concept project emerges. A project can be thought of as a container to hold all flows and related assets aimed at solving a particular problem - including metadata of the project itself. The idea of defining a standard way to specify projects brings several benefits: Provide a uniform conceptual scheme for community actors to interchange flows Provide Agama engine implementors common ground for the materialization of flows deployment Serve as reference for developers interested in coding tools such as an Agama IDE Anatomy of a project # The below shows the structure of an Agama project: \u251c\u2500\u2500 code/ \u251c\u2500\u2500 lib/ \u251c\u2500\u2500 web/ \u251c\u2500\u2500 project.json \u251c\u2500\u2500 LICENSE \u2514\u2500\u2500 README.md code directory holds all flows part of the project. Every flow - implemented in Agama language - has to reside in a separate file with extension flow and with file name matching the qualified name of the flow in question. This directory can have nested folders if desired lib may contain source code files in languages other than Agama and binary libraries required by the project, if any. Every engine can make use of the contents of this folder as needed web is expected to hold all UI templates plus required web assets (stylesheets, images, localization strings, etc.) that all flows in this project may use project.json file contains metadata about this project. More on this later README.md file may contain extra documentation in markdown format LICENSE file may contain legal-related information Except for code and web directories, all elements in the file structure above are optional. Note that files in web must follow a directory structure that is consistent with respect to Basepath and RRF directives found in the included flows. Metadata # project.json file is expected to contain metadata about the contents of the project in JSON format. Field Description data type projectName A unique name that will be associated to this project string version Project's version. It is recommended to use semantic versioning format string author A user handle that identifies the author of the project string license A reference to applicable license terms string description string configs Object containing exemplifying configuration properties for flows that may need them. The keys of this field, if any, are qualified flow names already part of the project json object noDirectLaunch An array holding zero or more qualified flow names. This list is used to prevent certain flows to be launched directly from a web browser. It's a security measure to avoid end-users triggering flows at will array All fields are optional and more can be added if desired. Below is an example of a project.json file: { \"projectName\": \"biometric-auth\", \"version\": \"2.0.3\", \"author\": \"avgJoe123\", \"license\": \"apache-2.0\", \"description\": \"Allows users to authenticate via fingerpint and/or iris recognition\", \"configs\": { \"com.acme.bio.IrisScan\": { \"prop1\": \"secret\", \"prop2\": { \"subprop\": [1, 2, 3] } } }, \"noDirectLaunch\": [ \"com.acme.bio.TraitExtractor\" ] } Important Use the configs section wisely: .gama files must not contain real configuration properties because these files may be freely distributed; in practice, configurations hold sensitive data that should not be exposed Sample project # As an example assume you want to deliver these two flows: Flow test Basepath \"hello\" in = { name: \"John\" } RRF \"templates/index.htm\" in Log \"Done!\" Finish \"john_doe\" Flow com.foods.sweet Basepath \"recipes/desserts\" ... choice = RRF \"selection.htm\" list = Call com.foods.RecipeUtils#retrieveIngredients choice.meal ... Here is how the project folder might look like: \u251c\u2500\u2500 code/ \u2502 \u2514\u2500\u2500 test.flow \u2502 \u2514\u2500\u2500 com.foods.sweet.flow \u251c\u2500\u2500 web/ \u2502 \u251c\u2500\u2500 hello/ | | \u2514\u2500\u2500 templates/ \u2502 | \u2514\u2500\u2500 index.htm \u2502 | \u2514\u2500\u2500 js/ \u2502 | \u2514\u2500\u2500 font-awesome.js | \u2514\u2500\u2500 recipes/ \u2502 \u2514\u2500\u2500 desserts/ \u2502 \u2514\u2500\u2500 selection.htm \u2502 \u2514\u2500\u2500 logo.png \u251c\u2500\u2500 lib/ \u2502 \u2514\u2500\u2500 com/ \u2502 \u2514\u2500\u2500 foods/ \u2502 \u2514\u2500\u2500 RecipeUtils.java \u2514\u2500\u2500 project.json .gama file # Dealing with a folder this way can be awkward for sharing and other tasks. Instead, if the project contents are compressed using the ZIP file format, we have what is known as .gama file. Thus, a .gama file is a project archive that can be shared and deployed to an Agama engine. Project deployment # The actual \"deployment\" of an Agama project is an engine-specific detail. Engines must offer mechanisms for administrators and developers to \"install\" .gama files.", "title": "gama format"}, {"location": "agama/gama-format/#the-gama-file-format", "text": "In practice, a web flow will make use of a bunch of artifacts, like UI pages, images, stylesheets, and source code. Actually, to solve a real-world problem several flows are needed to be able to keep flexibility and complexity at acceptable levels. Here is where the concept project emerges. A project can be thought of as a container to hold all flows and related assets aimed at solving a particular problem - including metadata of the project itself. The idea of defining a standard way to specify projects brings several benefits: Provide a uniform conceptual scheme for community actors to interchange flows Provide Agama engine implementors common ground for the materialization of flows deployment Serve as reference for developers interested in coding tools such as an Agama IDE", "title": "The .gama file format"}, {"location": "agama/gama-format/#anatomy-of-a-project", "text": "The below shows the structure of an Agama project: \u251c\u2500\u2500 code/ \u251c\u2500\u2500 lib/ \u251c\u2500\u2500 web/ \u251c\u2500\u2500 project.json \u251c\u2500\u2500 LICENSE \u2514\u2500\u2500 README.md code directory holds all flows part of the project. Every flow - implemented in Agama language - has to reside in a separate file with extension flow and with file name matching the qualified name of the flow in question. This directory can have nested folders if desired lib may contain source code files in languages other than Agama and binary libraries required by the project, if any. Every engine can make use of the contents of this folder as needed web is expected to hold all UI templates plus required web assets (stylesheets, images, localization strings, etc.) that all flows in this project may use project.json file contains metadata about this project. More on this later README.md file may contain extra documentation in markdown format LICENSE file may contain legal-related information Except for code and web directories, all elements in the file structure above are optional. Note that files in web must follow a directory structure that is consistent with respect to Basepath and RRF directives found in the included flows.", "title": "Anatomy of a project"}, {"location": "agama/gama-format/#metadata", "text": "project.json file is expected to contain metadata about the contents of the project in JSON format. Field Description data type projectName A unique name that will be associated to this project string version Project's version. It is recommended to use semantic versioning format string author A user handle that identifies the author of the project string license A reference to applicable license terms string description string configs Object containing exemplifying configuration properties for flows that may need them. The keys of this field, if any, are qualified flow names already part of the project json object noDirectLaunch An array holding zero or more qualified flow names. This list is used to prevent certain flows to be launched directly from a web browser. It's a security measure to avoid end-users triggering flows at will array All fields are optional and more can be added if desired. Below is an example of a project.json file: { \"projectName\": \"biometric-auth\", \"version\": \"2.0.3\", \"author\": \"avgJoe123\", \"license\": \"apache-2.0\", \"description\": \"Allows users to authenticate via fingerpint and/or iris recognition\", \"configs\": { \"com.acme.bio.IrisScan\": { \"prop1\": \"secret\", \"prop2\": { \"subprop\": [1, 2, 3] } } }, \"noDirectLaunch\": [ \"com.acme.bio.TraitExtractor\" ] } Important Use the configs section wisely: .gama files must not contain real configuration properties because these files may be freely distributed; in practice, configurations hold sensitive data that should not be exposed", "title": "Metadata"}, {"location": "agama/gama-format/#sample-project", "text": "As an example assume you want to deliver these two flows: Flow test Basepath \"hello\" in = { name: \"John\" } RRF \"templates/index.htm\" in Log \"Done!\" Finish \"john_doe\" Flow com.foods.sweet Basepath \"recipes/desserts\" ... choice = RRF \"selection.htm\" list = Call com.foods.RecipeUtils#retrieveIngredients choice.meal ... Here is how the project folder might look like: \u251c\u2500\u2500 code/ \u2502 \u2514\u2500\u2500 test.flow \u2502 \u2514\u2500\u2500 com.foods.sweet.flow \u251c\u2500\u2500 web/ \u2502 \u251c\u2500\u2500 hello/ | | \u2514\u2500\u2500 templates/ \u2502 | \u2514\u2500\u2500 index.htm \u2502 | \u2514\u2500\u2500 js/ \u2502 | \u2514\u2500\u2500 font-awesome.js | \u2514\u2500\u2500 recipes/ \u2502 \u2514\u2500\u2500 desserts/ \u2502 \u2514\u2500\u2500 selection.htm \u2502 \u2514\u2500\u2500 logo.png \u251c\u2500\u2500 lib/ \u2502 \u2514\u2500\u2500 com/ \u2502 \u2514\u2500\u2500 foods/ \u2502 \u2514\u2500\u2500 RecipeUtils.java \u2514\u2500\u2500 project.json", "title": "Sample project"}, {"location": "agama/gama-format/#gama-file", "text": "Dealing with a folder this way can be awkward for sharing and other tasks. Instead, if the project contents are compressed using the ZIP file format, we have what is known as .gama file. Thus, a .gama file is a project archive that can be shared and deployed to an Agama engine.", "title": ".gama file"}, {"location": "agama/gama-format/#project-deployment", "text": "The actual \"deployment\" of an Agama project is an engine-specific detail. Engines must offer mechanisms for administrators and developers to \"install\" .gama files.", "title": "Project deployment"}, {"location": "agama/introduction/", "tags": ["administration", "developer", "agama"], "text": "Agama overview # Agama is a framework that consists of: A DSL (domain-specific language) purposedly designed for writing web flows A set of rules that drive the behavior of such flows when they are executed The specification of a file format - known as .gama - useful for sharing Agama flows. Flows have the .flow file extension. Here, a web flow is understood as a process composed by one or more stages, where at each stage an actor - normally a person - provides some kind of data or response by using a web browser or similar client. Throughout the process only a single actor is involved. DSL # About the Agama language is worth to mention that: It helps depicting the structure of web flows in a natural way It is closer to human language than general-purpose programming languages It has a clean, concise, non-distracting syntax It has limited computational power by design, forcing computations to occur in a more formal, general-purpose language like Java, C++, etc. Intrinsic properties of the language include: It follows the imperative paradigm mainly and assumes a traditional sequential execution. It only makes use of a few declarative elements Flows can be treated as functions (reusable routines with well-defined inputs) It provides dedicated contructs for common patterns in web flows like: \"show a page\" and \"retrieve the data user provided in that page\" \"redirect a user to an external site\" and later \"retrieve the data provided at a callback URL\" It supports typical language elements like assignments, conditionals, loops, etc. Find the complete Agama DSL reference here . Behavioral rules of execution # These are aspects that concrete implementations of the framework must adhere to. Rules may include for instance: How and when a flow terminates If and how errors are handled in a flow How flows' assets, i.e. UI pages, images, stylesheets, etc., are organized or laid out How delegation of business logic execution occur in a language other than Agama A \"concrete implementation\" as referred above is known as an engine : a software component capable of running flows written in Agama DSL. More information on execution rules can be found here . .gama file format # Check this page for more information.", "title": "Introduction"}, {"location": "agama/introduction/#agama-overview", "text": "Agama is a framework that consists of: A DSL (domain-specific language) purposedly designed for writing web flows A set of rules that drive the behavior of such flows when they are executed The specification of a file format - known as .gama - useful for sharing Agama flows. Flows have the .flow file extension. Here, a web flow is understood as a process composed by one or more stages, where at each stage an actor - normally a person - provides some kind of data or response by using a web browser or similar client. Throughout the process only a single actor is involved.", "title": "Agama overview"}, {"location": "agama/introduction/#dsl", "text": "About the Agama language is worth to mention that: It helps depicting the structure of web flows in a natural way It is closer to human language than general-purpose programming languages It has a clean, concise, non-distracting syntax It has limited computational power by design, forcing computations to occur in a more formal, general-purpose language like Java, C++, etc. Intrinsic properties of the language include: It follows the imperative paradigm mainly and assumes a traditional sequential execution. It only makes use of a few declarative elements Flows can be treated as functions (reusable routines with well-defined inputs) It provides dedicated contructs for common patterns in web flows like: \"show a page\" and \"retrieve the data user provided in that page\" \"redirect a user to an external site\" and later \"retrieve the data provided at a callback URL\" It supports typical language elements like assignments, conditionals, loops, etc. Find the complete Agama DSL reference here .", "title": "DSL"}, {"location": "agama/introduction/#behavioral-rules-of-execution", "text": "These are aspects that concrete implementations of the framework must adhere to. Rules may include for instance: How and when a flow terminates If and how errors are handled in a flow How flows' assets, i.e. UI pages, images, stylesheets, etc., are organized or laid out How delegation of business logic execution occur in a language other than Agama A \"concrete implementation\" as referred above is known as an engine : a software component capable of running flows written in Agama DSL. More information on execution rules can be found here .", "title": "Behavioral rules of execution"}, {"location": "agama/introduction/#gama-file-format", "text": "Check this page for more information.", "title": ".gama file format"}, {"location": "agama/language-reference/", "tags": ["developer", "agama"], "text": "Agama DSL reference # This document surveys the different constructs of the Agama domain-specific language. Code comments # There is support for single line comments only (no block comments). Use // to start a comment. Comments can start anywhere in a line. Data types # In practice, values would fit into any of: string , boolean , number , list or map . Since routines implemented in other languages can be invoked (more on this later), returned values might not match up exactly with these categories, however this is not too relevant because there is no strict type enforcement in Agama. Literals # Strings # They are surrounded by double quotes. Examples: \"Agama\" , \"blah\" , \"\" (empty string) Backslash can be used to escape chars, like \"Hello\\nGluu\" (line feed), \"Hi\\u0040\" (unicode character) Including double quotes in strings requires unicode escaping, like \"\\u0022\" . Using \"\\\"\" won't work Booleans # Only true or false allowed (notice they are lowercased) Numbers # They are expressed in base 10 only Can be signed or unsigned, with or without decimal: 0 , -1 , 2.0 , 2.3 , -3.000001 , etc. No exponential notation allowed (e.g. 1E-05 ) The following are not valid: .1 , -.1 , +1 . These are their OK equivalents: 0.1 , -0.1 , 1 Null # The \u201cspecial\u201d value null can be used (responsibly) to represent the absence of a value. It is a direct consequence of supporting the integration of other languages in the DSL. Lists # They are finite sequences. Elements are separated by commas Examples: [ 1, 2, 3 ] , [ \"bah!\", \"humbug\" ] , [ ] (empty list) Elements of a list do not have to be of the same type: [ false, [ 0, 1], \"?\" ] is legal but generally discouraged Commas can be surrounded by any combination of spaces and new lines. This is handy when a list takes up some space. This is legal: [ \"no\", \"such\", \"thing\" , \"as\", \"a\", \"stupid\",\"question\"] Maps # They are in essence associative arrays (a.k.a. dictionaries): unordered collections of key/value pairs Example: { brand: \"Ford\", color: null, model: 1963, overhaulsIn: [ 1979, 1999 ] } . This map keys are brand , color , model , and overhaulsIn In literal notation, keys names must follow the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* so these are all valid key names: a , Agama , b_a , a0_0 ; on the contrary, _a , 9 , -a , and \"aha\" are invalid key names As with lists, commas can be surrounded by any combination of spaces and new lines Variables # Variable names follow the pattern: [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* camelCase naming is recommended Variables are not declared, just used freely. Variables are always global in a given flow They can be assigned a value using the equal sign. Example: colors = [ \"red\", \"blue\" ] They can be assigned several times in the same flow Accessing and mutating data in variables # Strings # Suppose x is a string. Individual characters can be accessed by zero-based indexes: x[0] , x[1] , etc. and they are themselves considered strings of size 1 x.length returns the string size (number of characters in it). Strings are not modifiable (neither size nor individual characters can be altered) Lists # Suppose x is a list. Elements can be accessed by zero-based indexes: x[0] , x[1] , etc. Elements of a list can be assigned (and re-assigned) using indexes too. Example: x[2] = false x.length returns the list size. This value can be updated in order to shrink or grow a list (e.g. x.length = 10 ). When extending a list beyond its current length, the \u201cgap\u201d created is filled with null values An attempt to access an index position greater than or equal to the list size returns null (most general-purpose languages would raise a runtime error in this situation) Using expressions for indexing is not allowed, like x[person.age] , x[y[0]] Click here to learn more about access in lists Maps # Suppose x is map. Values can be accessed by using \u201cdot notation\u201d Say x = { brand: \"Ford\", color: null, model: 1963, overhaulsIn: [ 1979, 1999 ] } , then x.model evaluates to 1963 , and x.overhaulsIn[1] evaluates to 1999 Setting the color would be like x.color = \"white\" A new key/value pair can be appended too: x.maxSpeed = 90 Access of an unknown property evaluates to null : x.owner If a key name does not follow the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* an alternative notation must be employed to retrieve or modify the associated value. Click here to learn more Flow structure # A flow written in Agama consists of a header and one or more statements following. Header basics # A header is declarative by nature. It starts with the Flow keyword followed by the qualified name of the flow, e.g. Flow com.acme.FoodSurvey . A qualified name is a sequence of one or more fragments separated by dot ( . ) where a fragment follows the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* . By convention, qualified names shall adhere to a reverse Internet domain name notation. In a header, at minimum, a base path literal string must be provided (in an indented block). This sets the location where flow assets will reside relative to the assets root: Flow com.acme.FoodSurvey Basepath \"mydir\" Here, assets refer to all elements required to build the end-user experience: UI pages, stylesheets, images, etc. The storage of these elements and location of the \"root\" are specific to the concrete Agama engine implementation used. Generally it will resemble a directory structure in a filesystem. Next, flow timeout may be specified. This is the maximum amount of time the end-user can take to fully complete a flow. For instance: Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds An unsigned integer literal value must be specified after the Timeout keyword, if present. The Configs keyword may be used to designate a variable so the flow's properties can be accessed in the code. These properties are usually provided when the flow is created - normally through an administrative tool. This process varies from engine to engine. Often flow properties are used to supply configuration parameters to the flow. As an example, suppose a flow that sends a confirmation e-mail has to be implemented. Properties are a good place to hold the configuration of the outgoing mail server to employ: name, port, authentication credentials, etc. For instance, this is how the configuration properties would be bound to variable conf : Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds Configs conf Inputs # In addition to the above, and optionally too, flows may receive inputs from their callers. Input names can be listed using the Inputs keyword: Flow com.acme.FoodSurvey Basepath \"mydir\" Inputs salutation askGender promptRealName Input names follow the same naming conventions (patterns) of variables and can be treated as such in code. Important Note the difference between properties and inputs. Properties are parameters that callers of the flow should not control or be interested in. On the other hand, inputs are parameters that callers supply explicitly to make the flow exhibit certain behaviors. Check this section to learn how callers can pass values to input parameters of a flow. Flow statements # The statements that make up a flow - body - come after the header and start at column 1, ie. aligned with the Flow keyword: Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds Configs conf Inputs salutation askGender promptRealName x = \"Hi\" y = false ... There are several types of statements: branching, looping, web interaction, etc. They will be regarded in the subsequent sections of this document. Note Agama does not support the concept of subroutines/procedures; this is not needed because functional decomposition is carried out by calling subflows . Logging # Flows can issue small messages (normally used as a form of troubleshooting) that will be appended to a log. Every message can be associated a severity level. Both the log location and available levels are engine specific. To append data to the flows log, use the Log instruction. Examples: Code Message appended Notes Log \"Hi there\" Hi there Log \"Hello\" \"world\" Hello world Log can be passed a variable number of parameters Log \"Hello\" \"world\" 0 false Hello world 0 false Log [1, 2, 3, 4, 5] 1, 2, 3, ...more Lists and maps are not traversed wholly Log \"Hell%% 0 %\" \"o\" \" world\" false Hello world 0 false Placeholders usage Log \"% % % yes\" 1 \"two\" 1 two % yes Log \"3\" \"%\" 0 3 % 0 Log \"@warn Today is Friday %th\" 13 Today is Friday 13th Message logged as warning (if the engine features a \"warning\" level) Log \"@w Today's Armageddon \\u263A\" Today's Armageddon \u263a Message logged as warning (if the engine features a \"w\" level - shortcut method) Check your engine's documentation to learn more about how statements are logged. Conditionals and branching # Keywords When and Otherwise allow to write conditionals. With and , or , is , and is not , logical (boolean) expressions can be built. Examples: car = { brand: \"Ford\", color: null, model: 1963 } When car.color is null car.color = \"pink\" ... Nested conditionals: ... When car.color is \"pink\" When car.brand is \"Ford\" Log \"Weird-looking car\" ... Use of Otherwise : ... When car.color is not null Log \"you have a regular painted car\" ... Otherwise ... Boolean expressions can span several lines: and and or can be at the start or end of a line as long as the whole expression is left-aligned with its corresponding When . Examples: //legal: When day is cloudy When there is hope and there is mercy Log \"let's rock n' roll\" ... When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... //illegal: When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... Notes: Equality is designed to work with null , numbers, strings, and boolean values only. More exactly, a number should only be compared to a number, a string to a string, etc., otherwise the equality test evaluates to false . Comparing a value with itself evaluates to true regardless of type, i.e. car is car , null is null , false is false are all truthy Comparisons are limited to equality ( is ) or inequality ( is not ). For other forms of comparison you can resort foreign routines As expected and has higher priority than or when evaluating expressions. There is no way to group expressions to override the precedence: there are no parenthesis in Agama. Assigning the result of a boolean expression to a variable is not supported. These restrictions are important when writing conditionals Advanced matching # Agama's Match ... to is a construct similar to C/Java switch . Example: car = ... x = ... y = ... // Assume x and y hold numbers z = [ 3.1416, 2.71828 ] Match car.model to x //Code in this block will be executed if car.model is equal to the value of x ... -y //Here we use minus y ... z[0] ... 1.618 //Literal values can be used too for matching ... null ... Otherwise //optional block //Instructions here are executed if there was no match at all Flow finish # Finish is used to terminate a flow's execution. A flow can finish successfully or failed. Examples: Code Meaning Finish true Shorthand for flow finished successfully Finish false Shorthand for failed flow it = { success: true, data: { userId: \"as9233Qz\", ... }} Finish it Flow finished successfully. Some relevant data attached it = { success: false, error: \"User entered a wrong password 3 times\" } Finish it Flow failed. Error description attached Finish \"as9233Qz\" Shorthand for { success: true, data: { userId: \"as9233Qz\" } } it = { nonsense: [ null ] } Finish it.nonsense This causes the flow to crash. Note this is not equivalent to Finish false (which means the flow ended with a negative outcome). Notes: Unless otherwise stated by the concrete engine implementation, a map literal should not be passed directly as argument. This means the following is illegal: Finish { success: false, error: \"spacetime singularity\" } . The examples above list several syntactically valid usages Any statement found after Finish is not reached and thus, not executed If no Finish statement is found in a flow's execution, this will degenerate in flow crash When a flow is finished and was used as subflow (part of the execution of a bigger parent flow), the parent does not terminate. Execution continues at the following instruction that triggered the subflow. More on Trigger later Using data in the Finish directive is an effective way to communicate information to callers (parent flows) Learn more about flows lifecycle here Web interaction # Web interaction constructs bring the most value to Agama. Developers can express the concepts of \u201dredirect a user to an external site and retrieve any data later provided\u201d or \u201cshow a page and grab user data after interaction\u201d using atomic instructions. RFAC # RFAC (stands for Redirect and Fetch at callback ) abstracts the process of redirecting the user's browser to an external site and then collect the data presented later at a designated callback URL. This feature is particularly useful in inbound identity scenarios (e.g. to support social login). Example Details RFAC \"https://login.twitter.com/?blah..&boo=...\" Redirects to the given location. Once the user browser is taken to the callback URL by the external site (twitter.com), the flow continues ignoring any data included map = { twitter: { loginUrl: \"https://...\", ... }, ... } result = RFAC map.twitter.loginUrl Redirects to the given location. Once the user browser is taken to the callback URL by the external site, the data included in the query string or payload is stored in result (a map) for further processing The callback URL varies depending on the engine used. Check your engine's docs. RRF # RRF (stands for Render-Reply-Fetch ) abstracts the process of rendering a UI template, send the produced markup to the browser and grab user-provided data back at the server side. Example Details RRF \"survey.htm\" Renders the template survey.htm (located in this flow's base path) and resulting markup is replied to user's browser. Data submitted by the user is ignored obj = { salutation: \"Hey!\", ... } result = RRF \"survey.htm\" obj Renders the template survey.htm by injecting the data passed in obj and the resulting markup is replied to user's browser. Data submitted by the user is stored in variable result : a map whose keys are named according to the form fields present in survey.htm Notes: The template location must be specified with a string literal only (not a variable) Where and how to store templates is an engine-specific detail as well as the file formats supported. See Assets management . Use map variables - not literal maps - for the second argument of RRF Looping # There are two constructs available for looping in Agama: Repeat and Iterate over . Repeat # Repeat was designed with the concept of attempts/retries in mind: a set of statements are executed, a condition can optionally be supplied in order to abort the loop early, and (optionally too) a block of statements can be executed before the next iteration is started if the condition evaluated to false . A loop is given a maximum number of iterations. Examples: Example Notes month = \"\u2026\" Repeat 3 times max data = RRF \"guess_birthday_month.htm\" //Quit is optional in loops Quit When data.guess is month A loop that runs 3 iterations at most. A page is shown at every iteration. If the value entered by the user matches that of month variable, the loop is aborted earlier x = \u2026 // an integer value month = \"\u2026\" obj = { error: null } Repeat x times max data = RRF \"guess_birthday_month.htm\" obj Quit When data.guess is month obj.error = \"Wrong! try again\" Similar to previous example This time the max no. of iterations is set using a variable When there is a miss a message error is set (which the UI template may potentially use) x = \u2026 // an integer value month = \"\u2026\" obj = { error: null } y = Repeat x times max data = RRF \"guess_birthday_month.htm\" obj Quit When data.guess is month obj.error = \"Wrong! try again\" Log \"Attempt number:\" idx[0] Similar to previous example After the loop finishes, variable y will contain the total number of iterations made to completion. This excludes partial iterations aborted by Quit , thus, y < = x Note the usage of implicit variable idx which holds the current (zero-based) iteration number Iterate over # Iterate over is used to traverse the items of a string, list, or the keys of a map. At every iteration, a variable is set with the current item or key name. As with Repeat , a loop may be aborted earlier, an optional block of statements can be specified after Quit , and the total number of iterations can be stored in a variable. Example Notes seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] Iterate over seasons using sn Log \"There is nothing like\" sn A loop running over a simple list. Every element visited is referenced with variable sn human = { weight: 100, height: 5.9, age: 26 } Iterate over human using attribute Log attribute \"is\" human.$attribute Iterates over the keys of the map printing both the key and its associated value. To learn about the .$ notation see Maps and dot notation seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer\", \"golf\", \"tennis\" ] Iterate over seasons using sn Iterate over sports using sport Log \"There is nothing like playing % in %\" sport sn Nested loops seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer,\" \"golf\", \"tenis\" ] Iterate over seasons using sn y = Iterate over sports using sport Log \"Shall we play % in % ?\" sport sn Quit When sn is \"winter\" Log \"yes!\" Log \"We played % sports in %\" y sn Similar to the previous example. The inner loop is aborted upon a given condition. Note the total number of complete iterations is recorded in y every time the inner loop finishes. seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer,\" \"golf\", \"tenis\" ] Iterate over seasons using sn Iterate over sports using sport Log idx[0] idx[1] Prints iteration numbers: 0 0, 0 1, 0 2, 1 0, 1 1, 1 2, ... 3 2 The index used in idx is 0 for the outermost loop and increases by one at every level of loop nesting Subflows # A flow can Trigger another flow (a.k.a subflow) and grab its response when Finish ed. This feature materializes flow composition and re-use in Agama. Example Notes Trigger jo.jo.PersonalInfoGathering Starts the flow with qualified name jo.jo.PersonalInfoGathering . Returned data is ignored outcome = Trigger jo.jo.PersonalInfoGathering null false Log \"subflow returned with success?\" outcome.success Starts a flow passing parameters (assuming PersonalInfoGathering receives two inputs). outcome will contain the map used when the subflow ended outcome | E = Trigger jo.jo.PersonalInfoGathering null false Similar to the previous example. If for some reason PersonalInfoGathering crashes, variable E will hold a reference to the error for further processing. Otherwise E evaluates to null . The type/structure of E is an engine-specific detail. The variable on the left of the pipe ( | ) can be omitted if the outcome of the flow will not be inspected userPrefs = { otp: \"...\", ... } Match userPrefs.otp to \"e-mail\" flow = \"co.acme.EmailOTP\" \"sms\" flow = \"co.acme.SmsOTP\" Trigger $flow Starts a flow whose qualified name is determined at runtime Input parameters # The values passed after the flow name in Trigger are supplied as input parameters in the order declared by the subflow's Inputs . When not enough values are passed, the unassigned inputs will hold a null value. Unless otherwise stated by the concrete engine implementation, list and map literals should not be passed as arguments to Trigger : Illegal: Trigger subflow { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] Legal: Trigger subflow x car.model list[1] null false -3 \"Sam\" Template overrides # When re-using flows, existing templates may not match the required look-and-feel or layout of the flow that is being built, or may require minor adjustments to fit better the parent's needs. These can be overcome by declaring which templates the developer would like to override for a given subflow call. Example: outcome = Trigger jo.jo.PersonalInfoGathering Override templates \"path/basic.htm\" \"\" \"path2/dir/detail.htm\" \"tmp/mydetail.htm\" Log \"subflow returned with success?\" outcome.success In an indented block using the Override templates keyword, several string literals can be provided. They specify the paths of the (subflows) templates that will be overriden by the parent and the corresponding new paths. In the example above, templates path/basic.htm and path2/dir/detail.htm rendered by flow PersonalInfoGathering (or its subflows) won't be picked from these locations but from the base path of the current (parent) flow using names basic.htm and tmp/mydetail.htm respectively. Usage of empty string denotes reusing the same file name than the original file. Alternatively, every pair of original vs. new path can be specified in a single line for more clarity, like this: outcome = Trigger jo.jo.PersonalInfoGathering Override templates \"path/basic.htm\" \"\" \"path2/dir/detail.htm\" \"tmp/mydetail.htm\" ... Note The new (overriding) templates will be injected with the same data original templates would receive. In other words, this directive only \"modifies\" the first parameter of RRF instructions. Foreign routines # Business logic implemented in languages other than Agama can be re-used by means of the Call instruction. Call plays a key role because Agama code serves fundamentally as a depiction of a flow hiding most of the internal details and low-level computations which are in turn delegated to foreign routines. The syntax of this directive is very general and actual semantics are left to the concrete engine. Roughly, here is how a Call can be structured: ( var_expr? ('|' var_name)? = )? Call alnum(.alnum)* (#alnum)? arg* where: var_name is a variable name , e.g.: x , fooBar , x_0 var_expr is a variable expression, e.g.: x , x.a , x[1].b , etc. alnum is syntactically identical to var_name but does not necessarily refer to an existing variable in the code, for instance, it may describe a path to locate a routine in a library arg is a var_expr or any string , number , boolean , null literal So the below are all syntactically valid invocations: Call apple#pear Call apple#pear \"Hi\" x 16 Call apple.banana#pear \"Hi\" abc 16 foo = Call apple.banana#pear \"Hi\" abc 16 foo | error = Call apple.banana#pear \"Hi\" abc 16 | error = Call apple.banana#pear \"Hi\" abc 16 x[0].ahoy.ahoy foo = Call street fighters true false Again, the semantics are given by the specific engine. Consult your engine documentation for examples. Unless otherwise stated by the concrete engine implementation, list and map literals should not be passed as arguments to method calls directly. This means the following is illegal: Call co.Utils#routine { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] . Advanced and special cases in variable manipulation # Indexing in lists # Accessing/modifying list elements requires providing a numeric index between the brackets, e.g. x[ 0 ] . Note variables can also be used for indexing, like x[ y ] where y is a positive integer or zero. For the below table, assume x = [ \"one\", \"two\", \"three\" ] . x[1] //\"two\" y = 1 x[y] //\"two\" x[\"1\"] //illegal x[ z[0] ] //illegal: variable expressions not allowed for indexes x[obj.property] //illegal: variable expressions not allowed for indexes Maps and dot notation # The regular \u201cdot\u201d notation is limited in the sense it is fairly static: developers have to have prior knowledge about the keys' names, in other words, about the structure of maps and nested submaps, like in person.homeAddress.postalCode . Also, there might be cases where a key name does not fit the required pattern, like in person.street-address or persona.direcci\u00f3n ; even worse, there might be cases where the actual key is only known at runtime. There are ways to overcome this: Example Notes x.\"- wow!\" Access the value associated to the key named -wow! prop = ... x.$prop Access the value associated to the key whose name is contained in the variable prop (that holds a string value). Note actual value of prop may be originated from a Java call or another form of computation propA = ... propB = ... x.$propA.c.\"d\".$propB A mix of notations is valid. For example, if x= { a: { b: 0, c: { c: true, d: { e: null, f: \"hello\" } } } } , propA is equal to \"a\" , and propB to \"f\" , the expression on the left evaluates \"hello\" Usage of .$ requires to supply a variable after the dollar sign: grouped variable expressions are not supported. Thus, it is not possible to achieve something like x.a.c.($map.mykey).f in order to obtain \"hello\" if map = { mykey: \"d\" } . Indexing in maps # For convenience, when a key name \u201clooks like\u201d a positive integer (or zero), e.g. \"2\" , \"10\" , etc., numeric values can directly be used to get/set data in a map: x = { } x.\"1\" = \"golf\" x[1] //retrieves \"golf\" x[2] = \"polo\" //adds the key/value pair \"2\" / \"polo\" Language keywords # The following is a list of reserved words and as such, cannot be used as variable names or maps keys (in literal notation). Keyword Purpose/usage Basepath header declaration Call Java interaction Configs header declaration Finish termination Flow header declaration Inputs header declaration Iterate over loops Log logging Match conditionals Otherwise conditionals Override templates web interaction Quit conditionals and loops Repeat loops RFAC web interaction RRF web interaction seconds header declaration times max loops to conditionals Timeout header declaration Trigger subflow calls using loops When conditionals Operator and is is not or Special literals true false null", "title": "Language reference"}, {"location": "agama/language-reference/#agama-dsl-reference", "text": "This document surveys the different constructs of the Agama domain-specific language.", "title": "Agama DSL reference"}, {"location": "agama/language-reference/#code-comments", "text": "There is support for single line comments only (no block comments). Use // to start a comment. Comments can start anywhere in a line.", "title": "Code comments"}, {"location": "agama/language-reference/#data-types", "text": "In practice, values would fit into any of: string , boolean , number , list or map . Since routines implemented in other languages can be invoked (more on this later), returned values might not match up exactly with these categories, however this is not too relevant because there is no strict type enforcement in Agama.", "title": "Data types"}, {"location": "agama/language-reference/#literals", "text": "", "title": "Literals"}, {"location": "agama/language-reference/#strings", "text": "They are surrounded by double quotes. Examples: \"Agama\" , \"blah\" , \"\" (empty string) Backslash can be used to escape chars, like \"Hello\\nGluu\" (line feed), \"Hi\\u0040\" (unicode character) Including double quotes in strings requires unicode escaping, like \"\\u0022\" . Using \"\\\"\" won't work", "title": "Strings"}, {"location": "agama/language-reference/#booleans", "text": "Only true or false allowed (notice they are lowercased)", "title": "Booleans"}, {"location": "agama/language-reference/#numbers", "text": "They are expressed in base 10 only Can be signed or unsigned, with or without decimal: 0 , -1 , 2.0 , 2.3 , -3.000001 , etc. No exponential notation allowed (e.g. 1E-05 ) The following are not valid: .1 , -.1 , +1 . These are their OK equivalents: 0.1 , -0.1 , 1", "title": "Numbers"}, {"location": "agama/language-reference/#null", "text": "The \u201cspecial\u201d value null can be used (responsibly) to represent the absence of a value. It is a direct consequence of supporting the integration of other languages in the DSL.", "title": "Null"}, {"location": "agama/language-reference/#lists", "text": "They are finite sequences. Elements are separated by commas Examples: [ 1, 2, 3 ] , [ \"bah!\", \"humbug\" ] , [ ] (empty list) Elements of a list do not have to be of the same type: [ false, [ 0, 1], \"?\" ] is legal but generally discouraged Commas can be surrounded by any combination of spaces and new lines. This is handy when a list takes up some space. This is legal: [ \"no\", \"such\", \"thing\" , \"as\", \"a\", \"stupid\",\"question\"]", "title": "Lists"}, {"location": "agama/language-reference/#maps", "text": "They are in essence associative arrays (a.k.a. dictionaries): unordered collections of key/value pairs Example: { brand: \"Ford\", color: null, model: 1963, overhaulsIn: [ 1979, 1999 ] } . This map keys are brand , color , model , and overhaulsIn In literal notation, keys names must follow the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* so these are all valid key names: a , Agama , b_a , a0_0 ; on the contrary, _a , 9 , -a , and \"aha\" are invalid key names As with lists, commas can be surrounded by any combination of spaces and new lines", "title": "Maps"}, {"location": "agama/language-reference/#variables", "text": "Variable names follow the pattern: [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* camelCase naming is recommended Variables are not declared, just used freely. Variables are always global in a given flow They can be assigned a value using the equal sign. Example: colors = [ \"red\", \"blue\" ] They can be assigned several times in the same flow", "title": "Variables"}, {"location": "agama/language-reference/#accessing-and-mutating-data-in-variables", "text": "", "title": "Accessing and mutating data in variables"}, {"location": "agama/language-reference/#strings_1", "text": "Suppose x is a string. Individual characters can be accessed by zero-based indexes: x[0] , x[1] , etc. and they are themselves considered strings of size 1 x.length returns the string size (number of characters in it). Strings are not modifiable (neither size nor individual characters can be altered)", "title": "Strings"}, {"location": "agama/language-reference/#lists_1", "text": "Suppose x is a list. Elements can be accessed by zero-based indexes: x[0] , x[1] , etc. Elements of a list can be assigned (and re-assigned) using indexes too. Example: x[2] = false x.length returns the list size. This value can be updated in order to shrink or grow a list (e.g. x.length = 10 ). When extending a list beyond its current length, the \u201cgap\u201d created is filled with null values An attempt to access an index position greater than or equal to the list size returns null (most general-purpose languages would raise a runtime error in this situation) Using expressions for indexing is not allowed, like x[person.age] , x[y[0]] Click here to learn more about access in lists", "title": "Lists"}, {"location": "agama/language-reference/#maps_1", "text": "Suppose x is map. Values can be accessed by using \u201cdot notation\u201d Say x = { brand: \"Ford\", color: null, model: 1963, overhaulsIn: [ 1979, 1999 ] } , then x.model evaluates to 1963 , and x.overhaulsIn[1] evaluates to 1999 Setting the color would be like x.color = \"white\" A new key/value pair can be appended too: x.maxSpeed = 90 Access of an unknown property evaluates to null : x.owner If a key name does not follow the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* an alternative notation must be employed to retrieve or modify the associated value. Click here to learn more", "title": "Maps"}, {"location": "agama/language-reference/#flow-structure", "text": "A flow written in Agama consists of a header and one or more statements following.", "title": "Flow structure"}, {"location": "agama/language-reference/#header-basics", "text": "A header is declarative by nature. It starts with the Flow keyword followed by the qualified name of the flow, e.g. Flow com.acme.FoodSurvey . A qualified name is a sequence of one or more fragments separated by dot ( . ) where a fragment follows the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* . By convention, qualified names shall adhere to a reverse Internet domain name notation. In a header, at minimum, a base path literal string must be provided (in an indented block). This sets the location where flow assets will reside relative to the assets root: Flow com.acme.FoodSurvey Basepath \"mydir\" Here, assets refer to all elements required to build the end-user experience: UI pages, stylesheets, images, etc. The storage of these elements and location of the \"root\" are specific to the concrete Agama engine implementation used. Generally it will resemble a directory structure in a filesystem. Next, flow timeout may be specified. This is the maximum amount of time the end-user can take to fully complete a flow. For instance: Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds An unsigned integer literal value must be specified after the Timeout keyword, if present. The Configs keyword may be used to designate a variable so the flow's properties can be accessed in the code. These properties are usually provided when the flow is created - normally through an administrative tool. This process varies from engine to engine. Often flow properties are used to supply configuration parameters to the flow. As an example, suppose a flow that sends a confirmation e-mail has to be implemented. Properties are a good place to hold the configuration of the outgoing mail server to employ: name, port, authentication credentials, etc. For instance, this is how the configuration properties would be bound to variable conf : Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds Configs conf", "title": "Header basics"}, {"location": "agama/language-reference/#inputs", "text": "In addition to the above, and optionally too, flows may receive inputs from their callers. Input names can be listed using the Inputs keyword: Flow com.acme.FoodSurvey Basepath \"mydir\" Inputs salutation askGender promptRealName Input names follow the same naming conventions (patterns) of variables and can be treated as such in code. Important Note the difference between properties and inputs. Properties are parameters that callers of the flow should not control or be interested in. On the other hand, inputs are parameters that callers supply explicitly to make the flow exhibit certain behaviors. Check this section to learn how callers can pass values to input parameters of a flow.", "title": "Inputs"}, {"location": "agama/language-reference/#flow-statements", "text": "The statements that make up a flow - body - come after the header and start at column 1, ie. aligned with the Flow keyword: Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds Configs conf Inputs salutation askGender promptRealName x = \"Hi\" y = false ... There are several types of statements: branching, looping, web interaction, etc. They will be regarded in the subsequent sections of this document. Note Agama does not support the concept of subroutines/procedures; this is not needed because functional decomposition is carried out by calling subflows .", "title": "Flow statements"}, {"location": "agama/language-reference/#logging", "text": "Flows can issue small messages (normally used as a form of troubleshooting) that will be appended to a log. Every message can be associated a severity level. Both the log location and available levels are engine specific. To append data to the flows log, use the Log instruction. Examples: Code Message appended Notes Log \"Hi there\" Hi there Log \"Hello\" \"world\" Hello world Log can be passed a variable number of parameters Log \"Hello\" \"world\" 0 false Hello world 0 false Log [1, 2, 3, 4, 5] 1, 2, 3, ...more Lists and maps are not traversed wholly Log \"Hell%% 0 %\" \"o\" \" world\" false Hello world 0 false Placeholders usage Log \"% % % yes\" 1 \"two\" 1 two % yes Log \"3\" \"%\" 0 3 % 0 Log \"@warn Today is Friday %th\" 13 Today is Friday 13th Message logged as warning (if the engine features a \"warning\" level) Log \"@w Today's Armageddon \\u263A\" Today's Armageddon \u263a Message logged as warning (if the engine features a \"w\" level - shortcut method) Check your engine's documentation to learn more about how statements are logged.", "title": "Logging"}, {"location": "agama/language-reference/#conditionals-and-branching", "text": "Keywords When and Otherwise allow to write conditionals. With and , or , is , and is not , logical (boolean) expressions can be built. Examples: car = { brand: \"Ford\", color: null, model: 1963 } When car.color is null car.color = \"pink\" ... Nested conditionals: ... When car.color is \"pink\" When car.brand is \"Ford\" Log \"Weird-looking car\" ... Use of Otherwise : ... When car.color is not null Log \"you have a regular painted car\" ... Otherwise ... Boolean expressions can span several lines: and and or can be at the start or end of a line as long as the whole expression is left-aligned with its corresponding When . Examples: //legal: When day is cloudy When there is hope and there is mercy Log \"let's rock n' roll\" ... When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... //illegal: When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... Notes: Equality is designed to work with null , numbers, strings, and boolean values only. More exactly, a number should only be compared to a number, a string to a string, etc., otherwise the equality test evaluates to false . Comparing a value with itself evaluates to true regardless of type, i.e. car is car , null is null , false is false are all truthy Comparisons are limited to equality ( is ) or inequality ( is not ). For other forms of comparison you can resort foreign routines As expected and has higher priority than or when evaluating expressions. There is no way to group expressions to override the precedence: there are no parenthesis in Agama. Assigning the result of a boolean expression to a variable is not supported. These restrictions are important when writing conditionals", "title": "Conditionals and branching"}, {"location": "agama/language-reference/#advanced-matching", "text": "Agama's Match ... to is a construct similar to C/Java switch . Example: car = ... x = ... y = ... // Assume x and y hold numbers z = [ 3.1416, 2.71828 ] Match car.model to x //Code in this block will be executed if car.model is equal to the value of x ... -y //Here we use minus y ... z[0] ... 1.618 //Literal values can be used too for matching ... null ... Otherwise //optional block //Instructions here are executed if there was no match at all", "title": "Advanced matching"}, {"location": "agama/language-reference/#flow-finish", "text": "Finish is used to terminate a flow's execution. A flow can finish successfully or failed. Examples: Code Meaning Finish true Shorthand for flow finished successfully Finish false Shorthand for failed flow it = { success: true, data: { userId: \"as9233Qz\", ... }} Finish it Flow finished successfully. Some relevant data attached it = { success: false, error: \"User entered a wrong password 3 times\" } Finish it Flow failed. Error description attached Finish \"as9233Qz\" Shorthand for { success: true, data: { userId: \"as9233Qz\" } } it = { nonsense: [ null ] } Finish it.nonsense This causes the flow to crash. Note this is not equivalent to Finish false (which means the flow ended with a negative outcome). Notes: Unless otherwise stated by the concrete engine implementation, a map literal should not be passed directly as argument. This means the following is illegal: Finish { success: false, error: \"spacetime singularity\" } . The examples above list several syntactically valid usages Any statement found after Finish is not reached and thus, not executed If no Finish statement is found in a flow's execution, this will degenerate in flow crash When a flow is finished and was used as subflow (part of the execution of a bigger parent flow), the parent does not terminate. Execution continues at the following instruction that triggered the subflow. More on Trigger later Using data in the Finish directive is an effective way to communicate information to callers (parent flows) Learn more about flows lifecycle here", "title": "Flow finish"}, {"location": "agama/language-reference/#web-interaction", "text": "Web interaction constructs bring the most value to Agama. Developers can express the concepts of \u201dredirect a user to an external site and retrieve any data later provided\u201d or \u201cshow a page and grab user data after interaction\u201d using atomic instructions.", "title": "Web interaction"}, {"location": "agama/language-reference/#rfac", "text": "RFAC (stands for Redirect and Fetch at callback ) abstracts the process of redirecting the user's browser to an external site and then collect the data presented later at a designated callback URL. This feature is particularly useful in inbound identity scenarios (e.g. to support social login). Example Details RFAC \"https://login.twitter.com/?blah..&boo=...\" Redirects to the given location. Once the user browser is taken to the callback URL by the external site (twitter.com), the flow continues ignoring any data included map = { twitter: { loginUrl: \"https://...\", ... }, ... } result = RFAC map.twitter.loginUrl Redirects to the given location. Once the user browser is taken to the callback URL by the external site, the data included in the query string or payload is stored in result (a map) for further processing The callback URL varies depending on the engine used. Check your engine's docs.", "title": "RFAC"}, {"location": "agama/language-reference/#rrf", "text": "RRF (stands for Render-Reply-Fetch ) abstracts the process of rendering a UI template, send the produced markup to the browser and grab user-provided data back at the server side. Example Details RRF \"survey.htm\" Renders the template survey.htm (located in this flow's base path) and resulting markup is replied to user's browser. Data submitted by the user is ignored obj = { salutation: \"Hey!\", ... } result = RRF \"survey.htm\" obj Renders the template survey.htm by injecting the data passed in obj and the resulting markup is replied to user's browser. Data submitted by the user is stored in variable result : a map whose keys are named according to the form fields present in survey.htm Notes: The template location must be specified with a string literal only (not a variable) Where and how to store templates is an engine-specific detail as well as the file formats supported. See Assets management . Use map variables - not literal maps - for the second argument of RRF", "title": "RRF"}, {"location": "agama/language-reference/#looping", "text": "There are two constructs available for looping in Agama: Repeat and Iterate over .", "title": "Looping"}, {"location": "agama/language-reference/#repeat", "text": "Repeat was designed with the concept of attempts/retries in mind: a set of statements are executed, a condition can optionally be supplied in order to abort the loop early, and (optionally too) a block of statements can be executed before the next iteration is started if the condition evaluated to false . A loop is given a maximum number of iterations. Examples: Example Notes month = \"\u2026\" Repeat 3 times max data = RRF \"guess_birthday_month.htm\" //Quit is optional in loops Quit When data.guess is month A loop that runs 3 iterations at most. A page is shown at every iteration. If the value entered by the user matches that of month variable, the loop is aborted earlier x = \u2026 // an integer value month = \"\u2026\" obj = { error: null } Repeat x times max data = RRF \"guess_birthday_month.htm\" obj Quit When data.guess is month obj.error = \"Wrong! try again\" Similar to previous example This time the max no. of iterations is set using a variable When there is a miss a message error is set (which the UI template may potentially use) x = \u2026 // an integer value month = \"\u2026\" obj = { error: null } y = Repeat x times max data = RRF \"guess_birthday_month.htm\" obj Quit When data.guess is month obj.error = \"Wrong! try again\" Log \"Attempt number:\" idx[0] Similar to previous example After the loop finishes, variable y will contain the total number of iterations made to completion. This excludes partial iterations aborted by Quit , thus, y < = x Note the usage of implicit variable idx which holds the current (zero-based) iteration number", "title": "Repeat"}, {"location": "agama/language-reference/#iterate-over", "text": "Iterate over is used to traverse the items of a string, list, or the keys of a map. At every iteration, a variable is set with the current item or key name. As with Repeat , a loop may be aborted earlier, an optional block of statements can be specified after Quit , and the total number of iterations can be stored in a variable. Example Notes seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] Iterate over seasons using sn Log \"There is nothing like\" sn A loop running over a simple list. Every element visited is referenced with variable sn human = { weight: 100, height: 5.9, age: 26 } Iterate over human using attribute Log attribute \"is\" human.$attribute Iterates over the keys of the map printing both the key and its associated value. To learn about the .$ notation see Maps and dot notation seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer\", \"golf\", \"tennis\" ] Iterate over seasons using sn Iterate over sports using sport Log \"There is nothing like playing % in %\" sport sn Nested loops seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer,\" \"golf\", \"tenis\" ] Iterate over seasons using sn y = Iterate over sports using sport Log \"Shall we play % in % ?\" sport sn Quit When sn is \"winter\" Log \"yes!\" Log \"We played % sports in %\" y sn Similar to the previous example. The inner loop is aborted upon a given condition. Note the total number of complete iterations is recorded in y every time the inner loop finishes. seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer,\" \"golf\", \"tenis\" ] Iterate over seasons using sn Iterate over sports using sport Log idx[0] idx[1] Prints iteration numbers: 0 0, 0 1, 0 2, 1 0, 1 1, 1 2, ... 3 2 The index used in idx is 0 for the outermost loop and increases by one at every level of loop nesting", "title": "Iterate over"}, {"location": "agama/language-reference/#subflows", "text": "A flow can Trigger another flow (a.k.a subflow) and grab its response when Finish ed. This feature materializes flow composition and re-use in Agama. Example Notes Trigger jo.jo.PersonalInfoGathering Starts the flow with qualified name jo.jo.PersonalInfoGathering . Returned data is ignored outcome = Trigger jo.jo.PersonalInfoGathering null false Log \"subflow returned with success?\" outcome.success Starts a flow passing parameters (assuming PersonalInfoGathering receives two inputs). outcome will contain the map used when the subflow ended outcome | E = Trigger jo.jo.PersonalInfoGathering null false Similar to the previous example. If for some reason PersonalInfoGathering crashes, variable E will hold a reference to the error for further processing. Otherwise E evaluates to null . The type/structure of E is an engine-specific detail. The variable on the left of the pipe ( | ) can be omitted if the outcome of the flow will not be inspected userPrefs = { otp: \"...\", ... } Match userPrefs.otp to \"e-mail\" flow = \"co.acme.EmailOTP\" \"sms\" flow = \"co.acme.SmsOTP\" Trigger $flow Starts a flow whose qualified name is determined at runtime", "title": "Subflows"}, {"location": "agama/language-reference/#input-parameters", "text": "The values passed after the flow name in Trigger are supplied as input parameters in the order declared by the subflow's Inputs . When not enough values are passed, the unassigned inputs will hold a null value. Unless otherwise stated by the concrete engine implementation, list and map literals should not be passed as arguments to Trigger : Illegal: Trigger subflow { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] Legal: Trigger subflow x car.model list[1] null false -3 \"Sam\"", "title": "Input parameters"}, {"location": "agama/language-reference/#template-overrides", "text": "When re-using flows, existing templates may not match the required look-and-feel or layout of the flow that is being built, or may require minor adjustments to fit better the parent's needs. These can be overcome by declaring which templates the developer would like to override for a given subflow call. Example: outcome = Trigger jo.jo.PersonalInfoGathering Override templates \"path/basic.htm\" \"\" \"path2/dir/detail.htm\" \"tmp/mydetail.htm\" Log \"subflow returned with success?\" outcome.success In an indented block using the Override templates keyword, several string literals can be provided. They specify the paths of the (subflows) templates that will be overriden by the parent and the corresponding new paths. In the example above, templates path/basic.htm and path2/dir/detail.htm rendered by flow PersonalInfoGathering (or its subflows) won't be picked from these locations but from the base path of the current (parent) flow using names basic.htm and tmp/mydetail.htm respectively. Usage of empty string denotes reusing the same file name than the original file. Alternatively, every pair of original vs. new path can be specified in a single line for more clarity, like this: outcome = Trigger jo.jo.PersonalInfoGathering Override templates \"path/basic.htm\" \"\" \"path2/dir/detail.htm\" \"tmp/mydetail.htm\" ... Note The new (overriding) templates will be injected with the same data original templates would receive. In other words, this directive only \"modifies\" the first parameter of RRF instructions.", "title": "Template overrides"}, {"location": "agama/language-reference/#foreign-routines", "text": "Business logic implemented in languages other than Agama can be re-used by means of the Call instruction. Call plays a key role because Agama code serves fundamentally as a depiction of a flow hiding most of the internal details and low-level computations which are in turn delegated to foreign routines. The syntax of this directive is very general and actual semantics are left to the concrete engine. Roughly, here is how a Call can be structured: ( var_expr? ('|' var_name)? = )? Call alnum(.alnum)* (#alnum)? arg* where: var_name is a variable name , e.g.: x , fooBar , x_0 var_expr is a variable expression, e.g.: x , x.a , x[1].b , etc. alnum is syntactically identical to var_name but does not necessarily refer to an existing variable in the code, for instance, it may describe a path to locate a routine in a library arg is a var_expr or any string , number , boolean , null literal So the below are all syntactically valid invocations: Call apple#pear Call apple#pear \"Hi\" x 16 Call apple.banana#pear \"Hi\" abc 16 foo = Call apple.banana#pear \"Hi\" abc 16 foo | error = Call apple.banana#pear \"Hi\" abc 16 | error = Call apple.banana#pear \"Hi\" abc 16 x[0].ahoy.ahoy foo = Call street fighters true false Again, the semantics are given by the specific engine. Consult your engine documentation for examples. Unless otherwise stated by the concrete engine implementation, list and map literals should not be passed as arguments to method calls directly. This means the following is illegal: Call co.Utils#routine { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] .", "title": "Foreign routines"}, {"location": "agama/language-reference/#advanced-and-special-cases-in-variable-manipulation", "text": "", "title": "Advanced and special cases in variable manipulation"}, {"location": "agama/language-reference/#indexing-in-lists", "text": "Accessing/modifying list elements requires providing a numeric index between the brackets, e.g. x[ 0 ] . Note variables can also be used for indexing, like x[ y ] where y is a positive integer or zero. For the below table, assume x = [ \"one\", \"two\", \"three\" ] . x[1] //\"two\" y = 1 x[y] //\"two\" x[\"1\"] //illegal x[ z[0] ] //illegal: variable expressions not allowed for indexes x[obj.property] //illegal: variable expressions not allowed for indexes", "title": "Indexing in lists"}, {"location": "agama/language-reference/#maps-and-dot-notation", "text": "The regular \u201cdot\u201d notation is limited in the sense it is fairly static: developers have to have prior knowledge about the keys' names, in other words, about the structure of maps and nested submaps, like in person.homeAddress.postalCode . Also, there might be cases where a key name does not fit the required pattern, like in person.street-address or persona.direcci\u00f3n ; even worse, there might be cases where the actual key is only known at runtime. There are ways to overcome this: Example Notes x.\"- wow!\" Access the value associated to the key named -wow! prop = ... x.$prop Access the value associated to the key whose name is contained in the variable prop (that holds a string value). Note actual value of prop may be originated from a Java call or another form of computation propA = ... propB = ... x.$propA.c.\"d\".$propB A mix of notations is valid. For example, if x= { a: { b: 0, c: { c: true, d: { e: null, f: \"hello\" } } } } , propA is equal to \"a\" , and propB to \"f\" , the expression on the left evaluates \"hello\" Usage of .$ requires to supply a variable after the dollar sign: grouped variable expressions are not supported. Thus, it is not possible to achieve something like x.a.c.($map.mykey).f in order to obtain \"hello\" if map = { mykey: \"d\" } .", "title": "Maps and dot notation"}, {"location": "agama/language-reference/#indexing-in-maps", "text": "For convenience, when a key name \u201clooks like\u201d a positive integer (or zero), e.g. \"2\" , \"10\" , etc., numeric values can directly be used to get/set data in a map: x = { } x.\"1\" = \"golf\" x[1] //retrieves \"golf\" x[2] = \"polo\" //adds the key/value pair \"2\" / \"polo\"", "title": "Indexing in maps"}, {"location": "agama/language-reference/#language-keywords", "text": "The following is a list of reserved words and as such, cannot be used as variable names or maps keys (in literal notation). Keyword Purpose/usage Basepath header declaration Call Java interaction Configs header declaration Finish termination Flow header declaration Inputs header declaration Iterate over loops Log logging Match conditionals Otherwise conditionals Override templates web interaction Quit conditionals and loops Repeat loops RFAC web interaction RRF web interaction seconds header declaration times max loops to conditionals Timeout header declaration Trigger subflow calls using loops When conditionals Operator and is is not or Special literals true false null", "title": "Language keywords"}, {"location": "casa/user-guide/", "tags": ["Casa", "user guide"], "text": "Jans Casa User Guide # Jans Casa (\"Casa\") is a self-service web portal for managing account security preferences. The primary use-case for Casa is self-service 2FA, but other use cases and functionalities can be supported via Casa plugins. The options displayed in the user portal will always depend upon which settings have been enabled by the administrator. Sign in for the first time # To log in to Casa, navigate to https://<yourdomain>/jans-casa . If you have an existing account, sign in with your standard username and password. Credential Dashboard # The credential dashboard displays widgets for each type of supported 2FA credential (e.g. U2F keys, OTP apps, etc.). Each widget includes summary details of enrolled credentials and a button to add / change credentials. To manage existing credentials and enroll new credentials, click the Manage button: 2FA overview # Turn 2FA on/off # After the minimum number of credentials have been enrolled (as specified by the system admin), 2FA can be turned on by clicking the switch in the Second Factor Authentication widget: If the switch is not visible, your administrator may have configured the system so that 2FA is turned on automatically when enough credentials are available. When prompted for 2FA, the specific credential to be prompted first varies depending on the priority of credentials established by the administrator and the user's preferred method, if set. If at any time the credential prompted is unavailable, you have the option to present any other previously enrolled 2FA credential type. To turn off 2FA, click again the switch. 2FA settings and trusted devices # If enabled by the system administrator, you can set your own policy for when 2FA is enforced. To manage your settings, after enrolling credentials and turning on 2FA, click the Manage your 2FA settings button in the Preferred Authentication Mechanism widget. By default, you will be able to choose from a few 2FA policies: Always (upon every login attempt) If the location (e.g. city) detected in the login attempt is unrecognized If the device used to login is unrecognized If you opt for 2FA based on location, device, or both, a new widget will appear to display your trusted devices. 2FA best practices # Depending on the device used to get access, some credentials are more convenient to use than others. For instance, security keys may not be compatible with mobile phones or certain browsers. To reduce the chance of account lockout , enroll at least two different types of 2FA credentials -- e.g. one security key and one OTP app; or one OTP app and one SMS phone number, etc. This way, regardless which device you're using to access a protected resource, you will have a usable option for passing strong authentication. 2FA credential details & enrollment # The details page provides additional information about each enrolled credential, for instance its name and date of enrollment. Nicknames can be edited, credentials can be deleted and new credentials can be enrolled and nicknamed. Depending on administrator configurations, some of the below sections may nor may not be available, or sections not listed here may appear. Warning When a credential is deleted, it cannot be recovered. Deleting credentials may result in 2FA being turned off. FIDO 2 security keys # To add a new FIDO 2 credential, navigate to 2FA credentials > Security Keys . Insert the fido key and click Ready . Casa will prompt to press the button on the key. Add a nickname and click Add . Once added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device. Super Gluu Devices # To add a new Super Gluu device, navigate to 2FA credentials > Super Gluu Devices . The Super Gluu enrollment QR code will pop up. Scan it in the Super Gluu app and approve the enrollment. Add a nickname for the device and click Add . Once it's added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device. OTP Tokens # To add a new OTP token, navigate to 2FA credentials > OTP Tokens . To add a soft OTP token, choose the Soft token option and follow the same steps as Super Gluu . For a hard token, choose the Hard Token option. Add the key associated with the device and the 6 digit code. Add a nickname for the device and click Add . Once it's added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device. Mobile Phone Numbers # To add a new mobile phone number for one-time passcodes, navigate to 2FA credentials > Mobile Phone Numbers . Enter a phone number and click 'Send SMS' to get the passcode. Enter the code received, nickname the mobile number, and click Add . Once it's added, the new mobile number will appear in a list on the same page. Click the pencil to edit the mobile number's nickname or the trashcan to delete the mobile number. Password Reset # If enabled by the system administrator, Casa can also be used to change your password. Navigate to the Password Reset widget. Enter your current and new passwords, then click Change password . Consent Management # If the administrator has enabled the Consent Management plugin, it will appear in the navigation menu for all users. New entries are added automatically whenever the user is prompted for, and authorizes the release of their personal data to an application accessed using their Janssen Server account. Revoking consent # When a previously granted consent decision is revoked, the user will be re-prompted to authorize release of their data if/when they attempt to access the application again.", "title": "User Guide"}, {"location": "casa/user-guide/#jans-casa-user-guide", "text": "Jans Casa (\"Casa\") is a self-service web portal for managing account security preferences. The primary use-case for Casa is self-service 2FA, but other use cases and functionalities can be supported via Casa plugins. The options displayed in the user portal will always depend upon which settings have been enabled by the administrator.", "title": "Jans Casa User Guide"}, {"location": "casa/user-guide/#sign-in-for-the-first-time", "text": "To log in to Casa, navigate to https://<yourdomain>/jans-casa . If you have an existing account, sign in with your standard username and password.", "title": "Sign in for the first time"}, {"location": "casa/user-guide/#credential-dashboard", "text": "The credential dashboard displays widgets for each type of supported 2FA credential (e.g. U2F keys, OTP apps, etc.). Each widget includes summary details of enrolled credentials and a button to add / change credentials. To manage existing credentials and enroll new credentials, click the Manage button:", "title": "Credential Dashboard"}, {"location": "casa/user-guide/#2fa-overview", "text": "", "title": "2FA overview"}, {"location": "casa/user-guide/#turn-2fa-onoff", "text": "After the minimum number of credentials have been enrolled (as specified by the system admin), 2FA can be turned on by clicking the switch in the Second Factor Authentication widget: If the switch is not visible, your administrator may have configured the system so that 2FA is turned on automatically when enough credentials are available. When prompted for 2FA, the specific credential to be prompted first varies depending on the priority of credentials established by the administrator and the user's preferred method, if set. If at any time the credential prompted is unavailable, you have the option to present any other previously enrolled 2FA credential type. To turn off 2FA, click again the switch.", "title": "Turn 2FA on/off"}, {"location": "casa/user-guide/#2fa-settings-and-trusted-devices", "text": "If enabled by the system administrator, you can set your own policy for when 2FA is enforced. To manage your settings, after enrolling credentials and turning on 2FA, click the Manage your 2FA settings button in the Preferred Authentication Mechanism widget. By default, you will be able to choose from a few 2FA policies: Always (upon every login attempt) If the location (e.g. city) detected in the login attempt is unrecognized If the device used to login is unrecognized If you opt for 2FA based on location, device, or both, a new widget will appear to display your trusted devices.", "title": "2FA settings and trusted devices"}, {"location": "casa/user-guide/#2fa-best-practices", "text": "Depending on the device used to get access, some credentials are more convenient to use than others. For instance, security keys may not be compatible with mobile phones or certain browsers. To reduce the chance of account lockout , enroll at least two different types of 2FA credentials -- e.g. one security key and one OTP app; or one OTP app and one SMS phone number, etc. This way, regardless which device you're using to access a protected resource, you will have a usable option for passing strong authentication.", "title": "2FA best practices"}, {"location": "casa/user-guide/#2fa-credential-details-enrollment", "text": "The details page provides additional information about each enrolled credential, for instance its name and date of enrollment. Nicknames can be edited, credentials can be deleted and new credentials can be enrolled and nicknamed. Depending on administrator configurations, some of the below sections may nor may not be available, or sections not listed here may appear. Warning When a credential is deleted, it cannot be recovered. Deleting credentials may result in 2FA being turned off.", "title": "2FA credential details & enrollment"}, {"location": "casa/user-guide/#fido-2-security-keys", "text": "To add a new FIDO 2 credential, navigate to 2FA credentials > Security Keys . Insert the fido key and click Ready . Casa will prompt to press the button on the key. Add a nickname and click Add . Once added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device.", "title": "FIDO 2 security keys"}, {"location": "casa/user-guide/#super-gluu-devices", "text": "To add a new Super Gluu device, navigate to 2FA credentials > Super Gluu Devices . The Super Gluu enrollment QR code will pop up. Scan it in the Super Gluu app and approve the enrollment. Add a nickname for the device and click Add . Once it's added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device.", "title": "Super Gluu Devices"}, {"location": "casa/user-guide/#otp-tokens", "text": "To add a new OTP token, navigate to 2FA credentials > OTP Tokens . To add a soft OTP token, choose the Soft token option and follow the same steps as Super Gluu . For a hard token, choose the Hard Token option. Add the key associated with the device and the 6 digit code. Add a nickname for the device and click Add . Once it's added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device.", "title": "OTP Tokens"}, {"location": "casa/user-guide/#mobile-phone-numbers", "text": "To add a new mobile phone number for one-time passcodes, navigate to 2FA credentials > Mobile Phone Numbers . Enter a phone number and click 'Send SMS' to get the passcode. Enter the code received, nickname the mobile number, and click Add . Once it's added, the new mobile number will appear in a list on the same page. Click the pencil to edit the mobile number's nickname or the trashcan to delete the mobile number.", "title": "Mobile Phone Numbers"}, {"location": "casa/user-guide/#password-reset", "text": "If enabled by the system administrator, Casa can also be used to change your password. Navigate to the Password Reset widget. Enter your current and new passwords, then click Change password .", "title": "Password Reset"}, {"location": "casa/user-guide/#consent-management", "text": "If the administrator has enabled the Consent Management plugin, it will appear in the navigation menu for all users. New entries are added automatically whenever the user is prompted for, and authorizes the release of their personal data to an application accessed using their Janssen Server account.", "title": "Consent Management"}, {"location": "casa/user-guide/#revoking-consent", "text": "When a previously granted consent decision is revoked, the user will be re-prompted to authorize release of their data if/when they attempt to access the application again.", "title": "Revoking consent"}, {"location": "casa/administration/2fa-basics/", "tags": ["Casa", "2FA", "two-factor"], "text": "About Two-Factor Authentication (2FA) # Note You can tailor different aspects of 2FA behavior in Casa using the plugin developed for this purpose. Availability # By default, strong (two-factor) authentication will be available to users of Casa once they have added at least two credentials. By requiring users to register two strong credentials, the number of account lockouts that require admin intervention will be greatly reduced. If one credential is lost, there will be at least one fallback mechanism available. Avoiding user lockout is important because it prevents a serious burden for IT administrators. There is no limit to the number of credentials a user can enroll, and credentials do not need to be of the same type: any combination is valid. Supported types of 2FA # Users will only be able to add credentials with a type matching one of the already enabled authentication methods in the admin console . Other methods may be supported via plugins . Resetting a user's 2FA availability # In the event a user loses access to his account, admins can revert the user's authentication method to \"password only\" by following the steps shown in the troubleshooting guide . Associated \"strength\" of credentials # When authenticating, a user with 2FA turned on, will be challenged to present the credential having the \"strongest\" authentication method (from his already available enrolled credentials). The relative strength of methods can be assigned in the authentication methods screen of the admin console. Forcing users to enroll a specific credential before 2FA is available # To further reduce the likelihood of lockouts, you can force users to initially enroll, for instance, one OTP credential before any other. OTP credentials are generally more accessible than their counterparts (like Fido) since they normally don't demand special conditions from the device used to access, like having a USB port. To do so, add a property named 2fa_requisite to the configuration of the Agama flow that backs the given authentication method, and assign true as its value. You can do this via TUI . Note this mechanism is applicable for the out-of-the box authentication methods supported by Casa. For other methods contributed via plugins, consult their respective documentation. You can flag more than one method as requisite. In this case users will be encouraged to enroll one credential associated to any of the flagged methods. If a user attempts to delete their only available credential matching the requisite method, a prompt will appear warning that doing so will disable 2FA, that is, resetting to password authentication. If you are a developer coding a plugin that adds an authentication method, you can make the method a requisite by properly implementing method mayBe2faActivationRequisite part of interface AuthnMethod . Enrolling credentials upon registration or first login # If the previous scenario is not enough for your needs, you can force users to enroll credentials and turn 2FA on before the first usage of the application. This can be done in two ways: Creating a new Agama project that takes charge of credentials enrollment and then reuses the flows bundled with the standard Agama project which performs the actual authentication. Learn more about this in the developer pages Making enrollments occur at registration time (through the application you use for this purpose)", "title": "About 2FA"}, {"location": "casa/administration/2fa-basics/#about-two-factor-authentication-2fa", "text": "Note You can tailor different aspects of 2FA behavior in Casa using the plugin developed for this purpose.", "title": "About Two-Factor Authentication (2FA)"}, {"location": "casa/administration/2fa-basics/#availability", "text": "By default, strong (two-factor) authentication will be available to users of Casa once they have added at least two credentials. By requiring users to register two strong credentials, the number of account lockouts that require admin intervention will be greatly reduced. If one credential is lost, there will be at least one fallback mechanism available. Avoiding user lockout is important because it prevents a serious burden for IT administrators. There is no limit to the number of credentials a user can enroll, and credentials do not need to be of the same type: any combination is valid.", "title": "Availability"}, {"location": "casa/administration/2fa-basics/#supported-types-of-2fa", "text": "Users will only be able to add credentials with a type matching one of the already enabled authentication methods in the admin console . Other methods may be supported via plugins .", "title": "Supported types of 2FA"}, {"location": "casa/administration/2fa-basics/#resetting-a-users-2fa-availability", "text": "In the event a user loses access to his account, admins can revert the user's authentication method to \"password only\" by following the steps shown in the troubleshooting guide .", "title": "Resetting a user's 2FA availability"}, {"location": "casa/administration/2fa-basics/#associated-strength-of-credentials", "text": "When authenticating, a user with 2FA turned on, will be challenged to present the credential having the \"strongest\" authentication method (from his already available enrolled credentials). The relative strength of methods can be assigned in the authentication methods screen of the admin console.", "title": "Associated \"strength\" of credentials"}, {"location": "casa/administration/2fa-basics/#forcing-users-to-enroll-a-specific-credential-before-2fa-is-available", "text": "To further reduce the likelihood of lockouts, you can force users to initially enroll, for instance, one OTP credential before any other. OTP credentials are generally more accessible than their counterparts (like Fido) since they normally don't demand special conditions from the device used to access, like having a USB port. To do so, add a property named 2fa_requisite to the configuration of the Agama flow that backs the given authentication method, and assign true as its value. You can do this via TUI . Note this mechanism is applicable for the out-of-the box authentication methods supported by Casa. For other methods contributed via plugins, consult their respective documentation. You can flag more than one method as requisite. In this case users will be encouraged to enroll one credential associated to any of the flagged methods. If a user attempts to delete their only available credential matching the requisite method, a prompt will appear warning that doing so will disable 2FA, that is, resetting to password authentication. If you are a developer coding a plugin that adds an authentication method, you can make the method a requisite by properly implementing method mayBe2faActivationRequisite part of interface AuthnMethod .", "title": "Forcing users to enroll a specific credential before 2FA is available"}, {"location": "casa/administration/2fa-basics/#enrolling-credentials-upon-registration-or-first-login", "text": "If the previous scenario is not enough for your needs, you can force users to enroll credentials and turn 2FA on before the first usage of the application. This can be done in two ways: Creating a new Agama project that takes charge of credentials enrollment and then reuses the flows bundled with the standard Agama project which performs the actual authentication. Learn more about this in the developer pages Making enrollments occur at registration time (through the application you use for this purpose)", "title": "Enrolling credentials upon registration or first login"}, {"location": "casa/administration/admin-console/", "tags": ["Casa", "administration", "admin console"], "text": "Admin Console # This document reviews the available options for configuring Casa. All configuration changes applied via the admin console take effect immediately with no restart or other actions required. Authentication methods # Here you can choose the type of 2FA credentials you want to support in Casa. Every authentication method is represented by a widget you can enable or disable. Administrators can arrange widgets according to perceived \"strength\" order, that is, methods considered safer than others can be placed on top of the list. This ordering has two practical consequences: When a user has 2FA turned on, he will be prompted safer methods first when authenticating. However, if the user has already chosen a preferred method in his dashboard, the prompt favors his choice In the user's dashboard enrolling options are presented following the defined order Widgets shown vary according to plugins installed. In a fresh installation, the following are supported out-of-the-box: OTP via SMS TOTP/HOTP: mobile OTP apps and hard tokens (cards, key fobs, dongles, etc.) FIDO devices Super Gluu for push notifications To add more authentication methods, please check the developer guide . Pass reset config # An admin can give users the ability to reset their password from inside Casa. To enable the password reset functionality, navigate to Pass reset config and click the toggle to ON . Reset to password authentication # If a user is locked out for any reason (e.g. lost device, etc.), an admin can navigate to Reset to password authentication in the admin console to turn 2FA off for them. Type the username (or part of) in the text field and then press search. Once the user has been located, click the checkbox and click the Reset to password button. The row will become disabled, and a success message will be displayed. Branding # Most organizations will want to custom brand Jans Casa. Follow our guide to learn more about custom branding Casa . Plugins # Through an easy-to-use screen, administrators can easily manage installed plugins and add new ones. Logging # Application logs are useful sources of information to diagnose anomalies and understand possible causes of errors if presented. Casa uses the Log4J2 logging framework for this. The severity level for logs can be modified at runtime and requires no restart. For more information about logging, check the FAQ entry . CORS domains # If a given plugin exposes one or more web services that are to be consumed from within a web browser, you can whitelist the origin domains from which consumption can takes place. 2FA settings # Warning This feature is only if the 2FA settings plugin is installed In the 2FA settings screen, an admin can: Specify the minimum number of credentials a user must enroll before 2FA can be turned on Determine whether 2FA should be automatically enabled upon credential enrollment Whether users can turn 2FA on and off their own Whether users can choose a preferred authentication method Choose from a few predefined policies for when 2FA should be prompted. To reduce the chance of lockouts, we recommend setting a minimum of two (2) strong credentials. Predefined 2FA policy options include: Enforce strong authentication for every login attempt Prompt for 2FA when users' location is unrecognized Prompt for 2FA when users' device is unrecognized Allow the user to set their own strong authentication policy The default policy is to enforce 2FA for every login attempt. If the admin opts to allow users to manager their own policy, a new widget will appear in the user-facing dashboard as described in the user guide . In addition, the plugin exposes an API to programmatically manipulate these settings.", "title": "Admin console"}, {"location": "casa/administration/admin-console/#admin-console", "text": "This document reviews the available options for configuring Casa. All configuration changes applied via the admin console take effect immediately with no restart or other actions required.", "title": "Admin Console"}, {"location": "casa/administration/admin-console/#authentication-methods", "text": "Here you can choose the type of 2FA credentials you want to support in Casa. Every authentication method is represented by a widget you can enable or disable. Administrators can arrange widgets according to perceived \"strength\" order, that is, methods considered safer than others can be placed on top of the list. This ordering has two practical consequences: When a user has 2FA turned on, he will be prompted safer methods first when authenticating. However, if the user has already chosen a preferred method in his dashboard, the prompt favors his choice In the user's dashboard enrolling options are presented following the defined order Widgets shown vary according to plugins installed. In a fresh installation, the following are supported out-of-the-box: OTP via SMS TOTP/HOTP: mobile OTP apps and hard tokens (cards, key fobs, dongles, etc.) FIDO devices Super Gluu for push notifications To add more authentication methods, please check the developer guide .", "title": "Authentication methods"}, {"location": "casa/administration/admin-console/#pass-reset-config", "text": "An admin can give users the ability to reset their password from inside Casa. To enable the password reset functionality, navigate to Pass reset config and click the toggle to ON .", "title": "Pass reset config"}, {"location": "casa/administration/admin-console/#reset-to-password-authentication", "text": "If a user is locked out for any reason (e.g. lost device, etc.), an admin can navigate to Reset to password authentication in the admin console to turn 2FA off for them. Type the username (or part of) in the text field and then press search. Once the user has been located, click the checkbox and click the Reset to password button. The row will become disabled, and a success message will be displayed.", "title": "Reset to password authentication"}, {"location": "casa/administration/admin-console/#branding", "text": "Most organizations will want to custom brand Jans Casa. Follow our guide to learn more about custom branding Casa .", "title": "Branding"}, {"location": "casa/administration/admin-console/#plugins", "text": "Through an easy-to-use screen, administrators can easily manage installed plugins and add new ones.", "title": "Plugins"}, {"location": "casa/administration/admin-console/#logging", "text": "Application logs are useful sources of information to diagnose anomalies and understand possible causes of errors if presented. Casa uses the Log4J2 logging framework for this. The severity level for logs can be modified at runtime and requires no restart. For more information about logging, check the FAQ entry .", "title": "Logging"}, {"location": "casa/administration/admin-console/#cors-domains", "text": "If a given plugin exposes one or more web services that are to be consumed from within a web browser, you can whitelist the origin domains from which consumption can takes place.", "title": "CORS domains"}, {"location": "casa/administration/admin-console/#2fa-settings", "text": "Warning This feature is only if the 2FA settings plugin is installed In the 2FA settings screen, an admin can: Specify the minimum number of credentials a user must enroll before 2FA can be turned on Determine whether 2FA should be automatically enabled upon credential enrollment Whether users can turn 2FA on and off their own Whether users can choose a preferred authentication method Choose from a few predefined policies for when 2FA should be prompted. To reduce the chance of lockouts, we recommend setting a minimum of two (2) strong credentials. Predefined 2FA policy options include: Enforce strong authentication for every login attempt Prompt for 2FA when users' location is unrecognized Prompt for 2FA when users' device is unrecognized Allow the user to set their own strong authentication policy The default policy is to enforce 2FA for every login attempt. If the admin opts to allow users to manager their own policy, a new widget will appear in the user-facing dashboard as described in the user guide . In addition, the plugin exposes an API to programmatically manipulate these settings.", "title": "2FA settings"}, {"location": "casa/administration/change-context-path/", "tags": ["Casa", "administration", "context path"], "text": "Change Application Context Path # To publish the application at a location other than /casa , do the following: Log into Janssen Server using SSH Edit tag <Set name=\"contextPath\"> in file /opt/jans/jetty/jans-casa/webapps/jans-casa.xml with the new path you want to use. For example, if you chose /creds , you would do the following: <Set name=\"contextPath\">/creds</Set> Edit tag <Set name=\"contextPath\"> in file /opt/jans/jetty/jans-casa/webapps/jans-casa_web_resources.xml appropriately with the new path you want to use. Adjust Apache's .conf file: Locate the https_jans.conf file. The exact location will vary depending on your distribution. In Ubuntu, for example, you can find it at /etc/apache2/sites-available Find the section starting with <Location /casa> and replace the 2 occurrences of casa with the path of your choice. Do not use trailing slashes Add the following directive: Redirect /casa /<new-context-path> before all <Location> and <Proxy> sections Adjust custom script settings: adjust the \"supergluu_app_id\" property of the casa custom script accordingly Wait for around 1 minute (so the server picks the script changes), then restart Casa and Apache services. Use this page as a guide The application should be accessible now at the new URL.", "title": "URL path customization"}, {"location": "casa/administration/change-context-path/#change-application-context-path", "text": "To publish the application at a location other than /casa , do the following: Log into Janssen Server using SSH Edit tag <Set name=\"contextPath\"> in file /opt/jans/jetty/jans-casa/webapps/jans-casa.xml with the new path you want to use. For example, if you chose /creds , you would do the following: <Set name=\"contextPath\">/creds</Set> Edit tag <Set name=\"contextPath\"> in file /opt/jans/jetty/jans-casa/webapps/jans-casa_web_resources.xml appropriately with the new path you want to use. Adjust Apache's .conf file: Locate the https_jans.conf file. The exact location will vary depending on your distribution. In Ubuntu, for example, you can find it at /etc/apache2/sites-available Find the section starting with <Location /casa> and replace the 2 occurrences of casa with the path of your choice. Do not use trailing slashes Add the following directive: Redirect /casa /<new-context-path> before all <Location> and <Proxy> sections Adjust custom script settings: adjust the \"supergluu_app_id\" property of the casa custom script accordingly Wait for around 1 minute (so the server picks the script changes), then restart Casa and Apache services. Use this page as a guide The application should be accessible now at the new URL.", "title": "Change Application Context Path"}, {"location": "casa/administration/custom-branding/", "tags": ["Casa", "administration", "custom branding", "brand"], "text": "Custom branding # In Casa, administrators can supply their own logo and favicon to better match the organization's look and feel. If you want to apply more advanced customizations, adding the custom branding plugin is the way to go. Note This page covers customizations available through the custom branding plugin . It is assumed you have already added it to your Casa installation. The plugin allows administrators to easily alter the appearance of Casa. There are two ways to tweak the design: a quick point-and-click set of changes that you can preview immediately, or a lower-level approach that allows you to supply your own CSS file and images (this is known as external assets directory usage). Quick design customization # Click on Custom branding in the admin console, and choose Upload images and pick colors . With this branding alternative, you can apply some visual changes effortlessly with zero CSS coding. You can: Supply your company logo and favicon Choose the background color for the page header Choose button colors Edit the footer text Once you supply your files, color values, and footer text, click on Save and see the changes take immediately by navigating to a different page or opening a new browser tab. Repeat the process till you get the combination that best matches your organization's look and feel. With \"Primary buttons\" we refer to the vast majority of buttons that trigger some action such as saving, updating or accepting - whether in the user pages or the admin UI itself. \"Cancel\" covers undo, close or cancel, while \"Misc\" is for anything not fitting any of the previous usages. You can choose \"Use defaults\" if you feel comfortable with the Bootstrap-like colors offered in Jans Casa. Using the external assets directory # Note Intermediate-level knowledge of CSS is required for this task. Background # Casa's UI design is driven by one CSS stylesheet and a few images. Specifically, Casa leverages the following UI frameworks: ZK Tachyons 4.11 Font Awesome 5.12 Particularly, ZK's default theme CSS file was disabled to offer a higher degree of flexibility in design. This enables Tachyons to claim control over style rules applied to HTML markup. External assets directory # In the /opt/jans/jetty/casa/static folder, you can place your own version of the main stylesheet and images Casa uses. No other stylesheet should be overriden. To start, log in to the Janssen Server and do the following: cd /opt/jans/jetty/jans-casa/static jar -xf ../webapps/jans-casa.war images styles/gluu/style.css This will copy the files you can edit later (these are the original versions provided out of the box in Casa). If you place additional files in this directory, ensure ownership is set to recursive. For instance, you can: $ chown -R jetty:jetty /opt/jans/jetty/jans-casa/static/ Enable and apply your customizations # In the admin console, navigate to Custom branding > Use Casa external assets directory . From that point on, your installation is reading relevant files from the static directory. Note In CSS, the rules' order of appearance is important. For all Casa pages, style.css is loaded first, then tachyons.css. This means rules for Tachyons have higher priority unless !important is used. The main stylesheet ( style.css ) is located at /opt/jans/jetty/jans-casa/static/styles/gluu if you have followed the instructions above. Here are some tips for applying your customizations: Get acquainted with functional CSS. This is the approach followed in Casa. Here , here , and here you can find useful introductory material. Inspect the DOM tree generated for application pages and determine the CSS selectors you need to edit or things you have to add in order to alter the appearance. Use your web browser's facilities to inspect web page composition: this is usually part of any browser's developer toolbar. Moreover, they allow you to change styles on the fly so you can play a lot before applying the real changes. Don't override rules that are already defined in Tachyons. Conversely, ZK rules (which are prefixed with z- ) are safe to be re-defined since ZK CSS isn't included. In most circumstances, your work will come down to editing existing rules in style.css . HTML markup will show rules (in the class attribute) prefixed with cust- that are apparently not defined anywhere. These rules are intended to give admins the opportunity to add their design tastes. The following is a list of custom selectors you can add to style.css . Names are in general self-explanatory, the images below help clarify more. cust-menu-item cust-content-heading cust-sections-wrapper cust-section cust-panel cust-modal-window cust-edit-button cust-link-button cust-delete-button cust-primary-button cust-cancel-button cust-misc-button cust-text-input cust-progress-bar Viewing your changes # There is no need to restart the application for the changes to take effect. However, most static files are cached by browsers, so you will need to open a fresh private browsing (incognito) session. If you tried the above and still don't see changes, try hitting the resource URL directly in a new browser tab. For example, to load the style.css file in your browser, visit https://<host-name>/casa/custom/styles/gluu/style.css . That way, you can determine if your changes are there. Reverting to Default Theme # If for any reason you wish to restore the default theme, select \"Use default (Gluu Inc.) theme\" in the admin dashboard. Examples # Here are solutions for common use cases: Use a different logo # Just replace images/logo.png (relative to the static directory) with your own image. Use a Different Favicon # Replace images/favicon.ico with your own image. Change the Font Used in Text # The vast majority of text that appears in the application uses the same font. To set the default font, locate at the bottom of style.css a declaration like @import url('https://fonts.googleapis.com... and point to one of your choosing. Check out this page to learn more about Google fonts. Then, scroll down and modify the html and body selectors appropriately with the font you picked. If you want to use your own fonts instead of Google's, you can use @font-face for this purpose. Copy your ttf , woff , svg or eot files somewhere in the static directory and link them appropriately. To use the more classical fonts like \"Helvetica\", \"Arial\", etc., simply update html and body selectors passing the font-family name.", "title": "Custom branding"}, {"location": "casa/administration/custom-branding/#custom-branding", "text": "In Casa, administrators can supply their own logo and favicon to better match the organization's look and feel. If you want to apply more advanced customizations, adding the custom branding plugin is the way to go. Note This page covers customizations available through the custom branding plugin . It is assumed you have already added it to your Casa installation. The plugin allows administrators to easily alter the appearance of Casa. There are two ways to tweak the design: a quick point-and-click set of changes that you can preview immediately, or a lower-level approach that allows you to supply your own CSS file and images (this is known as external assets directory usage).", "title": "Custom branding"}, {"location": "casa/administration/custom-branding/#quick-design-customization", "text": "Click on Custom branding in the admin console, and choose Upload images and pick colors . With this branding alternative, you can apply some visual changes effortlessly with zero CSS coding. You can: Supply your company logo and favicon Choose the background color for the page header Choose button colors Edit the footer text Once you supply your files, color values, and footer text, click on Save and see the changes take immediately by navigating to a different page or opening a new browser tab. Repeat the process till you get the combination that best matches your organization's look and feel. With \"Primary buttons\" we refer to the vast majority of buttons that trigger some action such as saving, updating or accepting - whether in the user pages or the admin UI itself. \"Cancel\" covers undo, close or cancel, while \"Misc\" is for anything not fitting any of the previous usages. You can choose \"Use defaults\" if you feel comfortable with the Bootstrap-like colors offered in Jans Casa.", "title": "Quick design customization"}, {"location": "casa/administration/custom-branding/#using-the-external-assets-directory", "text": "Note Intermediate-level knowledge of CSS is required for this task.", "title": "Using the external assets directory"}, {"location": "casa/administration/custom-branding/#background", "text": "Casa's UI design is driven by one CSS stylesheet and a few images. Specifically, Casa leverages the following UI frameworks: ZK Tachyons 4.11 Font Awesome 5.12 Particularly, ZK's default theme CSS file was disabled to offer a higher degree of flexibility in design. This enables Tachyons to claim control over style rules applied to HTML markup.", "title": "Background"}, {"location": "casa/administration/custom-branding/#external-assets-directory", "text": "In the /opt/jans/jetty/casa/static folder, you can place your own version of the main stylesheet and images Casa uses. No other stylesheet should be overriden. To start, log in to the Janssen Server and do the following: cd /opt/jans/jetty/jans-casa/static jar -xf ../webapps/jans-casa.war images styles/gluu/style.css This will copy the files you can edit later (these are the original versions provided out of the box in Casa). If you place additional files in this directory, ensure ownership is set to recursive. For instance, you can: $ chown -R jetty:jetty /opt/jans/jetty/jans-casa/static/", "title": "External assets directory"}, {"location": "casa/administration/custom-branding/#enable-and-apply-your-customizations", "text": "In the admin console, navigate to Custom branding > Use Casa external assets directory . From that point on, your installation is reading relevant files from the static directory. Note In CSS, the rules' order of appearance is important. For all Casa pages, style.css is loaded first, then tachyons.css. This means rules for Tachyons have higher priority unless !important is used. The main stylesheet ( style.css ) is located at /opt/jans/jetty/jans-casa/static/styles/gluu if you have followed the instructions above. Here are some tips for applying your customizations: Get acquainted with functional CSS. This is the approach followed in Casa. Here , here , and here you can find useful introductory material. Inspect the DOM tree generated for application pages and determine the CSS selectors you need to edit or things you have to add in order to alter the appearance. Use your web browser's facilities to inspect web page composition: this is usually part of any browser's developer toolbar. Moreover, they allow you to change styles on the fly so you can play a lot before applying the real changes. Don't override rules that are already defined in Tachyons. Conversely, ZK rules (which are prefixed with z- ) are safe to be re-defined since ZK CSS isn't included. In most circumstances, your work will come down to editing existing rules in style.css . HTML markup will show rules (in the class attribute) prefixed with cust- that are apparently not defined anywhere. These rules are intended to give admins the opportunity to add their design tastes. The following is a list of custom selectors you can add to style.css . Names are in general self-explanatory, the images below help clarify more. cust-menu-item cust-content-heading cust-sections-wrapper cust-section cust-panel cust-modal-window cust-edit-button cust-link-button cust-delete-button cust-primary-button cust-cancel-button cust-misc-button cust-text-input cust-progress-bar", "title": "Enable and apply your customizations"}, {"location": "casa/administration/custom-branding/#viewing-your-changes", "text": "There is no need to restart the application for the changes to take effect. However, most static files are cached by browsers, so you will need to open a fresh private browsing (incognito) session. If you tried the above and still don't see changes, try hitting the resource URL directly in a new browser tab. For example, to load the style.css file in your browser, visit https://<host-name>/casa/custom/styles/gluu/style.css . That way, you can determine if your changes are there.", "title": "Viewing your changes"}, {"location": "casa/administration/custom-branding/#reverting-to-default-theme", "text": "If for any reason you wish to restore the default theme, select \"Use default (Gluu Inc.) theme\" in the admin dashboard.", "title": "Reverting to Default Theme"}, {"location": "casa/administration/custom-branding/#examples", "text": "Here are solutions for common use cases:", "title": "Examples"}, {"location": "casa/administration/custom-branding/#use-a-different-logo", "text": "Just replace images/logo.png (relative to the static directory) with your own image.", "title": "Use a different logo"}, {"location": "casa/administration/custom-branding/#use-a-different-favicon", "text": "Replace images/favicon.ico with your own image.", "title": "Use a Different Favicon"}, {"location": "casa/administration/custom-branding/#change-the-font-used-in-text", "text": "The vast majority of text that appears in the application uses the same font. To set the default font, locate at the bottom of style.css a declaration like @import url('https://fonts.googleapis.com... and point to one of your choosing. Check out this page to learn more about Google fonts. Then, scroll down and modify the html and body selectors appropriately with the font you picked. If you want to use your own fonts instead of Google's, you can use @font-face for this purpose. Copy your ttf , woff , svg or eot files somewhere in the static directory and link them appropriately. To use the more classical fonts like \"Helvetica\", \"Arial\", etc., simply update html and body selectors passing the font-family name.", "title": "Change the Font Used in Text"}, {"location": "casa/administration/faq/", "tags": ["Casa", "administration", "faq"], "text": "Frequently Asked Questions # Common administrative tasks # Where are the logs? # The application logs are located at /opt/jans/jetty/jans-casa/logs . By default, Casa uses the INFO level for messages. You can change the log level at will using the app's admin UI. How do I custom brand Casa? # We have a dedicated page covering the topic of custom branding here . What ports are used by the application? # Casa uses port 8080 . One way to see if the app is up and running is by checking whether this port is open by issuing a command like netstat -nltp . How to turn 2FA off for a user? # If a user has been locked out for any reason (e.g. lost devices), you can reset his \"authentication method\" to password by accessing the admin console and choosing the menu item labelled \"Reset users preference\". Type the username (or part of) in the text field and then press search. Once you locate the user in the result grid, click the corresponding row and then hit \"Change to password\". The row will become disabled, and you'll see a success message. If you've followed the steps as described above, next time he attempts to log in, he won't be asked to present any credentials other than password to enter. How to adjust the issuer for OTP tokens # When people add OTP mobile apps, the enrollment appears in the device associated with an \"issuer\", so it is easy to recognize where the OTPs generated can be used. To keep track of which OTPs are valid for which IDPs, the issuer property can be adjusted in flow io.jans.casa.authn.otp part of Casa Agama project - you can use TUI for this purpose. For example, you might want to set the issuer property to ACME Dev on your dev server, and ACME, Inc. on your production server. Errors shown in the UI # A page with a \"Service Temporarily Unavailable\" message appears when accessing the application # This is the 503 HTTP error. There is an Apache server in front of the application and this means the reverse proxy couldn't establish a communication internally with the app. This usually happens when Casa hasn't started completely, so it's usually a matter of waiting a few seconds. An \"Unauthorized access\" error is shown when accessing the application # This is caused by an unauthorized access attempt (e.g. users requesting URLs without ever logging in or after session has expired). \"An error occurred: Casa did not start properly\" is shown when accessing the application # This occurs whenever the application failed to start successfully. Check the log to diagnose the problem. Try to find a message like \"WEBAPP INITIALIZATION FAILED\" and see the traces above it. Often, error messages are self-explanatory. Once fixed, please restart the application. You will have to see a \"WEBAPP INITIALIZED SUCCESSFULLY\" message to know that it's working. Miscellanenous # Admin console is not shown # If you have logged in using an administrative account and cannot find any admin features in the UI ensure you have gone through these steps . A previously enabled method is not available anymore # Check if the plugin that contributed the given authentication method was removed. The out-of-the-box methods will always appear listed. What kind of TOTP/HOTP devices are supported? # Both soft (mobile apps) or hard tokens (keyfobs, cards, etc.) are supported. Supported algorithms are HmacSHA1 , HmacSHA256 , and HmacSHA512 . Authentication fails when using TOTP or HOTP with no apparent reason # For Time-based OTP, ensure the time of your server is correctly synchronized (use NTP for instance). The time lag of the authentication device used (for instance, a mobile phone) with respect to server time should not be representative. Big time differences can cause unsuccessful attempts to enroll TOTP credentials in Casa. For Event-based OTP (HOTP), ensure you are using a suitable value for look ahead window (we suggest at least 10). Check the configuration of flow io.jans.casa.authn.otp part of Casa Agama project - you can use TUI for this purpose. The user interface is not showing any means to enroll credentials # In the administration console, ensure one or more authentication methods have been enabled. A user cannot turn 2FA on # To turn 2FA on, the user has to have enrolled at least a certain number of credentials through the app. Only after this is met, he will be able to perform this action. In the administration console you can specify the minimum number of enrolled credentials needed to enable second factor authentication for users. Please check the 2FA Settings plugin for more details. My problem is not listed here # Feel free to ask Janssen Server community .", "title": "FAQ"}, {"location": "casa/administration/faq/#frequently-asked-questions", "text": "", "title": "Frequently Asked Questions"}, {"location": "casa/administration/faq/#common-administrative-tasks", "text": "", "title": "Common administrative tasks"}, {"location": "casa/administration/faq/#where-are-the-logs", "text": "The application logs are located at /opt/jans/jetty/jans-casa/logs . By default, Casa uses the INFO level for messages. You can change the log level at will using the app's admin UI.", "title": "Where are the logs?"}, {"location": "casa/administration/faq/#how-do-i-custom-brand-casa", "text": "We have a dedicated page covering the topic of custom branding here .", "title": "How do I custom brand Casa?"}, {"location": "casa/administration/faq/#what-ports-are-used-by-the-application", "text": "Casa uses port 8080 . One way to see if the app is up and running is by checking whether this port is open by issuing a command like netstat -nltp .", "title": "What ports are used by the application?"}, {"location": "casa/administration/faq/#how-to-turn-2fa-off-for-a-user", "text": "If a user has been locked out for any reason (e.g. lost devices), you can reset his \"authentication method\" to password by accessing the admin console and choosing the menu item labelled \"Reset users preference\". Type the username (or part of) in the text field and then press search. Once you locate the user in the result grid, click the corresponding row and then hit \"Change to password\". The row will become disabled, and you'll see a success message. If you've followed the steps as described above, next time he attempts to log in, he won't be asked to present any credentials other than password to enter.", "title": "How to turn 2FA off for a user?"}, {"location": "casa/administration/faq/#how-to-adjust-the-issuer-for-otp-tokens", "text": "When people add OTP mobile apps, the enrollment appears in the device associated with an \"issuer\", so it is easy to recognize where the OTPs generated can be used. To keep track of which OTPs are valid for which IDPs, the issuer property can be adjusted in flow io.jans.casa.authn.otp part of Casa Agama project - you can use TUI for this purpose. For example, you might want to set the issuer property to ACME Dev on your dev server, and ACME, Inc. on your production server.", "title": "How to adjust the issuer for OTP tokens"}, {"location": "casa/administration/faq/#errors-shown-in-the-ui", "text": "", "title": "Errors shown in the UI"}, {"location": "casa/administration/faq/#a-page-with-a-service-temporarily-unavailable-message-appears-when-accessing-the-application", "text": "This is the 503 HTTP error. There is an Apache server in front of the application and this means the reverse proxy couldn't establish a communication internally with the app. This usually happens when Casa hasn't started completely, so it's usually a matter of waiting a few seconds.", "title": "A page with a \"Service Temporarily Unavailable\" message appears when accessing the application"}, {"location": "casa/administration/faq/#an-unauthorized-access-error-is-shown-when-accessing-the-application", "text": "This is caused by an unauthorized access attempt (e.g. users requesting URLs without ever logging in or after session has expired).", "title": "An \"Unauthorized access\" error is shown when accessing the application"}, {"location": "casa/administration/faq/#an-error-occurred-casa-did-not-start-properly-is-shown-when-accessing-the-application", "text": "This occurs whenever the application failed to start successfully. Check the log to diagnose the problem. Try to find a message like \"WEBAPP INITIALIZATION FAILED\" and see the traces above it. Often, error messages are self-explanatory. Once fixed, please restart the application. You will have to see a \"WEBAPP INITIALIZED SUCCESSFULLY\" message to know that it's working.", "title": "\"An error occurred: Casa did not start properly\" is shown when accessing the application"}, {"location": "casa/administration/faq/#miscellanenous", "text": "", "title": "Miscellanenous"}, {"location": "casa/administration/faq/#admin-console-is-not-shown", "text": "If you have logged in using an administrative account and cannot find any admin features in the UI ensure you have gone through these steps .", "title": "Admin console is not shown"}, {"location": "casa/administration/faq/#a-previously-enabled-method-is-not-available-anymore", "text": "Check if the plugin that contributed the given authentication method was removed. The out-of-the-box methods will always appear listed.", "title": "A previously enabled method is not available anymore"}, {"location": "casa/administration/faq/#what-kind-of-totphotp-devices-are-supported", "text": "Both soft (mobile apps) or hard tokens (keyfobs, cards, etc.) are supported. Supported algorithms are HmacSHA1 , HmacSHA256 , and HmacSHA512 .", "title": "What kind of TOTP/HOTP devices are supported?"}, {"location": "casa/administration/faq/#authentication-fails-when-using-totp-or-hotp-with-no-apparent-reason", "text": "For Time-based OTP, ensure the time of your server is correctly synchronized (use NTP for instance). The time lag of the authentication device used (for instance, a mobile phone) with respect to server time should not be representative. Big time differences can cause unsuccessful attempts to enroll TOTP credentials in Casa. For Event-based OTP (HOTP), ensure you are using a suitable value for look ahead window (we suggest at least 10). Check the configuration of flow io.jans.casa.authn.otp part of Casa Agama project - you can use TUI for this purpose.", "title": "Authentication fails when using TOTP or HOTP with no apparent reason"}, {"location": "casa/administration/faq/#the-user-interface-is-not-showing-any-means-to-enroll-credentials", "text": "In the administration console, ensure one or more authentication methods have been enabled.", "title": "The user interface is not showing any means to enroll credentials"}, {"location": "casa/administration/faq/#a-user-cannot-turn-2fa-on", "text": "To turn 2FA on, the user has to have enrolled at least a certain number of credentials through the app. Only after this is met, he will be able to perform this action. In the administration console you can specify the minimum number of enrolled credentials needed to enable second factor authentication for users. Please check the 2FA Settings plugin for more details.", "title": "A user cannot turn 2FA on"}, {"location": "casa/administration/faq/#my-problem-is-not-listed-here", "text": "Feel free to ask Janssen Server community .", "title": "My problem is not listed here"}, {"location": "casa/administration/localization/", "tags": ["Casa", "administration", "localization"], "text": "Casa localization # Casa supports multilingual support through resource bundles. Administrators supply bundles as plaintext files ending with the .properties file extension. By default, Casa contains three bundles, each in a separate file. These bundles contain the internationalization labels in the English language, as displayed in a default Casa installation. For example, to add support for French, you would have to create the following files: File Description user_fr.properties Contains labels mostly found in user-facing pages admin_fr.properties Contains labels mostly found in administrator-facing pages general_fr.properties Contains labels found widely across the app and plugins Adding internationalization labels # To supply labels in a particular language (or even if you want to override the English translation provided), do the following: Log in to the Janssen Server using SSH Extract the Casa default labels: /opt/jre/bin/jar -xf /opt/jans/jetty/jans-casa/webapps/casa.war WEB-INF/classes/labels Run cp WEB-INF/classes/labels/*.properties . and delete WEB-INF dir: rm -R WEB-INF/ Add the appropriate suffix to the properties files found in the current directory, ie. _de for German, _es for Spanish, _ja for Japanese, etc. Edit the contents of files accordingly. Use UTF-8 encoding for opening and saving cd to /opt/jans/jetty/jans-casa/static Create directory i18n if it does not exist: mkdir i18n Transfer the properties files to the i18n folder Ensure jetty user has permission for reading the files Restart casa Log in to the application and review your work. Make necessary edits and repeat the process. How are labels picked? # In Casa, the rule for displaying contents is leveraged from the underlying framework . In short, the locale to use per session is picked based on the end-user browser settings. As an example, if the browser was configured to use U.S. English, the locale will be en_US . This means that files ending in _en_US.properties will be considered first. Then, the country suffix is removed and thus _en.properties is looked up. Finally the non-suffixed ones are considered, that is, the default label files bundled with Casa. Additionally, end users can pick the language of their preference by selecting a language item from the dropdown list appearing at the bottom of any Casa page. The list is only shown if there are two or more languages available to display. Localization in plugins # Plugins also support localization through the \"zk-label\" bundle. If you have installed plugins developed by Gluu, they will only contain a single default English file. To add your own translation for plugin texts, proceed as follows: cd to the folder where you stored the jar file of the plugin of interest. Extract the plugin's default labels (requires Java bin on your path): jar -xf JAR_FILE labels/zk-label.properties cd to labels folder Add the appropriate suffix to the properties file, ie. _de for German, _es for Spanish, _ja for Japanese, etc. Edit the contents accordingly. Use UTF-8 encoding for opening and saving Connect to your Janssen Server using SSH cd to /opt/jans/jetty/jans-casa/static Create directory i18n if it does not exist: mkdir i18n Transfer the properties file to the i18n folder Ensure jetty user has permission for reading Restart casa Note If your plugins have a zk-label.properties , you can accumulate all plugin texts into a single file, or you can use a different filename for each plugin. Properties file syntax # Administrators acquainted with the format used for properties files in Java will find Casa resource bundle files familiar. The format used in Casa differs slightly, but it is more powerful. To learn more about this topic, visit this page . Tips # Not all entries present in default label files have to be translated in your own localized versions. If you are comfortable with the current text for a particular entry, you can simply remove it to use the one in the default files. There is no need to supply specific translations for countries. While supported, most of time it suffices to create files suffixed with the language code, for instance _es , and not with country code (e.g _es_CO , _es_AR , _es_EC , _es_ES , etc.) Actual filenames for properties files are not relevant. Upon start, Casa will parse all properties files present in i18n folder.", "title": "Localization"}, {"location": "casa/administration/localization/#casa-localization", "text": "Casa supports multilingual support through resource bundles. Administrators supply bundles as plaintext files ending with the .properties file extension. By default, Casa contains three bundles, each in a separate file. These bundles contain the internationalization labels in the English language, as displayed in a default Casa installation. For example, to add support for French, you would have to create the following files: File Description user_fr.properties Contains labels mostly found in user-facing pages admin_fr.properties Contains labels mostly found in administrator-facing pages general_fr.properties Contains labels found widely across the app and plugins", "title": "Casa localization"}, {"location": "casa/administration/localization/#adding-internationalization-labels", "text": "To supply labels in a particular language (or even if you want to override the English translation provided), do the following: Log in to the Janssen Server using SSH Extract the Casa default labels: /opt/jre/bin/jar -xf /opt/jans/jetty/jans-casa/webapps/casa.war WEB-INF/classes/labels Run cp WEB-INF/classes/labels/*.properties . and delete WEB-INF dir: rm -R WEB-INF/ Add the appropriate suffix to the properties files found in the current directory, ie. _de for German, _es for Spanish, _ja for Japanese, etc. Edit the contents of files accordingly. Use UTF-8 encoding for opening and saving cd to /opt/jans/jetty/jans-casa/static Create directory i18n if it does not exist: mkdir i18n Transfer the properties files to the i18n folder Ensure jetty user has permission for reading the files Restart casa Log in to the application and review your work. Make necessary edits and repeat the process.", "title": "Adding internationalization labels"}, {"location": "casa/administration/localization/#how-are-labels-picked", "text": "In Casa, the rule for displaying contents is leveraged from the underlying framework . In short, the locale to use per session is picked based on the end-user browser settings. As an example, if the browser was configured to use U.S. English, the locale will be en_US . This means that files ending in _en_US.properties will be considered first. Then, the country suffix is removed and thus _en.properties is looked up. Finally the non-suffixed ones are considered, that is, the default label files bundled with Casa. Additionally, end users can pick the language of their preference by selecting a language item from the dropdown list appearing at the bottom of any Casa page. The list is only shown if there are two or more languages available to display.", "title": "How are labels picked?"}, {"location": "casa/administration/localization/#localization-in-plugins", "text": "Plugins also support localization through the \"zk-label\" bundle. If you have installed plugins developed by Gluu, they will only contain a single default English file. To add your own translation for plugin texts, proceed as follows: cd to the folder where you stored the jar file of the plugin of interest. Extract the plugin's default labels (requires Java bin on your path): jar -xf JAR_FILE labels/zk-label.properties cd to labels folder Add the appropriate suffix to the properties file, ie. _de for German, _es for Spanish, _ja for Japanese, etc. Edit the contents accordingly. Use UTF-8 encoding for opening and saving Connect to your Janssen Server using SSH cd to /opt/jans/jetty/jans-casa/static Create directory i18n if it does not exist: mkdir i18n Transfer the properties file to the i18n folder Ensure jetty user has permission for reading Restart casa Note If your plugins have a zk-label.properties , you can accumulate all plugin texts into a single file, or you can use a different filename for each plugin.", "title": "Localization in plugins"}, {"location": "casa/administration/localization/#properties-file-syntax", "text": "Administrators acquainted with the format used for properties files in Java will find Casa resource bundle files familiar. The format used in Casa differs slightly, but it is more powerful. To learn more about this topic, visit this page .", "title": "Properties file syntax"}, {"location": "casa/administration/localization/#tips", "text": "Not all entries present in default label files have to be translated in your own localized versions. If you are comfortable with the current text for a particular entry, you can simply remove it to use the one in the default files. There is no need to supply specific translations for countries. While supported, most of time it suffices to create files suffixed with the language code, for instance _es , and not with country code (e.g _es_CO , _es_AR , _es_EC , _es_ES , etc.) Actual filenames for properties files are not relevant. Upon start, Casa will parse all properties files present in i18n folder.", "title": "Tips"}, {"location": "casa/administration/quick-start/", "tags": ["Casa", "quick start"], "text": "Jans Casa Quick Start Guide # Note This document is intended for administrators only. Learn here how to \"grant\" administrative privileges for Casa. Use this guide to install and configure your Casa deployment. Installation # Jans Casa can be used with Janssen Server or Gluu Flex Server . At installation time (applies to any of these two products), you will be prompted if you desire to include Casa. If you want to add Casa post-installation, you will simply have to re-run the installer and ensure to select Casa. Configuration # Enable authentication methods # The \"out-of-the-box\" login experience in Casa consists of the usual username and password prompt. To start leveraging a stronger authentication login to Casa with an administrative account (visit https://<your-server-name>/jans-casa ) and activate the methods you want to offer Casa users. Important notes : Usage of OTP via SMS requires the setup of a Twilio account and populating configuration properties of flow io.jans.casa.authn.twilio_sms found in Casa Agama project. You can do the latter via TUI . We encourage you to use the online Twilio testing tools beforehand to ensure you can send SMS to the countries you are targetting Usage of Super Gluu has some preliminar requisites described here Add the strong authentication settings plugin # This step is optional. Check this page for more information. Use this plugin if you need to exercise an advanced control on how 2FA behaves in your Casa deployment. Test enrollment and 2FA # Do the following steps using a testing account with no administrative privileges: Login to Casa. Only username and password should be prompted Use the menu on the left to access the screens from which enrollment of credentials can be performed Ensure at least two credentials have been added. In the home page, turn on 2FA Log off and log back in. From now on, besides username and password, one credential has to be presented to get access Click here to learn more about 2FA in Casa. Finish configuration # Once you are done with testing, you may use casa as the default authentication method of Janssen Server using TUI to log in users via Casa for all applications the server protects. Finally, as a security measure you can thoroughly disable access to the administrative console of Casa by following the steps below: Connect to your server Navigate to /opt/jans/jetty/jans-casa remove file .administrable (ie. rm .administrable ) If you want to make the admin console available again you need to recreate the marker file: Create an empty file (eg. touch .administrable ) Run chown casa:casa .administrable (do this only if you are on FIPS environment) Logout in case you have an open browser session, and login again Check out available plugins # Browse our catalog of plugins to add features and expand Casa!.", "title": "Quick Start"}, {"location": "casa/administration/quick-start/#jans-casa-quick-start-guide", "text": "Note This document is intended for administrators only. Learn here how to \"grant\" administrative privileges for Casa. Use this guide to install and configure your Casa deployment.", "title": "Jans Casa Quick Start Guide"}, {"location": "casa/administration/quick-start/#installation", "text": "Jans Casa can be used with Janssen Server or Gluu Flex Server . At installation time (applies to any of these two products), you will be prompted if you desire to include Casa. If you want to add Casa post-installation, you will simply have to re-run the installer and ensure to select Casa.", "title": "Installation"}, {"location": "casa/administration/quick-start/#configuration", "text": "", "title": "Configuration"}, {"location": "casa/administration/quick-start/#enable-authentication-methods", "text": "The \"out-of-the-box\" login experience in Casa consists of the usual username and password prompt. To start leveraging a stronger authentication login to Casa with an administrative account (visit https://<your-server-name>/jans-casa ) and activate the methods you want to offer Casa users. Important notes : Usage of OTP via SMS requires the setup of a Twilio account and populating configuration properties of flow io.jans.casa.authn.twilio_sms found in Casa Agama project. You can do the latter via TUI . We encourage you to use the online Twilio testing tools beforehand to ensure you can send SMS to the countries you are targetting Usage of Super Gluu has some preliminar requisites described here", "title": "Enable authentication methods"}, {"location": "casa/administration/quick-start/#add-the-strong-authentication-settings-plugin", "text": "This step is optional. Check this page for more information. Use this plugin if you need to exercise an advanced control on how 2FA behaves in your Casa deployment.", "title": "Add the strong authentication settings plugin"}, {"location": "casa/administration/quick-start/#test-enrollment-and-2fa", "text": "Do the following steps using a testing account with no administrative privileges: Login to Casa. Only username and password should be prompted Use the menu on the left to access the screens from which enrollment of credentials can be performed Ensure at least two credentials have been added. In the home page, turn on 2FA Log off and log back in. From now on, besides username and password, one credential has to be presented to get access Click here to learn more about 2FA in Casa.", "title": "Test enrollment and 2FA"}, {"location": "casa/administration/quick-start/#finish-configuration", "text": "Once you are done with testing, you may use casa as the default authentication method of Janssen Server using TUI to log in users via Casa for all applications the server protects. Finally, as a security measure you can thoroughly disable access to the administrative console of Casa by following the steps below: Connect to your server Navigate to /opt/jans/jetty/jans-casa remove file .administrable (ie. rm .administrable ) If you want to make the admin console available again you need to recreate the marker file: Create an empty file (eg. touch .administrable ) Run chown casa:casa .administrable (do this only if you are on FIPS environment) Logout in case you have an open browser session, and login again", "title": "Finish configuration"}, {"location": "casa/administration/quick-start/#check-out-available-plugins", "text": "Browse our catalog of plugins to add features and expand Casa!.", "title": "Check out available plugins"}, {"location": "casa/developer/add-authn-methods/", "tags": ["Casa", "developer guide"], "text": "Onboarding custom authentication methods # Out-of-the-box Casa supports some useful authentication methods for a secure, pleasant authentication experience. Adding more authentication mechanisms is possible and requires certain development effort. In this guide we summarize the steps required to do so and give you some useful pointers to start your coding journey. Supporting a new authentication mechanisms consists of two tasks: coding an Agama flow and creating a plugin that contributes an authentication method. The former has to do with the authentication flow the user experiences (to access Casa or other apps), while the latter with the credential enrollment process. Agama flow # Note Acquaintance with Agama framework and Agama project management is required About Casa authentication flow # Authentication in Casa is implemented through an Agama project called casa - in TUI you can see it listed in the Agama management screen. As a first step, the user is requested to enter the username and password combination, then depending on how the application is configured, personal user settings, and access policies defined, a second factor may be requested. The casa project allows to onboard new types of second factors (authentication mechanisms) and also provides a user experience that supports backtracking: if a user is asked to present a specific credential and that credential is not currently available or is not working, he can choose an alternative method for authentication where a different type of credential will be prompted. Users can backtrack several times. Flow requisites # To code the flow corresponding to the authentication method to add, you can use the Agama project found here as a canvas. Ensure the following conditions are met so that it properly integrates in the main Casa flow: The flow will be passed an Agama map containing information of the person attempting the authentication. This input parameter will contain at least three keys: uid , inum , and name . uid and inum map directly to attributes stored in the user's profile and are never empty, name is a displayable name which may come from attribute givenName or displayName . All values are strings . The flow should terminate with a true outcome if the user successfully passes the challenge, presents the expected credential, etc. In any other case, false must be returned and an optional error message can be included for the caller flow ( io.jans.casa.authn.main ) to show it in the screen. Any additional data attached in the Finish instruction will not be processed. If for some reason your flow crashes, the corresponding exception will be printed to the logs, the caller will continue running, and the browser taken to the selector page where an error message will be displayed. Note your project may contain more flows to serve as utilitarians or simply to break down the authentication flow into smaller, more manageable pieces. About templates # Regarding UI templates, it is recommended to re-use a couple of Freemarker macros available in the casa project. This will allow your flow's UI to have the same look-and-feel of flows bundled out-of-the box, like OTP and fido. Additionally this will allow to properly incorporate backtracking. Import the commons template in your UI page: <#import \"../kz1vc3/commons.ftlh\" as com> Copy the above line of code in the first line of your templates, preferably. Note you may need to add extra ../ fragments in the path to commons.ftlh depending on the directory level where your template resides inside the web subdirectory of your Agama project. Then call the main macro and supply your markup, like this: <@com.main> <!-- your markup here --> <@com.main> The above will generate a page incorporating the required CSS files and will render the header and footer appropriately while leaving your content in the center of the page. The casa project makes heavy use the Tachyons CSS. You may like to use those for building templates instead of incorporating yet another styling framework. It is highly recommended to include the following near the bottom of your markup (still inside the main call block): <@com.alternative /> This will render a form with a text and a link that will allow users to \"escape\" from your flow and take another route, i.e. to backtrack: Then, in your flow's code, you handle the escape this way: data = RRF \"mytemplate.ftlh\" ... When data.skipped is \"\" Finish false The above means your flow can finish with false not only if the authentication did not succeed but also when users wants to backtrack. The selector page # When backtracking, a selector page is shown where all available methods for the given user are displayed - sorted by strength. From here, the user can take another route to be challenged for an alternative credential. Every element in the list has an icon and descriptive text associated. These elements are configurable and for the case of adding an authentication method, both icon and text should be supplied. To do so, locate in TUI the casa Agama project. See how the flow io.jans.casa.authn.main has a selector section in its configurations. This is a dictionary (JSON object) where keys are qualified names of flows and values are dictionaries at the same time - this where you can provide the required info. For example, if your authentication method is backed by a flow com.acme.authn.food , the casa project configuration may look like { \"io.jans.casa.authn.main\": { \"selector\": { \"com.acme.authn.food\": { \"icon\": \"<i class='fas fa-pizza-slice'></i>\", \"text\": \"A sentence describing what the user is supposed to present in the next screen\" }, ... } }, ... } Alternatively, a pointer to a localized message can be used instead of text . This is the recommended practice if localization/internationalization is relevant. In this case, something like the below will work: ... \"com.acme.authn.food\": { \"icon\": \"<i class='fas fa-pizza-slice'></i>\", \"textKey\": \"foodAuth.methodTitle\" } ... as long as the message key foodAuth.methodTitle is defined in the project's labels.txt file, or elsewhere in another project. Note textKey takes precedence over text when rendering the page. Both icon and textKey (or text ) may contain HTML markup. In this example we are using the font awesome library available in the selector page for rendering a nice icon but we could have used any other thing here like an img tag, for instance. Ensure to properly escape double quotes if necessary. Also make the markup a one-liner: JSON strings cannot span several lines. Recommended practices # Note Ensure to go through this page before proceeding Config settings # Use a single place to store configuration settings for your authentication method. The most convenient place is in the Agama project itself. You may have configs associated to each flow in your project and they can be accessed directly in your flows code. Additionally, they can be easily read from your plugin's Java code this way: ips = io.jans.casa.misc.Utils.managedBean(IPersistenceService.class); JSONObject p = ips.getAgamaFlowConfigProperties(\"flow qname\"); Out-of-the-box methods in Casa employ this strategy. Also when you do this, every time a change in project configuration is detected, your Java code gets notified: a call to method reloadConfiguration of your extension is issued, see class SampleCredentialAuthnMethod in the sample credential plugin. Retries # Giving the user only one chance to pass an authentication challenge is unfair. Code your flow so users have a couple of opportunities to fail before finishing with false as outcome. Agama's Repeat directive helps you cover this case. Key questions # As you try to assemble your project, you will come up with some design decisions, for instance: How to model and store credentials associated to the authentication method? What kind of parameters are relevant for the authentication method? What's the algorithm for authenticating users once they have supplied a valid username/password combination? Depending on the answers, you may like to start instead with plugin development first. This is not always the case though, however, getting your hands on the plugin might help unclutter the path. Enrollment plugin # Coding a Casa plugin is mainly a Java development task. You can use the \"Sample credential\" plugin as a template to start the work. Ensure you have: A Jans Server installation that includes Jans Casa - prefer a VM environment over the CN edition for development purposes. Also, you'll need a way to connect to your server via SSH A copy of the Jans repository (a shallow clone of main branch is OK): https://github.com/JanssenProject/jans Plugin deployment # Start with deploying the plugin to get acquainted with the process: In the local development machine, cd to ./jans/jans-casa/plugins/samples/sample-cred Run mvn -Dmaven.test.skip package . This may take several minutes (lots of network requests). Once you get it done, the next time you can add the -o switch (offline mode) for faster results A target folder with a couple of jar files in it will be generated Access Casa admin console and in the plugins page, upload the file suffixed with jar-with-dependencies.jar . After one minute approximately, visit the \"Authentication methods\" page, check the \"Favorite color\" widget, and click on \"Save\". Then logout. Login again, this time with a non administrative account. In the landing page (user's dashboard), an item labeled \"Your favorite color\" will be shown on the left (under the \"2FA credentials\" heading). Also, a panel in the central area of the page will be added in accordance. Click on \"Your favorite color\" and you'll land a page to let Casa know what your favorite color is!. This color will be used as a second factor for authentication. Ensure you have enabled another method such as OTP so you can enroll an additional credential in order to be able to active 2FA for this account. Study the sample project # Now it's time for you to go through the project folder checking one file at a time. Most of files contain comments that explain the purpose of things. Ensure you make a deep inspection of file ./src/main/resources/assets/user/cred_details.zul . It contains the markup of the page you visited earlier. Make an excursion to interface AuthnMethod found in shared maven module. Note it brings a couple of default methods. Class SampleCredentialAuthnMethod implements this interface. Editing the project # Modifying the project may require you to edit files mainly with .java , .zul , or .properties extensions. Most Java classes used in this plugin can be found in: The repository you cloned earlier The ZK framework documentation Standard Java SE API docs You can remove the plugin and add it as many times as you like - no restarts are needed unless things go really weird. You can do so either via the admin console or by dropping/removing the file directly in the filesystem (the path is /opt/jans/jetty/jans-casa/plugins ). Page tweaks # If you alter a .zul file and then package and redeploy the plugin, you will most probably not see any change taking effect in the UI page. This is because the ZK framework caches the .zul pages by default for a very long period. To change this behavior do the following: Connect to your VM and cd to /opt/gluu/jetty/jans-casa/webapps Extract ZK descriptor: # jar -xf jans-casa.war WEB-INF/zk.xml Locate XML tag file-check-period and remove it including its surrounding parent desktop-config Save the file and patch the application war: # jar -uf jans-casa.war WEB-INF/zk.xml Restart casa (e.g. systemctl casa restart ) From now on, any template change will take effect after 5 seconds.", "title": "Adding authentication methods"}, {"location": "casa/developer/add-authn-methods/#onboarding-custom-authentication-methods", "text": "Out-of-the-box Casa supports some useful authentication methods for a secure, pleasant authentication experience. Adding more authentication mechanisms is possible and requires certain development effort. In this guide we summarize the steps required to do so and give you some useful pointers to start your coding journey. Supporting a new authentication mechanisms consists of two tasks: coding an Agama flow and creating a plugin that contributes an authentication method. The former has to do with the authentication flow the user experiences (to access Casa or other apps), while the latter with the credential enrollment process.", "title": "Onboarding custom authentication methods"}, {"location": "casa/developer/add-authn-methods/#agama-flow", "text": "Note Acquaintance with Agama framework and Agama project management is required", "title": "Agama flow"}, {"location": "casa/developer/add-authn-methods/#about-casa-authentication-flow", "text": "Authentication in Casa is implemented through an Agama project called casa - in TUI you can see it listed in the Agama management screen. As a first step, the user is requested to enter the username and password combination, then depending on how the application is configured, personal user settings, and access policies defined, a second factor may be requested. The casa project allows to onboard new types of second factors (authentication mechanisms) and also provides a user experience that supports backtracking: if a user is asked to present a specific credential and that credential is not currently available or is not working, he can choose an alternative method for authentication where a different type of credential will be prompted. Users can backtrack several times.", "title": "About Casa authentication flow"}, {"location": "casa/developer/add-authn-methods/#flow-requisites", "text": "To code the flow corresponding to the authentication method to add, you can use the Agama project found here as a canvas. Ensure the following conditions are met so that it properly integrates in the main Casa flow: The flow will be passed an Agama map containing information of the person attempting the authentication. This input parameter will contain at least three keys: uid , inum , and name . uid and inum map directly to attributes stored in the user's profile and are never empty, name is a displayable name which may come from attribute givenName or displayName . All values are strings . The flow should terminate with a true outcome if the user successfully passes the challenge, presents the expected credential, etc. In any other case, false must be returned and an optional error message can be included for the caller flow ( io.jans.casa.authn.main ) to show it in the screen. Any additional data attached in the Finish instruction will not be processed. If for some reason your flow crashes, the corresponding exception will be printed to the logs, the caller will continue running, and the browser taken to the selector page where an error message will be displayed. Note your project may contain more flows to serve as utilitarians or simply to break down the authentication flow into smaller, more manageable pieces.", "title": "Flow requisites"}, {"location": "casa/developer/add-authn-methods/#about-templates", "text": "Regarding UI templates, it is recommended to re-use a couple of Freemarker macros available in the casa project. This will allow your flow's UI to have the same look-and-feel of flows bundled out-of-the box, like OTP and fido. Additionally this will allow to properly incorporate backtracking. Import the commons template in your UI page: <#import \"../kz1vc3/commons.ftlh\" as com> Copy the above line of code in the first line of your templates, preferably. Note you may need to add extra ../ fragments in the path to commons.ftlh depending on the directory level where your template resides inside the web subdirectory of your Agama project. Then call the main macro and supply your markup, like this: <@com.main> <!-- your markup here --> <@com.main> The above will generate a page incorporating the required CSS files and will render the header and footer appropriately while leaving your content in the center of the page. The casa project makes heavy use the Tachyons CSS. You may like to use those for building templates instead of incorporating yet another styling framework. It is highly recommended to include the following near the bottom of your markup (still inside the main call block): <@com.alternative /> This will render a form with a text and a link that will allow users to \"escape\" from your flow and take another route, i.e. to backtrack: Then, in your flow's code, you handle the escape this way: data = RRF \"mytemplate.ftlh\" ... When data.skipped is \"\" Finish false The above means your flow can finish with false not only if the authentication did not succeed but also when users wants to backtrack.", "title": "About templates"}, {"location": "casa/developer/add-authn-methods/#the-selector-page", "text": "When backtracking, a selector page is shown where all available methods for the given user are displayed - sorted by strength. From here, the user can take another route to be challenged for an alternative credential. Every element in the list has an icon and descriptive text associated. These elements are configurable and for the case of adding an authentication method, both icon and text should be supplied. To do so, locate in TUI the casa Agama project. See how the flow io.jans.casa.authn.main has a selector section in its configurations. This is a dictionary (JSON object) where keys are qualified names of flows and values are dictionaries at the same time - this where you can provide the required info. For example, if your authentication method is backed by a flow com.acme.authn.food , the casa project configuration may look like { \"io.jans.casa.authn.main\": { \"selector\": { \"com.acme.authn.food\": { \"icon\": \"<i class='fas fa-pizza-slice'></i>\", \"text\": \"A sentence describing what the user is supposed to present in the next screen\" }, ... } }, ... } Alternatively, a pointer to a localized message can be used instead of text . This is the recommended practice if localization/internationalization is relevant. In this case, something like the below will work: ... \"com.acme.authn.food\": { \"icon\": \"<i class='fas fa-pizza-slice'></i>\", \"textKey\": \"foodAuth.methodTitle\" } ... as long as the message key foodAuth.methodTitle is defined in the project's labels.txt file, or elsewhere in another project. Note textKey takes precedence over text when rendering the page. Both icon and textKey (or text ) may contain HTML markup. In this example we are using the font awesome library available in the selector page for rendering a nice icon but we could have used any other thing here like an img tag, for instance. Ensure to properly escape double quotes if necessary. Also make the markup a one-liner: JSON strings cannot span several lines.", "title": "The selector page"}, {"location": "casa/developer/add-authn-methods/#recommended-practices", "text": "Note Ensure to go through this page before proceeding", "title": "Recommended practices"}, {"location": "casa/developer/add-authn-methods/#config-settings", "text": "Use a single place to store configuration settings for your authentication method. The most convenient place is in the Agama project itself. You may have configs associated to each flow in your project and they can be accessed directly in your flows code. Additionally, they can be easily read from your plugin's Java code this way: ips = io.jans.casa.misc.Utils.managedBean(IPersistenceService.class); JSONObject p = ips.getAgamaFlowConfigProperties(\"flow qname\"); Out-of-the-box methods in Casa employ this strategy. Also when you do this, every time a change in project configuration is detected, your Java code gets notified: a call to method reloadConfiguration of your extension is issued, see class SampleCredentialAuthnMethod in the sample credential plugin.", "title": "Config settings"}, {"location": "casa/developer/add-authn-methods/#retries", "text": "Giving the user only one chance to pass an authentication challenge is unfair. Code your flow so users have a couple of opportunities to fail before finishing with false as outcome. Agama's Repeat directive helps you cover this case.", "title": "Retries"}, {"location": "casa/developer/add-authn-methods/#key-questions", "text": "As you try to assemble your project, you will come up with some design decisions, for instance: How to model and store credentials associated to the authentication method? What kind of parameters are relevant for the authentication method? What's the algorithm for authenticating users once they have supplied a valid username/password combination? Depending on the answers, you may like to start instead with plugin development first. This is not always the case though, however, getting your hands on the plugin might help unclutter the path.", "title": "Key questions"}, {"location": "casa/developer/add-authn-methods/#enrollment-plugin", "text": "Coding a Casa plugin is mainly a Java development task. You can use the \"Sample credential\" plugin as a template to start the work. Ensure you have: A Jans Server installation that includes Jans Casa - prefer a VM environment over the CN edition for development purposes. Also, you'll need a way to connect to your server via SSH A copy of the Jans repository (a shallow clone of main branch is OK): https://github.com/JanssenProject/jans", "title": "Enrollment plugin"}, {"location": "casa/developer/add-authn-methods/#plugin-deployment", "text": "Start with deploying the plugin to get acquainted with the process: In the local development machine, cd to ./jans/jans-casa/plugins/samples/sample-cred Run mvn -Dmaven.test.skip package . This may take several minutes (lots of network requests). Once you get it done, the next time you can add the -o switch (offline mode) for faster results A target folder with a couple of jar files in it will be generated Access Casa admin console and in the plugins page, upload the file suffixed with jar-with-dependencies.jar . After one minute approximately, visit the \"Authentication methods\" page, check the \"Favorite color\" widget, and click on \"Save\". Then logout. Login again, this time with a non administrative account. In the landing page (user's dashboard), an item labeled \"Your favorite color\" will be shown on the left (under the \"2FA credentials\" heading). Also, a panel in the central area of the page will be added in accordance. Click on \"Your favorite color\" and you'll land a page to let Casa know what your favorite color is!. This color will be used as a second factor for authentication. Ensure you have enabled another method such as OTP so you can enroll an additional credential in order to be able to active 2FA for this account.", "title": "Plugin deployment"}, {"location": "casa/developer/add-authn-methods/#study-the-sample-project", "text": "Now it's time for you to go through the project folder checking one file at a time. Most of files contain comments that explain the purpose of things. Ensure you make a deep inspection of file ./src/main/resources/assets/user/cred_details.zul . It contains the markup of the page you visited earlier. Make an excursion to interface AuthnMethod found in shared maven module. Note it brings a couple of default methods. Class SampleCredentialAuthnMethod implements this interface.", "title": "Study the sample project"}, {"location": "casa/developer/add-authn-methods/#editing-the-project", "text": "Modifying the project may require you to edit files mainly with .java , .zul , or .properties extensions. Most Java classes used in this plugin can be found in: The repository you cloned earlier The ZK framework documentation Standard Java SE API docs You can remove the plugin and add it as many times as you like - no restarts are needed unless things go really weird. You can do so either via the admin console or by dropping/removing the file directly in the filesystem (the path is /opt/jans/jetty/jans-casa/plugins ).", "title": "Editing the project"}, {"location": "casa/developer/add-authn-methods/#page-tweaks", "text": "If you alter a .zul file and then package and redeploy the plugin, you will most probably not see any change taking effect in the UI page. This is because the ZK framework caches the .zul pages by default for a very long period. To change this behavior do the following: Connect to your VM and cd to /opt/gluu/jetty/jans-casa/webapps Extract ZK descriptor: # jar -xf jans-casa.war WEB-INF/zk.xml Locate XML tag file-check-period and remove it including its surrounding parent desktop-config Save the file and patch the application war: # jar -uf jans-casa.war WEB-INF/zk.xml Restart casa (e.g. systemctl casa restart ) From now on, any template change will take effect after 5 seconds.", "title": "Page tweaks"}, {"location": "casa/developer/overview/", "tags": ["Casa", "developer guide"], "text": "Developer guide # This page gives developers relevant pointers for several tasks including: Plugins development Configuration management Credentials enrollment Customization of Casa's authentication flow Plugins # A plugin is an artifact packaged in a Java ARchive ( jar file) that augments the functionalities available in your default Casa installation. The following is by no means an extensive list of things you can add via plugins: Menu items in user's menu, top-right dropdown menu, or admin's dashboard menu UI pages with arbitrary content (and backend-functionality!), this also applies for the admin dashboard Static files (e.g. Javascript, images, stylesheets, etc.) REST services Authentication mechanisms to be supported by the application In addition to the above: Any plugin can have easy access to the underlying Jans Server database Plugins can onboard their own libraries (jar files) and classes Tools # Acquaintance with the following technologies is recommended: Java 11 or higher, maven ZK 9 framework PF4J framework HTML/CSS/Javascript The underlying database engine used by your Jans Server installation, e.g. PostgreSQL, MySQL, etc. Sample plugins # The best way to start learning Casa plugin development is by playing with the sample plugins you can find here . Clone the repository (a shallow clone of main branch is fine), cd to one of the directories in the folder and run mvn package , then upload the resulting jar-with-dependencies through the administration console. Configuration management # Most aspects of Casa that are configurable through the admin console UI can be programmatically operated using the configuration API. A formal description can be found here . Note all endpoints are protected by OAuth tokens which must have the https://jans.io/casa.config scope. Credentials enrollment # Casa has enrollment capabilities built-in but there are use cases where credential enrollment needs to happen elsewhere in your app ecosystem. A typical scenario is in a user registration application, where users are asked to enroll strong authentication credentials during account creation. To facilitate these tasks, Casa exposes APIs for enrolling the following types of authenticators: Phone numbers for SMS OTP OTP apps or tokens FIDO2 security keys Note Per spec FIDO 2 credentials can only be enrolled from a page belonging to the same domain or subdomain of your Gluu Server. In addition to the above, the API also provides endpoints to query the number/type of credentials currently enrolled by a user as well as means to turn 2FA on and off. Customizing the authentication flow # The authentication experience the user faces when trying to access Casa is implemented in an Agama project which is attached to the authentication server when Casa is installed. As with all authentication flows in Janssen, they belong to (run in the context of) the jans-auth application. This distinction is important because jans-auth and casa are separate Java webapps executed on different Jetty instances. In Casa flow, the user is requested to enter the username and password combination, then depending on how the application is configured, personal user settings, and access policies defined, a second factor may be requested. While this may cater most companies requirements, sometimes there is the need to customize the authentication experience. In fact, Agama facilitates this by design. Here are some things companies would like to do: Alter the UI pages - e.g. look-and-feel, structure, etc. Support more authentication methods Add links to the initial screen to take users to different authentication paths, for instance, to leverage social sites login Include an account registration process Include an extra final screen in case of password expiration Add a \"forgot password\" link Important You might be tempted to take the Agama project archive, apply some editions, add files to it, repack, and redeploy it. While this might seem the easiest thing to do, it is also the worst thing to do. Authentication journeys can be extended/tailored by means of creating additional projects. Try not to hack/patch the original project. Casa ACR update # Given the warning above, there has to be a way to launch a different Agama flow than the one used by default to log into Casa. This can be achieved by supplying a value for Casa's acr startup variable: in VM-based installations, locate the file /etc/default/casa in and modify the variable as needed. The format is agama_<qualified-name-of-your-flow> . Then restart Casa. Requisites # Regardless of the customization required, it is desirable to get acquaintance with Agama framework . This is a good time to go through the Agama developer guide pages found in the Administration section of Jans Server docs. Specifically, several of the Agama advanced usages will help you materialize your requirements. Extract the Agama project to your development machine. It is useful to get an idea of how and what the out-of-the-box project does. Also, keep the Freemarker manual at hand. Page customizations # The UI pages of the default Casa flow resemble the design of the Casa app itself. Also, modifications applied through the \"custom branding\" functionalities are automatically reflected in flow pages without any sort of intervention. This is neat, but if you need to go further, you will have to code the UI pages your own based on the existing ones. For this purpose, create a new Agama project with one flow in it. Pick one of the pages you want to change from the original project and build your own - initially keep it really simple: a dummy page is OK. From your new flow, use the Trigger directive to launch flow io.jans.casa.authn.main . Add an Override templates directive to your Trigger so the page in Casa project is superseded by the page you are creating. This is explained here . Pack your new project and deploy it. Wait for around 30 seconds and try to log into Casa to see the changes. Note you have to configure casa so your flow is launched, not the default one, ie. io.jans.casa.authn.main . This was explained earlier . Do as many changes as needed to your page. Then pick another page to alter and feed your Override templates accordingly. Repeat until your are done. Recall there is no need to restart jans-auth or casa . In some cases, the original look-and-feel may be satisfying but it's the text content what you would like to change. Agama engine supports localization and internationalization as explained here so you can supply translated messages in your own project and make templates use those. Note Casa is only bundled with a set of \"default\" labels out-of-the box and thus pages don't change content regardless of browser's language or location. By overriding templates and providing labels in several languages, you can achieve full localization/internationalization in the authentication UI. Support more authentication methods # This is probably the most common requirement. Visit this page to learn more. Other forms of customization # Most forms of customization can be tackled using flow cancellation. Through cancellation, a flow can be aborted while running and the control returned to one of its callers. Learn more about this topic here . As an example, let's assume you want to add a \"don't have an account? register here\" button in the initial screen of Casa flow. Here's what you can do: Create a new Agama project with one flow in it. Copy the page that prompts username and password into your project. Below the login button, add a form containing markup like <button type=\"submit\" name=\"_abort\">don't have an account? register here</button> In your flow, let's call it A , use the Trigger directive to launch flow io.jans.casa.authn.main . Add an Override templates directive to your Trigger so the original login page in Casa project is superseded by the page you created Create another flow, let's call it B . This will be the \"registration\" flow which will present one or more screens to grab data in order to create an account for the user. Make B finish with true outcome if the account was successfully created, otherwise finish with false Back in flow A , add code to check if io.jans.casa.authn.main was aborted, if so, launch flow B . For simplicity, if B didn't go well, terminate A If B went well, show the original login form, that is, no registration button this time Add code for termination So flow A will end up looking more or less like this: ... result = Trigger io.jans.casa.authn.main Override templates \"kz1vc3/main.ftlh\" \"newPage.ftlh\" When result.aborted is true //registration button was clicked result = Trigger B When result.success is false Finish false result = Trigger io.jans.casa.authn.main Finish result Here we have taken a simplistic approach to make the example concise. In practice you may like to be more elaborated and include an \"already have an account?\" button in the registration page, which could create a sort of navigational loop. Here the Repeat directive will emerge in your code for sure. Note When trying to customize an existing flow, familiarize with all possible paths the flow can take you to. Consider all possible screens and determine which require adjustments and the points at which cancellation is of use. Sometimes you will have to glance its .flow file (Agama code) to get a better idea.", "title": "Overview"}, {"location": "casa/developer/overview/#developer-guide", "text": "This page gives developers relevant pointers for several tasks including: Plugins development Configuration management Credentials enrollment Customization of Casa's authentication flow", "title": "Developer guide"}, {"location": "casa/developer/overview/#plugins", "text": "A plugin is an artifact packaged in a Java ARchive ( jar file) that augments the functionalities available in your default Casa installation. The following is by no means an extensive list of things you can add via plugins: Menu items in user's menu, top-right dropdown menu, or admin's dashboard menu UI pages with arbitrary content (and backend-functionality!), this also applies for the admin dashboard Static files (e.g. Javascript, images, stylesheets, etc.) REST services Authentication mechanisms to be supported by the application In addition to the above: Any plugin can have easy access to the underlying Jans Server database Plugins can onboard their own libraries (jar files) and classes", "title": "Plugins"}, {"location": "casa/developer/overview/#tools", "text": "Acquaintance with the following technologies is recommended: Java 11 or higher, maven ZK 9 framework PF4J framework HTML/CSS/Javascript The underlying database engine used by your Jans Server installation, e.g. PostgreSQL, MySQL, etc.", "title": "Tools"}, {"location": "casa/developer/overview/#sample-plugins", "text": "The best way to start learning Casa plugin development is by playing with the sample plugins you can find here . Clone the repository (a shallow clone of main branch is fine), cd to one of the directories in the folder and run mvn package , then upload the resulting jar-with-dependencies through the administration console.", "title": "Sample plugins"}, {"location": "casa/developer/overview/#configuration-management", "text": "Most aspects of Casa that are configurable through the admin console UI can be programmatically operated using the configuration API. A formal description can be found here . Note all endpoints are protected by OAuth tokens which must have the https://jans.io/casa.config scope.", "title": "Configuration management"}, {"location": "casa/developer/overview/#credentials-enrollment", "text": "Casa has enrollment capabilities built-in but there are use cases where credential enrollment needs to happen elsewhere in your app ecosystem. A typical scenario is in a user registration application, where users are asked to enroll strong authentication credentials during account creation. To facilitate these tasks, Casa exposes APIs for enrolling the following types of authenticators: Phone numbers for SMS OTP OTP apps or tokens FIDO2 security keys Note Per spec FIDO 2 credentials can only be enrolled from a page belonging to the same domain or subdomain of your Gluu Server. In addition to the above, the API also provides endpoints to query the number/type of credentials currently enrolled by a user as well as means to turn 2FA on and off.", "title": "Credentials enrollment"}, {"location": "casa/developer/overview/#customizing-the-authentication-flow", "text": "The authentication experience the user faces when trying to access Casa is implemented in an Agama project which is attached to the authentication server when Casa is installed. As with all authentication flows in Janssen, they belong to (run in the context of) the jans-auth application. This distinction is important because jans-auth and casa are separate Java webapps executed on different Jetty instances. In Casa flow, the user is requested to enter the username and password combination, then depending on how the application is configured, personal user settings, and access policies defined, a second factor may be requested. While this may cater most companies requirements, sometimes there is the need to customize the authentication experience. In fact, Agama facilitates this by design. Here are some things companies would like to do: Alter the UI pages - e.g. look-and-feel, structure, etc. Support more authentication methods Add links to the initial screen to take users to different authentication paths, for instance, to leverage social sites login Include an account registration process Include an extra final screen in case of password expiration Add a \"forgot password\" link Important You might be tempted to take the Agama project archive, apply some editions, add files to it, repack, and redeploy it. While this might seem the easiest thing to do, it is also the worst thing to do. Authentication journeys can be extended/tailored by means of creating additional projects. Try not to hack/patch the original project.", "title": "Customizing the authentication flow"}, {"location": "casa/developer/overview/#casa-acr-update", "text": "Given the warning above, there has to be a way to launch a different Agama flow than the one used by default to log into Casa. This can be achieved by supplying a value for Casa's acr startup variable: in VM-based installations, locate the file /etc/default/casa in and modify the variable as needed. The format is agama_<qualified-name-of-your-flow> . Then restart Casa.", "title": "Casa ACR update"}, {"location": "casa/developer/overview/#requisites", "text": "Regardless of the customization required, it is desirable to get acquaintance with Agama framework . This is a good time to go through the Agama developer guide pages found in the Administration section of Jans Server docs. Specifically, several of the Agama advanced usages will help you materialize your requirements. Extract the Agama project to your development machine. It is useful to get an idea of how and what the out-of-the-box project does. Also, keep the Freemarker manual at hand.", "title": "Requisites"}, {"location": "casa/developer/overview/#page-customizations", "text": "The UI pages of the default Casa flow resemble the design of the Casa app itself. Also, modifications applied through the \"custom branding\" functionalities are automatically reflected in flow pages without any sort of intervention. This is neat, but if you need to go further, you will have to code the UI pages your own based on the existing ones. For this purpose, create a new Agama project with one flow in it. Pick one of the pages you want to change from the original project and build your own - initially keep it really simple: a dummy page is OK. From your new flow, use the Trigger directive to launch flow io.jans.casa.authn.main . Add an Override templates directive to your Trigger so the page in Casa project is superseded by the page you are creating. This is explained here . Pack your new project and deploy it. Wait for around 30 seconds and try to log into Casa to see the changes. Note you have to configure casa so your flow is launched, not the default one, ie. io.jans.casa.authn.main . This was explained earlier . Do as many changes as needed to your page. Then pick another page to alter and feed your Override templates accordingly. Repeat until your are done. Recall there is no need to restart jans-auth or casa . In some cases, the original look-and-feel may be satisfying but it's the text content what you would like to change. Agama engine supports localization and internationalization as explained here so you can supply translated messages in your own project and make templates use those. Note Casa is only bundled with a set of \"default\" labels out-of-the box and thus pages don't change content regardless of browser's language or location. By overriding templates and providing labels in several languages, you can achieve full localization/internationalization in the authentication UI.", "title": "Page customizations"}, {"location": "casa/developer/overview/#support-more-authentication-methods", "text": "This is probably the most common requirement. Visit this page to learn more.", "title": "Support more authentication methods"}, {"location": "casa/developer/overview/#other-forms-of-customization", "text": "Most forms of customization can be tackled using flow cancellation. Through cancellation, a flow can be aborted while running and the control returned to one of its callers. Learn more about this topic here . As an example, let's assume you want to add a \"don't have an account? register here\" button in the initial screen of Casa flow. Here's what you can do: Create a new Agama project with one flow in it. Copy the page that prompts username and password into your project. Below the login button, add a form containing markup like <button type=\"submit\" name=\"_abort\">don't have an account? register here</button> In your flow, let's call it A , use the Trigger directive to launch flow io.jans.casa.authn.main . Add an Override templates directive to your Trigger so the original login page in Casa project is superseded by the page you created Create another flow, let's call it B . This will be the \"registration\" flow which will present one or more screens to grab data in order to create an account for the user. Make B finish with true outcome if the account was successfully created, otherwise finish with false Back in flow A , add code to check if io.jans.casa.authn.main was aborted, if so, launch flow B . For simplicity, if B didn't go well, terminate A If B went well, show the original login form, that is, no registration button this time Add code for termination So flow A will end up looking more or less like this: ... result = Trigger io.jans.casa.authn.main Override templates \"kz1vc3/main.ftlh\" \"newPage.ftlh\" When result.aborted is true //registration button was clicked result = Trigger B When result.success is false Finish false result = Trigger io.jans.casa.authn.main Finish result Here we have taken a simplistic approach to make the example concise. In practice you may like to be more elaborated and include an \"already have an account?\" button in the registration page, which could create a sort of navigational loop. Here the Repeat directive will emerge in your code for sure. Note When trying to customize an existing flow, familiarize with all possible paths the flow can take you to. Consider all possible screens and determine which require adjustments and the points at which cancellation is of use. Sometimes you will have to glance its .flow file (Agama code) to get a better idea.", "title": "Other forms of customization"}, {"location": "casa/plugins/2fa-settings/", "tags": ["Casa", "2FA"], "text": "2FA Settings Plugin # Overview # This plugin allows administrators to configure how and when 2FA is applied. Admins may: Specify the minimum number of credentials users must enroll before 2FA can be used Allow 2FA to be automatically enabled upon credential enrollment Prevent users to turn 2FA on and off their own Allow users to choose a preferred method of authentication When (2) is not used, option (3) is disabled. This is the default behavior exhibited in Casa where users explicitly enable or disable 2FA usage. When (2) is active, 2FA is turned on as soon as the user enrolls a credential and the minimum required is fulfilled. Bear in mind: Automatic enablement happens only via GUI: enrollments made using the API will have to turn 2FA on by means of the API itself Plugins attaching authentication methods to Casa have to explicitly call method notifyEnrollment of SndFactorAuthenticationUtils upon successful enrollments (see the javadocs). Also, 2FA is automatically turned on upon login for users with enough credentials registered and not having 2FA turned on yet. With (4) users may choose a preferred type of credential. This means that when requested for a second factor, a credential of such \"preferred\" type will be prompted first instead of the credential considered the \"strongest\". The strength associated to a method is equal to the numeric level assigned to the custom script that represents the method. For more restrictive scenarios, administrators have the option to remove the 2FA switch (3) from the user's dashboard. Additionally this plugin allows to: Choose from a set of predefined policies for when 2FA should be prompted: Always (at every login attempt) When user's location is unrecognized When user's device is unrecognized Users can define their own policy (based on the above) Set how long a location or device can be deemed as recognized Moreover, when administrators allow users to set their own strong authentication policy, users can: View the list of physical devices they have used to login (e.g. PC, tablet, phone) View the time and location (city) associated to the last login event Remove a device from the list (eg. when it should not be considered trustworthy anymore) A device/location is considered trustworthy when the user has presented a strong credential in order to login to Casa in such device/location. Subsequent login attempts from trustworthy (recognized) device/locations will not require them to present a second factor. Requirements # The plugin jar file must match the version of your Janssen Server installation. Installation # Download the plugin Log in to Casa using an administrator account Navigate to Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add How to use # For administrators, a new link labeled \"2FA settings\" appears in the dashboard menu to access the function. For regular users, proper details appear in the widget where 2FA is turned on. API # Configurations provided by this plugin can also be applied by means of the API exposed for this purpose. A formal description of the API can be found in this swagger file. Note all endpoints are protected by tokens which must have the https://jans.io/casa.config OAuth scope.", "title": "2FA Settings"}, {"location": "casa/plugins/2fa-settings/#2fa-settings-plugin", "text": "", "title": "2FA Settings Plugin"}, {"location": "casa/plugins/2fa-settings/#overview", "text": "This plugin allows administrators to configure how and when 2FA is applied. Admins may: Specify the minimum number of credentials users must enroll before 2FA can be used Allow 2FA to be automatically enabled upon credential enrollment Prevent users to turn 2FA on and off their own Allow users to choose a preferred method of authentication When (2) is not used, option (3) is disabled. This is the default behavior exhibited in Casa where users explicitly enable or disable 2FA usage. When (2) is active, 2FA is turned on as soon as the user enrolls a credential and the minimum required is fulfilled. Bear in mind: Automatic enablement happens only via GUI: enrollments made using the API will have to turn 2FA on by means of the API itself Plugins attaching authentication methods to Casa have to explicitly call method notifyEnrollment of SndFactorAuthenticationUtils upon successful enrollments (see the javadocs). Also, 2FA is automatically turned on upon login for users with enough credentials registered and not having 2FA turned on yet. With (4) users may choose a preferred type of credential. This means that when requested for a second factor, a credential of such \"preferred\" type will be prompted first instead of the credential considered the \"strongest\". The strength associated to a method is equal to the numeric level assigned to the custom script that represents the method. For more restrictive scenarios, administrators have the option to remove the 2FA switch (3) from the user's dashboard. Additionally this plugin allows to: Choose from a set of predefined policies for when 2FA should be prompted: Always (at every login attempt) When user's location is unrecognized When user's device is unrecognized Users can define their own policy (based on the above) Set how long a location or device can be deemed as recognized Moreover, when administrators allow users to set their own strong authentication policy, users can: View the list of physical devices they have used to login (e.g. PC, tablet, phone) View the time and location (city) associated to the last login event Remove a device from the list (eg. when it should not be considered trustworthy anymore) A device/location is considered trustworthy when the user has presented a strong credential in order to login to Casa in such device/location. Subsequent login attempts from trustworthy (recognized) device/locations will not require them to present a second factor.", "title": "Overview"}, {"location": "casa/plugins/2fa-settings/#requirements", "text": "The plugin jar file must match the version of your Janssen Server installation.", "title": "Requirements"}, {"location": "casa/plugins/2fa-settings/#installation", "text": "Download the plugin Log in to Casa using an administrator account Navigate to Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add", "title": "Installation"}, {"location": "casa/plugins/2fa-settings/#how-to-use", "text": "For administrators, a new link labeled \"2FA settings\" appears in the dashboard menu to access the function. For regular users, proper details appear in the widget where 2FA is turned on.", "title": "How to use"}, {"location": "casa/plugins/2fa-settings/#api", "text": "Configurations provided by this plugin can also be applied by means of the API exposed for this purpose. A formal description of the API can be found in this swagger file. Note all endpoints are protected by tokens which must have the https://jans.io/casa.config OAuth scope.", "title": "API"}, {"location": "casa/plugins/bioid/", "tags": ["Casa", "Biometrical"], "text": "BioID plugin # Overview # This plugin allows users to enroll their BioID facial biometrics. Requirements # A Janssen server installation with Casa installed A BioID account. Register on the BioID site Application credentials from the BWS Portal. Please register an application against your account. You will need the app identifier, app secret, storage and partition. Installation # Download the plugin jar. Log into Casa as an administrator, navigate to Administration Console > Casa plugins and add the plugin jar Restart the casa service: sudo systemctl restart jans-casa Using the TUI, navigate to Auth Server > Clients , open the details for Client for Casa , and add the following redirect URI: https://<hostname>/jans-casa/pl/bioid-plugin/user/interlude.zul . Replace <hostname> with the hostname of your server, and save the client. Run the following commands to generate the Agama flow file: git clone --depth 1 --branch main --no-checkout https://github.com/JanssenProject/jans.git cd jans/jans-casa/plugins/bioid/extras/agama zip -r casa-bioid.gama ./* 1. Transfer the casa-bioid.gama file to the server, and deploy it using the TUI 1. Using the TUI, export the sample configuration, edit it according to the specification below and import it back in Agama Configuration # { \"io.jans.agama.bioid.enroll\": { \"host\": \"https://<HOSTNAME>/jans-auth/fl/callback\", \"endpoint\": \"https://bws.bioid.com/extension/\", \"appIdentifier\": \"\", \"appSecret\": \"\", \"storage\": \"\", \"partition\": \"\" } } host : Replace <HOSTNAME> with the hostname of your server endpoint : BioID API endpoint. Leave as default appIdentifier : The app identifier string from BWS Portal - Configuration appSecret : The app secret from BWS Portal - Configuration storage : Storage value from BWS Portal - Configuration partition : Partition value from BWS Portal - Configuration How to use # The plugin provides a user menu. When clicking the Click to Enroll button, Casa launches the io.jans.agama.bioid.enroll flow on the authorization server. This flow queries the BioID database for existing enrollments for the user. If the user has not enrolled, the flow presents the BWS GUI for enrollment. Upon success, the flow redirects back to a Casa landing page. Deletion of credentials is not supported as of now because Casa is unaware of enrollment status of a user.", "title": "BioID"}, {"location": "casa/plugins/bioid/#bioid-plugin", "text": "", "title": "BioID plugin"}, {"location": "casa/plugins/bioid/#overview", "text": "This plugin allows users to enroll their BioID facial biometrics.", "title": "Overview"}, {"location": "casa/plugins/bioid/#requirements", "text": "A Janssen server installation with Casa installed A BioID account. Register on the BioID site Application credentials from the BWS Portal. Please register an application against your account. You will need the app identifier, app secret, storage and partition.", "title": "Requirements"}, {"location": "casa/plugins/bioid/#installation", "text": "Download the plugin jar. Log into Casa as an administrator, navigate to Administration Console > Casa plugins and add the plugin jar Restart the casa service: sudo systemctl restart jans-casa Using the TUI, navigate to Auth Server > Clients , open the details for Client for Casa , and add the following redirect URI: https://<hostname>/jans-casa/pl/bioid-plugin/user/interlude.zul . Replace <hostname> with the hostname of your server, and save the client. Run the following commands to generate the Agama flow file: git clone --depth 1 --branch main --no-checkout https://github.com/JanssenProject/jans.git cd jans/jans-casa/plugins/bioid/extras/agama zip -r casa-bioid.gama ./* 1. Transfer the casa-bioid.gama file to the server, and deploy it using the TUI 1. Using the TUI, export the sample configuration, edit it according to the specification below and import it back in", "title": "Installation"}, {"location": "casa/plugins/bioid/#agama-configuration", "text": "{ \"io.jans.agama.bioid.enroll\": { \"host\": \"https://<HOSTNAME>/jans-auth/fl/callback\", \"endpoint\": \"https://bws.bioid.com/extension/\", \"appIdentifier\": \"\", \"appSecret\": \"\", \"storage\": \"\", \"partition\": \"\" } } host : Replace <HOSTNAME> with the hostname of your server endpoint : BioID API endpoint. Leave as default appIdentifier : The app identifier string from BWS Portal - Configuration appSecret : The app secret from BWS Portal - Configuration storage : Storage value from BWS Portal - Configuration partition : Partition value from BWS Portal - Configuration", "title": "Agama Configuration"}, {"location": "casa/plugins/bioid/#how-to-use", "text": "The plugin provides a user menu. When clicking the Click to Enroll button, Casa launches the io.jans.agama.bioid.enroll flow on the authorization server. This flow queries the BioID database for existing enrollments for the user. If the user has not enrolled, the flow presents the BWS GUI for enrollment. Upon success, the flow redirects back to a Casa landing page. Deletion of credentials is not supported as of now because Casa is unaware of enrollment status of a user.", "title": "How to use"}, {"location": "casa/plugins/consent-management/", "tags": ["Casa", "Consent"], "text": "Consent Management Plugin # Overview # The Consent Management plugin gives end-users the ability to view and revoke previously granted authorizations provided to applications accessed with their account in a Janssen Server. Requirements # The plugin jar file must match the version of your Casa (and Janssen Server) installation. Installation # Download the plugin Login to Casa using an administrator account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add User guide # For information on how to use the plugin, see the User Guide", "title": "Consent Management"}, {"location": "casa/plugins/consent-management/#consent-management-plugin", "text": "", "title": "Consent Management Plugin"}, {"location": "casa/plugins/consent-management/#overview", "text": "The Consent Management plugin gives end-users the ability to view and revoke previously granted authorizations provided to applications accessed with their account in a Janssen Server.", "title": "Overview"}, {"location": "casa/plugins/consent-management/#requirements", "text": "The plugin jar file must match the version of your Casa (and Janssen Server) installation.", "title": "Requirements"}, {"location": "casa/plugins/consent-management/#installation", "text": "Download the plugin Login to Casa using an administrator account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add", "title": "Installation"}, {"location": "casa/plugins/consent-management/#user-guide", "text": "For information on how to use the plugin, see the User Guide", "title": "User guide"}, {"location": "casa/plugins/custom-branding/", "tags": ["Casa", "Branding"], "text": "Custom Branding Plugin # Overview # This plugin allows admins to apply a design customization by choosing colors, favicon, logo, and footer text to match their company's look and feel. Alternatively, they can supply all assets (images and CSS files) externally to cover more demanding needs. Requirements # The plugin jar file must match the version of your Casa (and Janssen Server) installation. Installation # Download the plugin Login to Casa using an administrator account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add How to use # See the custom branding page for full instructions.", "title": "Custom Branding"}, {"location": "casa/plugins/custom-branding/#custom-branding-plugin", "text": "", "title": "Custom Branding Plugin"}, {"location": "casa/plugins/custom-branding/#overview", "text": "This plugin allows admins to apply a design customization by choosing colors, favicon, logo, and footer text to match their company's look and feel. Alternatively, they can supply all assets (images and CSS files) externally to cover more demanding needs.", "title": "Overview"}, {"location": "casa/plugins/custom-branding/#requirements", "text": "The plugin jar file must match the version of your Casa (and Janssen Server) installation.", "title": "Requirements"}, {"location": "casa/plugins/custom-branding/#installation", "text": "Download the plugin Login to Casa using an administrator account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add", "title": "Installation"}, {"location": "casa/plugins/custom-branding/#how-to-use", "text": "See the custom branding page for full instructions.", "title": "How to use"}, {"location": "casa/plugins/email-otp/", "tags": ["Casa", "OTP"], "text": "E-mail OTP Plugin # Overview # With this plugin, administrators can onboard a new type of authentication factor consisting of one-time passcodes (OTP) delivered to the user's inbox. This plugin simply shows a list of the already registered e-mail addresses of the user in the UI of Casa, however the accompanying Agama project contributes a new option in the authentication experience where the user is prompted to enter an OTP delivered to one of his e-mail addresses, if any. By adding the plugin and the corresponding Agama project to your server, all users having at least one e-mail address in his profile (database attribute mail ) will be given the option to get a passcode delivered and then prompted for such as a form of 2FA. Requirements # The SMTP configuration must be previously populated in the Jans Server. For this purpose you can use an administrative tool like TUI. Visit the SMTP section and fill the values requested. Ensure to run and pass the test presented before proceeding. Then, restart the authentication server. Installation # Plugin # Download the plugin jar file Login to Casa using an administrative account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin file Click on Add and wait for one minute Visit the Authentication methods section of the admin console. Tick the Registered e-mails widget, drag it to the desired position, and finally hit Save Agama project # Download the project archive Deploy the project onto the server - you can use TUI for this task Parameterize the project - you can use the project's sample configuration as a guide. The below summarizes the properties used: otp_length : Number of digits the OTPs will have (passcode length) otp_lifetime : Passcode expiration in minutes subject : Subject to use in e-mail messages. You can use %s as a placeholder to insert the value of the generated OTP message : Body of e-mail messages. You can use %s as a placeholder to insert the value of the generated OTP. Basic HTML markup is supported; ensure to properly escape characters like double quotes - keep in mind this is JSON content Parameterize the casa project: in the casa project configuration, locate the selector section under io.jans.casa.authn.main flow and add an entry with key io.jans.casa.authn.emailotp . Assign an icon and a pointer to a short descriptive text. Example: ... \"io.jans.casa.authn.emailotp\": { \"icon\": \"<i class='fas fa-envelope' data-fa-transform='shrink-1'></i>\", \"textKey\": \"email2fa.selector_text\" } ... Test # Create one or more testing users with real e-mail addresses associated to their accounts Log into casa with such users and enroll some credential, like a passkey, SuperGluu, etc. Then turn 2fA for them. Logout and login again. A new option for receiving OTPs via e-mail will be presented User guide # Using the plugin is straightforward and does not require further explanation.", "title": "Email OTP"}, {"location": "casa/plugins/email-otp/#e-mail-otp-plugin", "text": "", "title": "E-mail OTP Plugin"}, {"location": "casa/plugins/email-otp/#overview", "text": "With this plugin, administrators can onboard a new type of authentication factor consisting of one-time passcodes (OTP) delivered to the user's inbox. This plugin simply shows a list of the already registered e-mail addresses of the user in the UI of Casa, however the accompanying Agama project contributes a new option in the authentication experience where the user is prompted to enter an OTP delivered to one of his e-mail addresses, if any. By adding the plugin and the corresponding Agama project to your server, all users having at least one e-mail address in his profile (database attribute mail ) will be given the option to get a passcode delivered and then prompted for such as a form of 2FA.", "title": "Overview"}, {"location": "casa/plugins/email-otp/#requirements", "text": "The SMTP configuration must be previously populated in the Jans Server. For this purpose you can use an administrative tool like TUI. Visit the SMTP section and fill the values requested. Ensure to run and pass the test presented before proceeding. Then, restart the authentication server.", "title": "Requirements"}, {"location": "casa/plugins/email-otp/#installation", "text": "", "title": "Installation"}, {"location": "casa/plugins/email-otp/#plugin", "text": "Download the plugin jar file Login to Casa using an administrative account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin file Click on Add and wait for one minute Visit the Authentication methods section of the admin console. Tick the Registered e-mails widget, drag it to the desired position, and finally hit Save", "title": "Plugin"}, {"location": "casa/plugins/email-otp/#agama-project", "text": "Download the project archive Deploy the project onto the server - you can use TUI for this task Parameterize the project - you can use the project's sample configuration as a guide. The below summarizes the properties used: otp_length : Number of digits the OTPs will have (passcode length) otp_lifetime : Passcode expiration in minutes subject : Subject to use in e-mail messages. You can use %s as a placeholder to insert the value of the generated OTP message : Body of e-mail messages. You can use %s as a placeholder to insert the value of the generated OTP. Basic HTML markup is supported; ensure to properly escape characters like double quotes - keep in mind this is JSON content Parameterize the casa project: in the casa project configuration, locate the selector section under io.jans.casa.authn.main flow and add an entry with key io.jans.casa.authn.emailotp . Assign an icon and a pointer to a short descriptive text. Example: ... \"io.jans.casa.authn.emailotp\": { \"icon\": \"<i class='fas fa-envelope' data-fa-transform='shrink-1'></i>\", \"textKey\": \"email2fa.selector_text\" } ...", "title": "Agama project"}, {"location": "casa/plugins/email-otp/#test", "text": "Create one or more testing users with real e-mail addresses associated to their accounts Log into casa with such users and enroll some credential, like a passkey, SuperGluu, etc. Then turn 2fA for them. Logout and login again. A new option for receiving OTPs via e-mail will be presented", "title": "Test"}, {"location": "casa/plugins/email-otp/#user-guide", "text": "Using the plugin is straightforward and does not require further explanation.", "title": "User guide"}, {"location": "casa/plugins/accts-linking/account-linking-index/", "tags": ["Casa", "Accounts Linking"], "text": "Accounts Linking Plugin # Overview # This plugin allows users to \"link\" their local Jans account with existing accounts at third-party identity providers like OIDC OPs and social sites, e.g. Apple, Facebook, Google, etc. Besides the usual onboarding of a plugin jar file in Casa, administrators must deploy a number of additional components. This will be regarded later. However let's summary the key points of the accounts linking experience: When a user tries to login to Casa, the usual username/password form is presented but also a list of links that can take him to external sites (third-party identity providers) where authentication takes place Once authenticated, user profile data is grabbed from the external site - this is all backchannel A process called attribute mapping is performed on profile data. This is a transformation process that turns incoming profile data into a shape compatible with a regular Jans database user entry If the mapped profile data matches an existing user in the Jans database, the existing entry is updated with the incoming data, otherwise, a new entry is inserted - this is called user provisioning . When provisioning occurs, the account has no password associated Finally the user is given access to Casa From the perspective of a user already logged into Casa, the experience is as follows: In casa, a menu item is provided which takes the user to a (Casa) page that shows a list of third-party identity providers. For every provider there are options to trigger linking in case there is no account linked yet (external site authentication is launched), or to remove the linked account from the user profile If an account has no password assigned, removal of linked accounts is not allowed. However, a functionality for the user to assign himself a password is provided Components deployment # The pieces that allow materialization of the experience summarized above are the following: a) The Casa plugin jar file b) The Agama inbound identity project c) The Casa accounts linking Agama project Most of work is demanded on setting up project c , where configuration of identity providers and attribute mapping tuning takes place. In the following, it is assumed you have a VM-based installation of Jans Server (or Gluu Flex) available with Casa installed. In a separate machine, ensure you have SSH/SCP/SFTP access to such server and git installed. Download the plugin jar file https://maven.jans.io/maven/io/jans/casa/plugins/acct-linking/0.0.0-nightly/acct-linking-0.0.0-nightly-jar-with-dependencies.jar and copy to your server's /opt/jans/jetty/jans-casa/plugins Download the utility jar file https://maven.jans.io/maven/io/jans/agama-inbound/0.0.0-nightly/agama-inbound-0.0.0-nightly.jar and copy to your server's /opt/jans/jetty/jans-auth/custom/libs In TUI, visit the Clients screen, locate the client labeled \"Client for Casa\". Add the following redirect URI to the list: https://<your-jans-host>/jans-casa/pl/acct-linking/user/interlude.zul . Replace the name of your Jans server accordingly Run the following commands to generate the archive of the Agama inbound identity project git clone --depth 1 --branch main --no-checkout https://github.com/JanssenProject/jans.git cd jans git sparse-checkout init --cone git sparse-checkout set docs/agama-catalog/jans/inboundID/project git checkout main cd docs/agama-catalog/jans/inboundID/project zip -r inbound.zip * Download the Casa accounts linking Agama project https://maven.jans.io/maven/io/jans/casa/plugins/acct-linking-agama/0.0.0-nightly/acct-linking-agama-0.0.0-nightly-project.zip Transfer the two zip files to a location in the server, deploy both archives using TUI (Agama menu) Finally restart the authentication server Configuration # The first step is figuring out the external sites to support. Keep in mind only OpenID or OAuth 2.0 based providers can be onboarded. There is not support for SAML IDPs. The procedures for getting configuration settings in order to integrate third party providers vary widely. Here, only basic guidelines are given: If the provider is OpenId-compliant and supports dynamic client registration, obtain the OP URL and the scopes list to use when requesting user profile information. Most of times the scopes openid , profile and email will fit the bill If the provider is OpenId-compliant and does not support dynamic client registration, obtain the OP URL and scopes as in the previous case, and also a client ID and secret If the provider does not support OpenId. Obtain the following: The authorization endpoint URL The token endpoint URL The endpoint URL where profile data can be retrieved Client credentials (ID and secret) Scopes to use when requesting user profile information The steps required to grab the above data vary among providers. Normally this is obtained through a sort of administrative developer GUI tool. If you are prompted for a \"redirect URI\" in such tool, provide https://<your-jans-host>/jans-auth/fl/callback . Now it's time to supply the settings grabbed. The component these configurations are injected to is the Casa accounts linking Agama project. To make the effort easier, this project is bundled with some dummy configuration properties you can use as a template. Proceed as follows: In TUI, open the Agama tab and scroll through the list of projects until the casa-account-linking is highlighted Open the configuration management dialog (press c ) and choose to export the sample configuration to a file on disk Apply changes as needed - this is covered in a separate doc page here . Note you can add or remove sections in the file at will, and that providers can also be disabled so they are not listed in the login page or in Casa app Still in TUI, choose to import the file you have edited For VM-based installations, update the file /etc/default/jans-casa . Locate a segment that reads -Dacr= and assign agama_io.jans.casa.authn.acctlinking as new value. This will make Casa use the flow found in the accounts linking project - not the flow bundled out-of-the-box. Finally restart Casa and conduct your testing. You will now see the login page contains a list of links to the configured identity providers.", "title": "Accounts Linking Plugin"}, {"location": "casa/plugins/accts-linking/account-linking-index/#accounts-linking-plugin", "text": "", "title": "Accounts Linking Plugin"}, {"location": "casa/plugins/accts-linking/account-linking-index/#overview", "text": "This plugin allows users to \"link\" their local Jans account with existing accounts at third-party identity providers like OIDC OPs and social sites, e.g. Apple, Facebook, Google, etc. Besides the usual onboarding of a plugin jar file in Casa, administrators must deploy a number of additional components. This will be regarded later. However let's summary the key points of the accounts linking experience: When a user tries to login to Casa, the usual username/password form is presented but also a list of links that can take him to external sites (third-party identity providers) where authentication takes place Once authenticated, user profile data is grabbed from the external site - this is all backchannel A process called attribute mapping is performed on profile data. This is a transformation process that turns incoming profile data into a shape compatible with a regular Jans database user entry If the mapped profile data matches an existing user in the Jans database, the existing entry is updated with the incoming data, otherwise, a new entry is inserted - this is called user provisioning . When provisioning occurs, the account has no password associated Finally the user is given access to Casa From the perspective of a user already logged into Casa, the experience is as follows: In casa, a menu item is provided which takes the user to a (Casa) page that shows a list of third-party identity providers. For every provider there are options to trigger linking in case there is no account linked yet (external site authentication is launched), or to remove the linked account from the user profile If an account has no password assigned, removal of linked accounts is not allowed. However, a functionality for the user to assign himself a password is provided", "title": "Overview"}, {"location": "casa/plugins/accts-linking/account-linking-index/#components-deployment", "text": "The pieces that allow materialization of the experience summarized above are the following: a) The Casa plugin jar file b) The Agama inbound identity project c) The Casa accounts linking Agama project Most of work is demanded on setting up project c , where configuration of identity providers and attribute mapping tuning takes place. In the following, it is assumed you have a VM-based installation of Jans Server (or Gluu Flex) available with Casa installed. In a separate machine, ensure you have SSH/SCP/SFTP access to such server and git installed. Download the plugin jar file https://maven.jans.io/maven/io/jans/casa/plugins/acct-linking/0.0.0-nightly/acct-linking-0.0.0-nightly-jar-with-dependencies.jar and copy to your server's /opt/jans/jetty/jans-casa/plugins Download the utility jar file https://maven.jans.io/maven/io/jans/agama-inbound/0.0.0-nightly/agama-inbound-0.0.0-nightly.jar and copy to your server's /opt/jans/jetty/jans-auth/custom/libs In TUI, visit the Clients screen, locate the client labeled \"Client for Casa\". Add the following redirect URI to the list: https://<your-jans-host>/jans-casa/pl/acct-linking/user/interlude.zul . Replace the name of your Jans server accordingly Run the following commands to generate the archive of the Agama inbound identity project git clone --depth 1 --branch main --no-checkout https://github.com/JanssenProject/jans.git cd jans git sparse-checkout init --cone git sparse-checkout set docs/agama-catalog/jans/inboundID/project git checkout main cd docs/agama-catalog/jans/inboundID/project zip -r inbound.zip * Download the Casa accounts linking Agama project https://maven.jans.io/maven/io/jans/casa/plugins/acct-linking-agama/0.0.0-nightly/acct-linking-agama-0.0.0-nightly-project.zip Transfer the two zip files to a location in the server, deploy both archives using TUI (Agama menu) Finally restart the authentication server", "title": "Components deployment"}, {"location": "casa/plugins/accts-linking/account-linking-index/#configuration", "text": "The first step is figuring out the external sites to support. Keep in mind only OpenID or OAuth 2.0 based providers can be onboarded. There is not support for SAML IDPs. The procedures for getting configuration settings in order to integrate third party providers vary widely. Here, only basic guidelines are given: If the provider is OpenId-compliant and supports dynamic client registration, obtain the OP URL and the scopes list to use when requesting user profile information. Most of times the scopes openid , profile and email will fit the bill If the provider is OpenId-compliant and does not support dynamic client registration, obtain the OP URL and scopes as in the previous case, and also a client ID and secret If the provider does not support OpenId. Obtain the following: The authorization endpoint URL The token endpoint URL The endpoint URL where profile data can be retrieved Client credentials (ID and secret) Scopes to use when requesting user profile information The steps required to grab the above data vary among providers. Normally this is obtained through a sort of administrative developer GUI tool. If you are prompted for a \"redirect URI\" in such tool, provide https://<your-jans-host>/jans-auth/fl/callback . Now it's time to supply the settings grabbed. The component these configurations are injected to is the Casa accounts linking Agama project. To make the effort easier, this project is bundled with some dummy configuration properties you can use as a template. Proceed as follows: In TUI, open the Agama tab and scroll through the list of projects until the casa-account-linking is highlighted Open the configuration management dialog (press c ) and choose to export the sample configuration to a file on disk Apply changes as needed - this is covered in a separate doc page here . Note you can add or remove sections in the file at will, and that providers can also be disabled so they are not listed in the login page or in Casa app Still in TUI, choose to import the file you have edited For VM-based installations, update the file /etc/default/jans-casa . Locate a segment that reads -Dacr= and assign agama_io.jans.casa.authn.acctlinking as new value. This will make Casa use the flow found in the accounts linking project - not the flow bundled out-of-the-box. Finally restart Casa and conduct your testing. You will now see the login page contains a list of links to the configured identity providers.", "title": "Configuration"}, {"location": "casa/plugins/accts-linking/accts-linking-agama/", "tags": ["Casa", "Accounts Linking", "Agama"], "text": "Accounts linking project configuration # Overview # The accounts linking Agama project must be configured in order to integrate third-party identity providers. The configuration of this project is supplied in a JSON file whose structure is like: { \"io.jans.casa.authn.acctlinking\": { \"providerID_1\": { ... }, \"providerID_2\": { ... }, ... } } Each property part of the JSON object io.jans.casa.auth.acctlinking holds the configuration of a different identity provider. Here's a how a typical configuration of a provider looks like: { \"displayName\": \"Goooogle\", \"flowQname\": \"io.jans.inbound.GenericProvider\", \"mappingClassField\": \"io.jans.casa.acctlinking.Mappings.GOOGLE\", \"oauthParams\": { \"authzEndpoint\": \"https://accounts.google.com/o/oauth2/v2/auth\", \"tokenEndpoint\": \"https://oauth2.googleapis.com/token\", \"userInfoEndpoint\": \"https://www.googleapis.com/oauth2/v3/userinfo\", \"clientId\": \"202403151302\", \"clientSecret\": \"m|a1l2d3i4t5a6S7h8a9k0i'r\u00bfa\", \"scopes\": [\"email\", \"profile\"] } } In this case, we are populating the configuration of an OAuth-based provider called \"Goooogle\". The tables shown in this page list all possible properties to configure a provider. Particularly, two properties deserve the most detail: flowQname . Agama projects are made up of flows - think of small \"web journeys\". This property must contain the name of an existing flow capable of interfacing with the identity provider of interest. Often, there is no need to write such \"interfacing\" flow. The below are ready-to-use and cover most of real-world cases, specifically OpenId/OAuth providers that support the authorization code grant (see section 1.3 of rfc6749 ): io.jans.inbound.GenericProvider . It implements the authorization code flow where the user's browser is taken to the external site. When authentication completes, a code is received at a designated redirect (callback) URL. With such code an access token is obtained as well as user's profile data. This flow supports dynamic client registration io.jans.inbound.Apple . It implements the authorization code flow with some nuances required in order to integrate \"Apple Sign In\" mappingClassField . This is key for performing the attribute mapping process and the user provisioning. The remainder of this document is dedicated to these two aspects Note Recall enabled is a handy property that can be used to temporarily \"deactive\" a given identity provider. Configuring attribute mappings # An introduction to attribute mapping can be found here . Unless an elaborated processing of attributes is required, a basic knowledge of Java language suffices to write a useful mapping. To write a mapping, you can use the samples provided as a guideline (see folder lib/io/jans/casa/acctlinking in the Agama accounts linking project). You can add your mapping in the same file or create a new Java class for this purpose. Then save your changes, re-package (zip) the project, re-deploy, and update (re-import) the configuration if necessary. Specifically, for Casa accounts linking, the mapping must include an attribute named ID . While ID is not part of the Jans database, here it is used to supply what could be understood as the identifier of the user at the external site. For instance, in a social site this may be the username or email. The example below shows how to set ID assuming the username was returned by the external site in an attribute named userId : profile -> { Map<String, Object> map = new HashMap<>(); map.put(\"ID\", profile.get(\"userId\")); ... return map; } In the above example, profile is a Map<String, Object> that holds the attribute-value pairs the third-party identity provider released for this user. For the interested, profile contents are dumped to the server logs (check jans-auth_script.log ) so it is easy to peak into the values. Check for a message in debug level starting with \"Profile data\". Both the ID of identity provider and the ID of the user will end up stored in an auxiliary database attribute. This helps to identify if the incoming user is already known (has been onboarded previously). When the attribute mapping is applied, the uid attribute is set as well. This is the username the incoming user will be assigned in the local Jans database. The uid is automatically generated based on ID unless the mapping already populates the uid directly. The return value of the mapping is a Map<String, Object> . This caters for cases where resulting attributes hold booleans, dates, numbers, strings, etc. When the attribute has to hold multiple values, you can use an array or a Java Collection object, like a List . User provisioning # After attribute mapping occurs, the local database is checked to determine if the incoming user is known (based on the ID in the mapping and the ID of the provider in question). If no match is found, the user is onboarded: a new entry is created in the database using the information found in the resulting mapping. Otherwise, the exact behavior varies depending on the provider configuration as follows: If skipProfileUpdate is set to false , the existing database entry is left untouched, otherwise: If cumulativeUpdate is set to false , the existing attributes in the entry which are part of the mapping are overwritten If cumulativeUpdate is set to true , the existing attribute values in the entry are preserved and new values are added if present in the mapping The updates just referenced apply to the matching entry based on mapping and provider ID, however, when emailLinkingSafe is set to true and the mapping comes with a mail value equal to an existing e-mail in the database, the update is carried over the e-mail matching entry.", "title": "Configuring Agama Project"}, {"location": "casa/plugins/accts-linking/accts-linking-agama/#accounts-linking-project-configuration", "text": "", "title": "Accounts linking project configuration"}, {"location": "casa/plugins/accts-linking/accts-linking-agama/#overview", "text": "The accounts linking Agama project must be configured in order to integrate third-party identity providers. The configuration of this project is supplied in a JSON file whose structure is like: { \"io.jans.casa.authn.acctlinking\": { \"providerID_1\": { ... }, \"providerID_2\": { ... }, ... } } Each property part of the JSON object io.jans.casa.auth.acctlinking holds the configuration of a different identity provider. Here's a how a typical configuration of a provider looks like: { \"displayName\": \"Goooogle\", \"flowQname\": \"io.jans.inbound.GenericProvider\", \"mappingClassField\": \"io.jans.casa.acctlinking.Mappings.GOOGLE\", \"oauthParams\": { \"authzEndpoint\": \"https://accounts.google.com/o/oauth2/v2/auth\", \"tokenEndpoint\": \"https://oauth2.googleapis.com/token\", \"userInfoEndpoint\": \"https://www.googleapis.com/oauth2/v3/userinfo\", \"clientId\": \"202403151302\", \"clientSecret\": \"m|a1l2d3i4t5a6S7h8a9k0i'r\u00bfa\", \"scopes\": [\"email\", \"profile\"] } } In this case, we are populating the configuration of an OAuth-based provider called \"Goooogle\". The tables shown in this page list all possible properties to configure a provider. Particularly, two properties deserve the most detail: flowQname . Agama projects are made up of flows - think of small \"web journeys\". This property must contain the name of an existing flow capable of interfacing with the identity provider of interest. Often, there is no need to write such \"interfacing\" flow. The below are ready-to-use and cover most of real-world cases, specifically OpenId/OAuth providers that support the authorization code grant (see section 1.3 of rfc6749 ): io.jans.inbound.GenericProvider . It implements the authorization code flow where the user's browser is taken to the external site. When authentication completes, a code is received at a designated redirect (callback) URL. With such code an access token is obtained as well as user's profile data. This flow supports dynamic client registration io.jans.inbound.Apple . It implements the authorization code flow with some nuances required in order to integrate \"Apple Sign In\" mappingClassField . This is key for performing the attribute mapping process and the user provisioning. The remainder of this document is dedicated to these two aspects Note Recall enabled is a handy property that can be used to temporarily \"deactive\" a given identity provider.", "title": "Overview"}, {"location": "casa/plugins/accts-linking/accts-linking-agama/#configuring-attribute-mappings", "text": "An introduction to attribute mapping can be found here . Unless an elaborated processing of attributes is required, a basic knowledge of Java language suffices to write a useful mapping. To write a mapping, you can use the samples provided as a guideline (see folder lib/io/jans/casa/acctlinking in the Agama accounts linking project). You can add your mapping in the same file or create a new Java class for this purpose. Then save your changes, re-package (zip) the project, re-deploy, and update (re-import) the configuration if necessary. Specifically, for Casa accounts linking, the mapping must include an attribute named ID . While ID is not part of the Jans database, here it is used to supply what could be understood as the identifier of the user at the external site. For instance, in a social site this may be the username or email. The example below shows how to set ID assuming the username was returned by the external site in an attribute named userId : profile -> { Map<String, Object> map = new HashMap<>(); map.put(\"ID\", profile.get(\"userId\")); ... return map; } In the above example, profile is a Map<String, Object> that holds the attribute-value pairs the third-party identity provider released for this user. For the interested, profile contents are dumped to the server logs (check jans-auth_script.log ) so it is easy to peak into the values. Check for a message in debug level starting with \"Profile data\". Both the ID of identity provider and the ID of the user will end up stored in an auxiliary database attribute. This helps to identify if the incoming user is already known (has been onboarded previously). When the attribute mapping is applied, the uid attribute is set as well. This is the username the incoming user will be assigned in the local Jans database. The uid is automatically generated based on ID unless the mapping already populates the uid directly. The return value of the mapping is a Map<String, Object> . This caters for cases where resulting attributes hold booleans, dates, numbers, strings, etc. When the attribute has to hold multiple values, you can use an array or a Java Collection object, like a List .", "title": "Configuring attribute mappings"}, {"location": "casa/plugins/accts-linking/accts-linking-agama/#user-provisioning", "text": "After attribute mapping occurs, the local database is checked to determine if the incoming user is known (based on the ID in the mapping and the ID of the provider in question). If no match is found, the user is onboarded: a new entry is created in the database using the information found in the resulting mapping. Otherwise, the exact behavior varies depending on the provider configuration as follows: If skipProfileUpdate is set to false , the existing database entry is left untouched, otherwise: If cumulativeUpdate is set to false , the existing attributes in the entry which are part of the mapping are overwritten If cumulativeUpdate is set to true , the existing attribute values in the entry are preserved and new values are added if present in the mapping The updates just referenced apply to the matching entry based on mapping and provider ID, however, when emailLinkingSafe is set to true and the mapping comes with a mail value equal to an existing e-mail in the database, the update is carried over the e-mail matching entry.", "title": "User provisioning"}, {"location": "cedarling/cedarling-authz/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling"], "text": "Authorization Using Cedarling # The Policy Store contains the Cedar Policies, Cedar Schema, and optionally, a list of the Trusted IDPs. The Cedarling loads its Policy Store during initialization as a static JSON file or fetched via HTTPS. In enterprise deployments, the Cedarling can retrieve its Policy Store from a Jans Lock Server OAuth protected endpoint. Developers need to define Cedar Schema that makes sense for their application. For example, a developer writing a customer support application might define an \"Issue\" Resource and Actions like \"Reply\" or \"Close\". Once the schema is defined, developers can author policies to model the fine grain access controls needed to implement the business rules of their application. The easiest way to define schema and policies is to use the AgamaLab Policy Designer. This is a free developer tool hosted by Gluu . The JWTs, Resource, Action, and Context are sent in the authz request. Cedar Pricipals entities are derived from JWT tokens. The OpenID Connect (\"OIDC\") JWTs are joined by the Cedarling to create User and Role entities; the OAuth access token is used to create a Workload entity, which is the software that is acting on behalf of the Person (or autonomously). The Cedarling validates that given its policies, Role, Person and Workload are authorized. If one of Role or Person and Workload is authorized then the request is allowed to proceed. The Cedarling maps \"Roles\" out-of-the-box. In Cedar, Roles are a special kind of Principal. Instead of saying \"User can perform action\", we can say \"Role can perform action\"--a convenient way to implement RBAC. Developers can specify which JWT claim is used to map Cedar Roles. For example, one domain may use the role user claim of the OpenID Userinfo token; another domain may use the memberOf claim in the OIDC id_token. Developers can also express a variety of policies beyond the limitations of RBAC by expressing ABAC conditions, or combining ABAC and RBAC conditions. For example, a policy like Admins can access a \"private\" Resource from the private network, during business hours. In this case \"Admins\" is the role, but the other conditions are ABAC. Policy evaluation is fast because Cedar uses the RBAC role to \"slice\" the data, minimizing the number of entries on which to evaluate the ABAC conditions. The OIDC id_token JWT represents a Person authentication event. The access token JWT represents a Workload authentication event. These tokens contain other interesting contextual data. The id_token tells you who authenticated, when they authenticated, how they authenticatated, and optionally other claims like the User's roles. An OAuth access token can tell you information about the Workload that obtained the JWT, its extent of access as defined by the OAuth Authorization Server ( i.e. the values of the scope claim), or other claims--domains frequently enhance the access token to contain business specific data needed for policy evaluation. The Cedarling authorizes a Person using a certain piece of software, which is called a \"Workload\". From a logical perspective, ( person_allowed AND workload_allowed ) must be True . The JWT's, Action, Resource and Context is sent by the application in the authorization request. For example, this is a sample request from a hypothetical application: const bootstrap_config = {...}; const cedarling = await init ( bootstrap_config ); let input = { \"tokens\" : { \"access_token\" : \"eyJhbGc....\" , \"id_token\" : \"eyJjbGc...\" , \"userinfo_token\" : \"eyJjbGc...\" , }, \"action\" : \"View\" , \"resource\" : { \"id\" : \"ticket-10101\" , \"type\" : \"Ticket\" , \"owner\" : \"bob@acme.com\" , \"org_id\" : \"Acme\" }, \"context\" : { \"ip_address\" : \"54.9.21.201\" , \"network_type\" : \"VPN\" , \"user_agent\" : \"Chrome 125.0.6422.77 (Official Build) (arm64)\" , \"time\" : \"1719266610.98636\" , } } decision_result = await cedarling ( input ) Automatically Adding Entity References to the Context # Cedarling simplifies context creation by automatically including certain entities. This means you don't need to manually pass their references when using them in your policies. The following entities are automatically added to the context, along with their naming conventions in lower_snake_case format: Workload Entity : workload User Entity : user Resource Entity : resource Access Token Entity : access_token ID Token Entity : id_token Userinfo Token Entity : userinfo_token Example Policy # Below is an example policy schema that illustrates how entities are used: type Context = { \"access_token\": Access_token, \"time\": Long, \"user\": User, \"workload\": Workload }; type Url = { \"host\": String, \"path\": String, \"protocol\": String }; entity Access_token = { \"exp\": Long, \"iss\": TrustedIssuer }; entity Issue = { \"country\": String, \"org_id\": String }; entity Role; entity TrustedIssuer = { \"issuer_entity_id\": Url }; entity User in [Role] = { \"country\": String, \"email\": String, \"sub\": String, \"username\": String }; entity Workload = { \"client_id\": String, \"iss\": TrustedIssuer, \"name\": String, \"org_id\": String }; action \"Update\" appliesTo { principal: [Role, Workload, User], resource: [Issue], context: { \"access_token\": Access_token, \"time\": Long, \"user\": User, \"workload\": Workload } }; action \"View\" appliesTo { principal: [Role, Workload, User], resource: [Issue], context: Context }; With this schema, you only need to provide the fields that are not automatically included. For instance, to define the time in the context: let context = { \"time\" : 1719266610.98636 , }", "title": "Authz"}, {"location": "cedarling/cedarling-authz/#authorization-using-cedarling", "text": "The Policy Store contains the Cedar Policies, Cedar Schema, and optionally, a list of the Trusted IDPs. The Cedarling loads its Policy Store during initialization as a static JSON file or fetched via HTTPS. In enterprise deployments, the Cedarling can retrieve its Policy Store from a Jans Lock Server OAuth protected endpoint. Developers need to define Cedar Schema that makes sense for their application. For example, a developer writing a customer support application might define an \"Issue\" Resource and Actions like \"Reply\" or \"Close\". Once the schema is defined, developers can author policies to model the fine grain access controls needed to implement the business rules of their application. The easiest way to define schema and policies is to use the AgamaLab Policy Designer. This is a free developer tool hosted by Gluu . The JWTs, Resource, Action, and Context are sent in the authz request. Cedar Pricipals entities are derived from JWT tokens. The OpenID Connect (\"OIDC\") JWTs are joined by the Cedarling to create User and Role entities; the OAuth access token is used to create a Workload entity, which is the software that is acting on behalf of the Person (or autonomously). The Cedarling validates that given its policies, Role, Person and Workload are authorized. If one of Role or Person and Workload is authorized then the request is allowed to proceed. The Cedarling maps \"Roles\" out-of-the-box. In Cedar, Roles are a special kind of Principal. Instead of saying \"User can perform action\", we can say \"Role can perform action\"--a convenient way to implement RBAC. Developers can specify which JWT claim is used to map Cedar Roles. For example, one domain may use the role user claim of the OpenID Userinfo token; another domain may use the memberOf claim in the OIDC id_token. Developers can also express a variety of policies beyond the limitations of RBAC by expressing ABAC conditions, or combining ABAC and RBAC conditions. For example, a policy like Admins can access a \"private\" Resource from the private network, during business hours. In this case \"Admins\" is the role, but the other conditions are ABAC. Policy evaluation is fast because Cedar uses the RBAC role to \"slice\" the data, minimizing the number of entries on which to evaluate the ABAC conditions. The OIDC id_token JWT represents a Person authentication event. The access token JWT represents a Workload authentication event. These tokens contain other interesting contextual data. The id_token tells you who authenticated, when they authenticated, how they authenticatated, and optionally other claims like the User's roles. An OAuth access token can tell you information about the Workload that obtained the JWT, its extent of access as defined by the OAuth Authorization Server ( i.e. the values of the scope claim), or other claims--domains frequently enhance the access token to contain business specific data needed for policy evaluation. The Cedarling authorizes a Person using a certain piece of software, which is called a \"Workload\". From a logical perspective, ( person_allowed AND workload_allowed ) must be True . The JWT's, Action, Resource and Context is sent by the application in the authorization request. For example, this is a sample request from a hypothetical application: const bootstrap_config = {...}; const cedarling = await init ( bootstrap_config ); let input = { \"tokens\" : { \"access_token\" : \"eyJhbGc....\" , \"id_token\" : \"eyJjbGc...\" , \"userinfo_token\" : \"eyJjbGc...\" , }, \"action\" : \"View\" , \"resource\" : { \"id\" : \"ticket-10101\" , \"type\" : \"Ticket\" , \"owner\" : \"bob@acme.com\" , \"org_id\" : \"Acme\" }, \"context\" : { \"ip_address\" : \"54.9.21.201\" , \"network_type\" : \"VPN\" , \"user_agent\" : \"Chrome 125.0.6422.77 (Official Build) (arm64)\" , \"time\" : \"1719266610.98636\" , } } decision_result = await cedarling ( input )", "title": "Authorization Using Cedarling"}, {"location": "cedarling/cedarling-authz/#automatically-adding-entity-references-to-the-context", "text": "Cedarling simplifies context creation by automatically including certain entities. This means you don't need to manually pass their references when using them in your policies. The following entities are automatically added to the context, along with their naming conventions in lower_snake_case format: Workload Entity : workload User Entity : user Resource Entity : resource Access Token Entity : access_token ID Token Entity : id_token Userinfo Token Entity : userinfo_token", "title": "Automatically Adding Entity References to the Context"}, {"location": "cedarling/cedarling-authz/#example-policy", "text": "Below is an example policy schema that illustrates how entities are used: type Context = { \"access_token\": Access_token, \"time\": Long, \"user\": User, \"workload\": Workload }; type Url = { \"host\": String, \"path\": String, \"protocol\": String }; entity Access_token = { \"exp\": Long, \"iss\": TrustedIssuer }; entity Issue = { \"country\": String, \"org_id\": String }; entity Role; entity TrustedIssuer = { \"issuer_entity_id\": Url }; entity User in [Role] = { \"country\": String, \"email\": String, \"sub\": String, \"username\": String }; entity Workload = { \"client_id\": String, \"iss\": TrustedIssuer, \"name\": String, \"org_id\": String }; action \"Update\" appliesTo { principal: [Role, Workload, User], resource: [Issue], context: { \"access_token\": Access_token, \"time\": Long, \"user\": User, \"workload\": Workload } }; action \"View\" appliesTo { principal: [Role, Workload, User], resource: [Issue], context: Context }; With this schema, you only need to provide the fields that are not automatically included. For instance, to define the time in the context: let context = { \"time\" : 1719266610.98636 , }", "title": "Example Policy"}, {"location": "cedarling/cedarling-jwt/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling", "JWT"], "text": "Cedarling JWT Flow # Json Web Token Validation # Note: To enable Json Web Token (JWT) Validation in Cedarling, it is required to populate the trusted_issuers field in the Policy Store . Enabling JWT Signature Validation # Cedarling can validate JWT signatures for enhanced security. To enable this feature, set the CEDARLING_JWT_VALIDATION bootstrap property to True . For development and testing purposes, you can set this property to False and submit an unsigned JWT, such as one generated from JWT.io . Public Key Management # When token validation is enabled, Cedarling downloads the public keys of the Trusted IDPs specified in the policy store during initialization. Cedarling uses the JWT iss claim to select the appropriate keys for validation. JWT Revocation # In enterprise deployments, Cedarling can also check for JWT revocation. This is achieved by following the mechanism described in the OAuth Status Lists draft. Token status enforcement helps mitigate risks associated with account takeover by enabling immediate revocation of all tokens issued to an attacker. Additionally, domains may choose to use Token Status to implement single-use transaction tokens. Summary of JWT Validation Mechanisms # Depending on your bootstrap properties, Cedarling may validate JWTs through the following methods: Validate signatures from Trusted Issuers Check JWT status for revocation Discard id_token if the aud claim does not match the client_id of the access token Discard Userinfo tokens that are not associated with a sub claim from the id_token Verify exp (expiration) and nbf (not before) claims of access tokens and id_tokens, if timestamps are provided in the context", "title": "JWT"}, {"location": "cedarling/cedarling-jwt/#cedarling-jwt-flow", "text": "", "title": "Cedarling JWT Flow"}, {"location": "cedarling/cedarling-jwt/#json-web-token-validation", "text": "Note: To enable Json Web Token (JWT) Validation in Cedarling, it is required to populate the trusted_issuers field in the Policy Store .", "title": "Json Web Token Validation"}, {"location": "cedarling/cedarling-jwt/#enabling-jwt-signature-validation", "text": "Cedarling can validate JWT signatures for enhanced security. To enable this feature, set the CEDARLING_JWT_VALIDATION bootstrap property to True . For development and testing purposes, you can set this property to False and submit an unsigned JWT, such as one generated from JWT.io .", "title": "Enabling JWT Signature Validation"}, {"location": "cedarling/cedarling-jwt/#public-key-management", "text": "When token validation is enabled, Cedarling downloads the public keys of the Trusted IDPs specified in the policy store during initialization. Cedarling uses the JWT iss claim to select the appropriate keys for validation.", "title": "Public Key Management"}, {"location": "cedarling/cedarling-jwt/#jwt-revocation", "text": "In enterprise deployments, Cedarling can also check for JWT revocation. This is achieved by following the mechanism described in the OAuth Status Lists draft. Token status enforcement helps mitigate risks associated with account takeover by enabling immediate revocation of all tokens issued to an attacker. Additionally, domains may choose to use Token Status to implement single-use transaction tokens.", "title": "JWT Revocation"}, {"location": "cedarling/cedarling-jwt/#summary-of-jwt-validation-mechanisms", "text": "Depending on your bootstrap properties, Cedarling may validate JWTs through the following methods: Validate signatures from Trusted Issuers Check JWT status for revocation Discard id_token if the aud claim does not match the client_id of the access token Discard Userinfo tokens that are not associated with a sub claim from the id_token Verify exp (expiration) and nbf (not before) claims of access tokens and id_tokens, if timestamps are provided in the context", "title": "Summary of JWT Validation Mechanisms"}, {"location": "cedarling/cedarling-logs/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling", "logging", "audit"], "text": "Cedarling Logs # Cedarling Audit Logs # The Cedarling logs contains a record of all a Cedarling's decisions and token validations. Cedarling has four logging options, which are configurable via the CEDARLING_LOG_TYPE bootstrap property: off - no logging memory - logs stored in Cedarling in-memory KV store, fetched by client via logging interface. This is ideal for batching logs without impeding authz performance std_out - write logs synchronously to std_out lock - periodically POST logs to Jans Lock Server /audit endpoint for central archiving. There are three different log records produced by the Cedarling: Decision - The result and diagnostics of an authz decision System - Startup, debug and other Cedarling messages not related to authz Metric - Performance and usage data System Log Levels # This is set by CEDARLING_LOG_LEVEL FATAL : Indicates very severe error events that will likely lead the application to abort. These are the most critical issues. ERROR : Designates error events that might still allow the application to continue running but indicate a significant problem. WARN : Designates potentially harmful situations that should be addressed to prevent future issues. INFO : Provides informational messages that highlight the progress of the application at a coarse-grained level. DEBUG : Designates fine-grained informational events useful for debugging the application. TRACE : Provides finer-grained informational events than DEBUG. It is often used for detailed tracing of program execution. Jans Lock Server # In enterprise deployments, Janssen Lock Server collects Cedarling logs and can stream to a database or S3 bucket. The Cedarling decision logs provide compliance evidence of usage of the domain's externalized policies. The logs are also useful for forensic analysis to show everything the attacker attempted, both allowed and denied. Sample logs # The JSON in this document is formatted for readability but is not prettified in the actual implementation. Startup Message # { \"request_id\" : \"0193b8a8-efc0-77ce-bd90-4a62a2998462\" , \"timestamp\" : \"2024-12-12T04:18:19.456Z\" , \"log_kind\" : \"System\" , \"pdp_id\" : \"d47e245e-beaa-4ea4-b899-b8184cd3eb7e\" , \"level\" : \"DEBUG\" , \"msg\" : \"configuration parsed successfully\" } { \"request_id\" : \"0193b8a8-efc1-7e42-9678-b2480268b91f\" , \"timestamp\" : \"2024-12-12T04:18:19.457Z\" , \"log_kind\" : \"System\" , \"pdp_id\" : \"d47e245e-beaa-4ea4-b899-b8184cd3eb7e\" , \"level\" : \"INFO\" , \"msg\" : \"Cedarling Authz initialized successfully\" , \"application_id\" : \"My App\" , \"cedar_lang_version\" : \"4.1.0\" , \"cedar_sdk_version\" : \"4.2.2\" } Decision Log # Example of decision log. { \"request_id\" : \"019394db-f52b-7b06-88b8-a288670a32c2\" , \"timestamp\" : \"2024-12-05T05:27:43.403Z\" , \"log_type\" : \"Decision\" , \"pdp_id\" : \"9e189c4b-96ae-4818-8e7f-75a42186af15\" , \"policystore_id\" : \"a1bf93115de86de760ee0bea1d529b521489e5a11747\" , \"policystore_version\" : \"undefined\" , \"principal\" : \"User & Workload\" , \"User\" : { \"username\" : \"admin@gluu.org\" }, \"Workload\" : { \"org_id\" : \"some_long_id\" }, \"diagnostics\" : { \"reason\" : [ { \"id\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"policy for user\" } ], \"errors\" : [] }, \"lock_client_id\" : null , \"action\" : \"Jans::Action::\\\"Update\\\"\" , \"resource\" : \"Jans::Issue::\\\"random_id\\\"\" , \"decision\" : \"ALLOW\" , \"tokens\" : { \"id_token\" : { \"jti\" : \"id_tkn_jti\" }, \"Userinfo\" : { \"jti\" : \"usrinfo_tkn_jti\" }, \"access\" : { \"jti\" : \"access_tkn_jti\" } }, \"decision_time_ms\" : 3 } Field Definitions # request_id : unique identifier for the decision request timestamp : Derived if possible from the system or context--may be empty in cases where WASM can't access the system clock, and the time wasn't sent in the context. pdp_id : unique identifier for the Cedarling policystore_id : What policystore this Cedarling instance is using policystore_version : What version of the policystore the Cedarling is using principal : User | Workload User : A list of claims, specified by the CEDARLING_DECISION_LOG_USER_CLAIMS property, that must be present in the Cedar User entity Workload : A list of claims, specified by the CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS property, that must be present in the Cedar Workload entity lock_client_id : If this Cedarling has registered with a Lock Server, what is the client_id it received action : From the request resource : From the Request decision : ALLOW or DENY tokens : Dictionary with the token type and claims which should be included in the log decision_time_ms : how long the decision took Debug Log Sample # The result of the authorization is quite extensive because we log all cedar-policy entity information for forensic analysis. We cannot truncate the data, as it may contain critical information. { \"id\" : \"01937015-4649-7aad-8df8-4976e4bd8565\" , \"time\" : 1732752262 , \"log_type\" : \"Decision\" , \"level\" : \"DEBUG\" , \"pdp_id\" : \"75f0dc93-0a90-4076-95fa-dc16d3f00375\" , \"msg\" : \"Result of authorize.\" , \"application_id\" : \"TestApp\" , \"action\" : \"Jans::Action::\\\"Read\\\"\" , \"resource\" : \"Jans::Application::\\\"some_id\\\"\" , \"context\" : { \"user_agent\" : \"Linux\" , \"operating_system\" : \"Linux\" , \"network_type\" : \"Local\" , \"network\" : \"127.0.0.1\" , \"geolocation\" : [ \"America\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"device_health\" : [ \"Healthy\" ], \"current_time\" : 1732752262 }, \"entities\" : [ { \"uid\" : { \"type\" : \"Jans::User\" , \"id\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" }, \"attrs\" : { \"sub\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" , \"role\" : [ \"CasaAdmin\" ], \"email\" : { \"domain\" : \"jans.test\" , \"uid\" : \"admin\" } }, \"parents\" : [ { \"type\" : \"Jans::Role\" , \"id\" : \"CasaAdmin\" } ] }, { \"uid\" : { \"type\" : \"Jans::id_token\" , \"id\" : \"ijLZO1ooRyWrgIn7cIdNyA\" }, \"attrs\" : { \"sub\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" , \"acr\" : \"simple_password_auth\" , \"exp\" : 1731956630 , \"jti\" : \"ijLZO1ooRyWrgIn7cIdNyA\" , \"amr\" : [], \"aud\" : \"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\" , \"iss\" : { \"__entity\" : { \"type\" : \"Jans::TrustedIssuer\" , \"id\" : \"https://account.gluu.org\" } }, \"iat\" : 1731953030 }, \"parents\" : [] }, ... { \"uid\" : { \"type\" : \"Jans::Action\" , \"id\" : \"Tag\" }, \"attrs\" : {}, \"parents\" : [] } ], \"person_principal\" : \"Jans::User::\\\"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\\\"\" , \"person_diagnostics\" : { \"reason\" : [ { \"id\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"simple policy example for principal user\" } ], \"errors\" : [] }, \"person_decision\" : \"ALLOW\" , \"workload_principal\" : \"Jans::Workload::\\\"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\\\"\" , \"workload_diagnostics\" : { \"reason\" : [ { \"id\" : \"444da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"simple policy example for principal workload\" } ], \"errors\" : [] }, \"workload_decision\" : \"ALLOW\" , \"authorized\" : true }", "title": "Logs"}, {"location": "cedarling/cedarling-logs/#cedarling-logs", "text": "", "title": "Cedarling Logs"}, {"location": "cedarling/cedarling-logs/#cedarling-audit-logs", "text": "The Cedarling logs contains a record of all a Cedarling's decisions and token validations. Cedarling has four logging options, which are configurable via the CEDARLING_LOG_TYPE bootstrap property: off - no logging memory - logs stored in Cedarling in-memory KV store, fetched by client via logging interface. This is ideal for batching logs without impeding authz performance std_out - write logs synchronously to std_out lock - periodically POST logs to Jans Lock Server /audit endpoint for central archiving. There are three different log records produced by the Cedarling: Decision - The result and diagnostics of an authz decision System - Startup, debug and other Cedarling messages not related to authz Metric - Performance and usage data", "title": "Cedarling Audit Logs"}, {"location": "cedarling/cedarling-logs/#system-log-levels", "text": "This is set by CEDARLING_LOG_LEVEL FATAL : Indicates very severe error events that will likely lead the application to abort. These are the most critical issues. ERROR : Designates error events that might still allow the application to continue running but indicate a significant problem. WARN : Designates potentially harmful situations that should be addressed to prevent future issues. INFO : Provides informational messages that highlight the progress of the application at a coarse-grained level. DEBUG : Designates fine-grained informational events useful for debugging the application. TRACE : Provides finer-grained informational events than DEBUG. It is often used for detailed tracing of program execution.", "title": "System Log Levels"}, {"location": "cedarling/cedarling-logs/#jans-lock-server", "text": "In enterprise deployments, Janssen Lock Server collects Cedarling logs and can stream to a database or S3 bucket. The Cedarling decision logs provide compliance evidence of usage of the domain's externalized policies. The logs are also useful for forensic analysis to show everything the attacker attempted, both allowed and denied.", "title": "Jans Lock Server"}, {"location": "cedarling/cedarling-logs/#sample-logs", "text": "The JSON in this document is formatted for readability but is not prettified in the actual implementation.", "title": "Sample logs"}, {"location": "cedarling/cedarling-logs/#startup-message", "text": "{ \"request_id\" : \"0193b8a8-efc0-77ce-bd90-4a62a2998462\" , \"timestamp\" : \"2024-12-12T04:18:19.456Z\" , \"log_kind\" : \"System\" , \"pdp_id\" : \"d47e245e-beaa-4ea4-b899-b8184cd3eb7e\" , \"level\" : \"DEBUG\" , \"msg\" : \"configuration parsed successfully\" } { \"request_id\" : \"0193b8a8-efc1-7e42-9678-b2480268b91f\" , \"timestamp\" : \"2024-12-12T04:18:19.457Z\" , \"log_kind\" : \"System\" , \"pdp_id\" : \"d47e245e-beaa-4ea4-b899-b8184cd3eb7e\" , \"level\" : \"INFO\" , \"msg\" : \"Cedarling Authz initialized successfully\" , \"application_id\" : \"My App\" , \"cedar_lang_version\" : \"4.1.0\" , \"cedar_sdk_version\" : \"4.2.2\" }", "title": "Startup Message"}, {"location": "cedarling/cedarling-logs/#decision-log", "text": "Example of decision log. { \"request_id\" : \"019394db-f52b-7b06-88b8-a288670a32c2\" , \"timestamp\" : \"2024-12-05T05:27:43.403Z\" , \"log_type\" : \"Decision\" , \"pdp_id\" : \"9e189c4b-96ae-4818-8e7f-75a42186af15\" , \"policystore_id\" : \"a1bf93115de86de760ee0bea1d529b521489e5a11747\" , \"policystore_version\" : \"undefined\" , \"principal\" : \"User & Workload\" , \"User\" : { \"username\" : \"admin@gluu.org\" }, \"Workload\" : { \"org_id\" : \"some_long_id\" }, \"diagnostics\" : { \"reason\" : [ { \"id\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"policy for user\" } ], \"errors\" : [] }, \"lock_client_id\" : null , \"action\" : \"Jans::Action::\\\"Update\\\"\" , \"resource\" : \"Jans::Issue::\\\"random_id\\\"\" , \"decision\" : \"ALLOW\" , \"tokens\" : { \"id_token\" : { \"jti\" : \"id_tkn_jti\" }, \"Userinfo\" : { \"jti\" : \"usrinfo_tkn_jti\" }, \"access\" : { \"jti\" : \"access_tkn_jti\" } }, \"decision_time_ms\" : 3 }", "title": "Decision Log"}, {"location": "cedarling/cedarling-logs/#field-definitions", "text": "request_id : unique identifier for the decision request timestamp : Derived if possible from the system or context--may be empty in cases where WASM can't access the system clock, and the time wasn't sent in the context. pdp_id : unique identifier for the Cedarling policystore_id : What policystore this Cedarling instance is using policystore_version : What version of the policystore the Cedarling is using principal : User | Workload User : A list of claims, specified by the CEDARLING_DECISION_LOG_USER_CLAIMS property, that must be present in the Cedar User entity Workload : A list of claims, specified by the CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS property, that must be present in the Cedar Workload entity lock_client_id : If this Cedarling has registered with a Lock Server, what is the client_id it received action : From the request resource : From the Request decision : ALLOW or DENY tokens : Dictionary with the token type and claims which should be included in the log decision_time_ms : how long the decision took", "title": "Field Definitions"}, {"location": "cedarling/cedarling-logs/#debug-log-sample", "text": "The result of the authorization is quite extensive because we log all cedar-policy entity information for forensic analysis. We cannot truncate the data, as it may contain critical information. { \"id\" : \"01937015-4649-7aad-8df8-4976e4bd8565\" , \"time\" : 1732752262 , \"log_type\" : \"Decision\" , \"level\" : \"DEBUG\" , \"pdp_id\" : \"75f0dc93-0a90-4076-95fa-dc16d3f00375\" , \"msg\" : \"Result of authorize.\" , \"application_id\" : \"TestApp\" , \"action\" : \"Jans::Action::\\\"Read\\\"\" , \"resource\" : \"Jans::Application::\\\"some_id\\\"\" , \"context\" : { \"user_agent\" : \"Linux\" , \"operating_system\" : \"Linux\" , \"network_type\" : \"Local\" , \"network\" : \"127.0.0.1\" , \"geolocation\" : [ \"America\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"device_health\" : [ \"Healthy\" ], \"current_time\" : 1732752262 }, \"entities\" : [ { \"uid\" : { \"type\" : \"Jans::User\" , \"id\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" }, \"attrs\" : { \"sub\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" , \"role\" : [ \"CasaAdmin\" ], \"email\" : { \"domain\" : \"jans.test\" , \"uid\" : \"admin\" } }, \"parents\" : [ { \"type\" : \"Jans::Role\" , \"id\" : \"CasaAdmin\" } ] }, { \"uid\" : { \"type\" : \"Jans::id_token\" , \"id\" : \"ijLZO1ooRyWrgIn7cIdNyA\" }, \"attrs\" : { \"sub\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" , \"acr\" : \"simple_password_auth\" , \"exp\" : 1731956630 , \"jti\" : \"ijLZO1ooRyWrgIn7cIdNyA\" , \"amr\" : [], \"aud\" : \"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\" , \"iss\" : { \"__entity\" : { \"type\" : \"Jans::TrustedIssuer\" , \"id\" : \"https://account.gluu.org\" } }, \"iat\" : 1731953030 }, \"parents\" : [] }, ... { \"uid\" : { \"type\" : \"Jans::Action\" , \"id\" : \"Tag\" }, \"attrs\" : {}, \"parents\" : [] } ], \"person_principal\" : \"Jans::User::\\\"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\\\"\" , \"person_diagnostics\" : { \"reason\" : [ { \"id\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"simple policy example for principal user\" } ], \"errors\" : [] }, \"person_decision\" : \"ALLOW\" , \"workload_principal\" : \"Jans::Workload::\\\"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\\\"\" , \"workload_diagnostics\" : { \"reason\" : [ { \"id\" : \"444da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"simple policy example for principal workload\" } ], \"errors\" : [] }, \"workload_decision\" : \"ALLOW\" , \"authorized\" : true }", "title": "Debug Log Sample"}, {"location": "cedarling/cedarling-overview/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling"], "text": "Cedarling Overview # What is Cedar # Cedar is a policy syntax invented by Amazon and used by their Verified Permission service. Cedar policies enable developers to implement fine-grain access control and externalize policies. To learn more about why the design of Cedar is intuitive , fast and safe , read this article or watch this video Cedar uses the PARC syntax: P rincipal A ction R esource C ontext For example, you may have a policy that says Admins can write to the /config folder. The Admin role is the Principal, write is the Action, and the /config folder is the Resource. The Context is used to specify information about the enivironment, like the time of day or network address. Fine grain access control makes sense in both the frontend and backend. In the frontend, mastery of authz can help developers build better UX. For example, why display form fields a user is not authorized to see? In the backend, fine grain policies are necessary for a zero trust architecture. What is the Cedarling # Architecturally, the Cedarling is an embeddable stateful Policy Decision Point, or \"PDP\". It is stateful because it implements an in-memory cache which makes it possible to batch logs and implement other performance optimizations. The Cedarling is written in Rust with bindings to WASM, iOS, Android, and Python--this makes it possible for web, mobile, and cloud developers to incorporate the Cedarling into their applications. The Cedarling is used for both frontend and backend security. Because the frontend is more constrained with regard to memory and compute, this requirement was critical to the design. For example, in the backend, a PDP could run in a Linux container. But in the frontend, the Cedarling must run in a browser, using the browser WASM engine. How does the Cedarling get the data to calculate a decision? The Principal data is contained in the JWTs--a person, a workload, or both. The Action, Resource and Context are sent by the application as arguments in the authz request. The Cedarling is fast because it has all the data it needs to make a local decision. No cloud round-trips are needed to return an authz decision--a cloud roundtrip may kill the performance of a frontend application. The Cedarling can execute many requests in less then 1ms--this is critical for UX fine grain authorization. Below is a conceptual diagram showing how you can archiect the Cedarling for frontend and backend security. The Cedarling is used to determine if the Mobile Application should be allowed to register. For example, perhaps the IDP wants to execute a policy that restricts registration to mobile applications that present a Google Integrity API attestation to indicate the checksum of the binary has not changed, and that the phone is not rooted. The Cedarling is used to authenticate the person using the mobile application, i.e. the \"User\". For example, perhaps the IDP wants to execute a policy that says that 2FA is required from a non trusted network. The Cedarling is used to determine which scopes to add to the OAuth access token. For example, perhaps if the mobile application presents a software statement assertion JWT (i.e. and \"SSA\") issued by the IDP, the application may request the financial scope. Once JWT tokens are issued by the IDP, the frontend can use these tokens to evaluate local policies. For example, perhaps the mobile application only allows access to certain features if the Userinfo JWT contains a role claim for a \"Manager\". The mobile application may send an OAuth access token to call an API. This API Gateway may route this request to a backend service, but only after evaluating certain security policies. For example, perhaps the Action POST is only allowed on a Resource (e.g. \"URI\") when the access token JWT contains a certain scope. Finally, the Backend API can use the Cedarling to perform its own fine grain authorization. For example, perhaps the Backend only allows transaction greater than $10,000 if the access token contains scope value high-net-worth . This is just a hypothetical example, but hopefully you can see how the Cedarling is used to achieve multilayer security. Each Cedarling has it's own specific policy store. The API Gateway Cedarling instance does not need to know the policies or schema for the mobile application. By layering security, you can implement a zero trust architecture. Cedarling Interfaces # The developer using the Cedarling to build an application uses three easy interfaces: (\" init \"), authorization (\" authz \") and logging (\" log \"). Developers call the init interface on startup of their application, causing the Cedarling to read its bootstrap properties and load its policy store . If configured, the Cedarling will also retrieve the most recent IDP public keys and request JWT status updates. The authz interface provides the main functionality of the Cedarling: to authorize a PARC request from the application by mapping the data sent in the request, and evaluating it with the embedded Rust Cedar Engine . The authz interface answers the question: \"Is this action, on this resource, given this context, allowed with these JWTs?\". The Cedarling returns the decion-- allow or deny . If denied, the Cedarling returns \"diagnostics\"--additional context if the decision is denied. During authz , the Cedarling can perform two more important jobs: (1) validate JWT tokens; (2) log the resulting decision. The log interface enables developers to retrieve decision and system logs from the Cedarling's in-memory cache. See the Cedarling log documentation for more information. Cedarling Components # As a developer, you don't really need to understand how the Cedarling is constructed. But this section is meant to give you an idea to help you get a better understand of what it's actually doing. The following diagram is a very high level picture: Cedar Engine is the latest code released from the open source Rust Cedar project. Thanks Amazon for supporting this fabulous technology! SparKV is an in-memory key-value store that support automatic expiration of data. For example, we don't want to store logs for more then a few minutes. The Cedarling is a stateful PDP, but of course it doesn't write anything to disk. The state is stored entirely in Memory, and SparKV provides an easy way to do this. Init, Authz, and Log Engines perform actions similar to those described in the interfaces above. JWT Engine is used to validate JWT signatures and to check the status of a JWT token. Lock Engine is used for enterprise deployments, where the Cedarling is one of many instances, and it needs to pick up its Policy Store from a trusted source and send to store its logs centrally, for example in a SIEM. So you can see that the Cedar Engine is central to the functionality of the Cedarling. However, the other helper engines make it easier for developer to use Cedar for application security when they are using JWT tokens as the source of Person and Workload identity.", "title": "Overview"}, {"location": "cedarling/cedarling-overview/#cedarling-overview", "text": "", "title": "Cedarling Overview"}, {"location": "cedarling/cedarling-overview/#what-is-cedar", "text": "Cedar is a policy syntax invented by Amazon and used by their Verified Permission service. Cedar policies enable developers to implement fine-grain access control and externalize policies. To learn more about why the design of Cedar is intuitive , fast and safe , read this article or watch this video Cedar uses the PARC syntax: P rincipal A ction R esource C ontext For example, you may have a policy that says Admins can write to the /config folder. The Admin role is the Principal, write is the Action, and the /config folder is the Resource. The Context is used to specify information about the enivironment, like the time of day or network address. Fine grain access control makes sense in both the frontend and backend. In the frontend, mastery of authz can help developers build better UX. For example, why display form fields a user is not authorized to see? In the backend, fine grain policies are necessary for a zero trust architecture.", "title": "What is Cedar"}, {"location": "cedarling/cedarling-overview/#what-is-the-cedarling", "text": "Architecturally, the Cedarling is an embeddable stateful Policy Decision Point, or \"PDP\". It is stateful because it implements an in-memory cache which makes it possible to batch logs and implement other performance optimizations. The Cedarling is written in Rust with bindings to WASM, iOS, Android, and Python--this makes it possible for web, mobile, and cloud developers to incorporate the Cedarling into their applications. The Cedarling is used for both frontend and backend security. Because the frontend is more constrained with regard to memory and compute, this requirement was critical to the design. For example, in the backend, a PDP could run in a Linux container. But in the frontend, the Cedarling must run in a browser, using the browser WASM engine. How does the Cedarling get the data to calculate a decision? The Principal data is contained in the JWTs--a person, a workload, or both. The Action, Resource and Context are sent by the application as arguments in the authz request. The Cedarling is fast because it has all the data it needs to make a local decision. No cloud round-trips are needed to return an authz decision--a cloud roundtrip may kill the performance of a frontend application. The Cedarling can execute many requests in less then 1ms--this is critical for UX fine grain authorization. Below is a conceptual diagram showing how you can archiect the Cedarling for frontend and backend security. The Cedarling is used to determine if the Mobile Application should be allowed to register. For example, perhaps the IDP wants to execute a policy that restricts registration to mobile applications that present a Google Integrity API attestation to indicate the checksum of the binary has not changed, and that the phone is not rooted. The Cedarling is used to authenticate the person using the mobile application, i.e. the \"User\". For example, perhaps the IDP wants to execute a policy that says that 2FA is required from a non trusted network. The Cedarling is used to determine which scopes to add to the OAuth access token. For example, perhaps if the mobile application presents a software statement assertion JWT (i.e. and \"SSA\") issued by the IDP, the application may request the financial scope. Once JWT tokens are issued by the IDP, the frontend can use these tokens to evaluate local policies. For example, perhaps the mobile application only allows access to certain features if the Userinfo JWT contains a role claim for a \"Manager\". The mobile application may send an OAuth access token to call an API. This API Gateway may route this request to a backend service, but only after evaluating certain security policies. For example, perhaps the Action POST is only allowed on a Resource (e.g. \"URI\") when the access token JWT contains a certain scope. Finally, the Backend API can use the Cedarling to perform its own fine grain authorization. For example, perhaps the Backend only allows transaction greater than $10,000 if the access token contains scope value high-net-worth . This is just a hypothetical example, but hopefully you can see how the Cedarling is used to achieve multilayer security. Each Cedarling has it's own specific policy store. The API Gateway Cedarling instance does not need to know the policies or schema for the mobile application. By layering security, you can implement a zero trust architecture.", "title": "What is the Cedarling"}, {"location": "cedarling/cedarling-overview/#cedarling-interfaces", "text": "The developer using the Cedarling to build an application uses three easy interfaces: (\" init \"), authorization (\" authz \") and logging (\" log \"). Developers call the init interface on startup of their application, causing the Cedarling to read its bootstrap properties and load its policy store . If configured, the Cedarling will also retrieve the most recent IDP public keys and request JWT status updates. The authz interface provides the main functionality of the Cedarling: to authorize a PARC request from the application by mapping the data sent in the request, and evaluating it with the embedded Rust Cedar Engine . The authz interface answers the question: \"Is this action, on this resource, given this context, allowed with these JWTs?\". The Cedarling returns the decion-- allow or deny . If denied, the Cedarling returns \"diagnostics\"--additional context if the decision is denied. During authz , the Cedarling can perform two more important jobs: (1) validate JWT tokens; (2) log the resulting decision. The log interface enables developers to retrieve decision and system logs from the Cedarling's in-memory cache. See the Cedarling log documentation for more information.", "title": "Cedarling Interfaces"}, {"location": "cedarling/cedarling-overview/#cedarling-components", "text": "As a developer, you don't really need to understand how the Cedarling is constructed. But this section is meant to give you an idea to help you get a better understand of what it's actually doing. The following diagram is a very high level picture: Cedar Engine is the latest code released from the open source Rust Cedar project. Thanks Amazon for supporting this fabulous technology! SparKV is an in-memory key-value store that support automatic expiration of data. For example, we don't want to store logs for more then a few minutes. The Cedarling is a stateful PDP, but of course it doesn't write anything to disk. The state is stored entirely in Memory, and SparKV provides an easy way to do this. Init, Authz, and Log Engines perform actions similar to those described in the interfaces above. JWT Engine is used to validate JWT signatures and to check the status of a JWT token. Lock Engine is used for enterprise deployments, where the Cedarling is one of many instances, and it needs to pick up its Policy Store from a trusted source and send to store its logs centrally, for example in a SIEM. So you can see that the Cedar Engine is central to the functionality of the Cedarling. However, the other helper engines make it easier for developer to use Cedar for application security when they are using JWT tokens as the source of Person and Workload identity.", "title": "Cedarling Components"}, {"location": "cedarling/cedarling-policy-store/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling", "policy store"], "text": "Cedarling Policy Store # The Cedarling Policy Store uses a JSON file named cedarling_store.json to store all necessary data for evaluating policies and verifying JWT tokens. The structure includes the following key components: Cedar Schema : The Cedar schema encoded in Base64. Cedar Policies : The Cedar policies encoded in Base64. Trusted Issuers : Details about the trusted issuers (see below for syntax). Note: The cedarling_store.json file is only needed if the bootstrap properties: CEDARLING_LOCK ; CEDARLING_POLICY_STORE_URI ; and CEDARLING_POLICY_STORE_ID are not set to a local location. If you're fetching the policies remotely, you don't need a cedarling_store.json file. JSON Schema # The JSON Schema accepted by cedarling is defined as follows: { \"cedar_version\" : \"v4.0.0\" , \"policy_stores\" : { \"some_unique_string_id\" : { \"name\" : \"TestPolicy\" , \"description\" : \"Once upon a time there was a Policy, that lived in a Store.\" , \"policies\" : { ... }, \"schema\" : { ... }, \"trusted_issuers\" : { ... } } } } cedar_version : ( String ) The version of Cedar policy . The protocols of this version will be followed when processing Cedar schema and policies. policies : ( Object ) Object containing one or more policy IDs as keys, with their corresponding objects as values. See: policies schema . schema : ( String | Object ) The Cedar Schema. See schema below. trusted_issuers : ( Object of {unique_id => IdentitySource}(#trusted-issuer-schema) ) List of metadata for Identity Sources. schema # Either String or Object , where Object is preferred. Where Object - An object with encoding , content_type and body keys. For example: \"schema\" : { \"encoding\" : \"none\" , // can be one of \"none\" or \"base64\" \"content_type\" : \"cedar\" , // can be one of \"cedar\" or \"cedar-json\" \"body\" : \"namespace Jans {\\ntype Url = {\" hos t \": String, \" pa t h \": String, \" pro t ocol \": String};...\" } Where String - The schema in cedar-json format, encoded as Base64. For example: \"schema\" : \"cGVybWl0KAogICAgc...\" Cedar Policies Schema # The policies field describes the Cedar policies that will be used in Cedarling. Multiple policies can be defined, with each policy requiring a unique_policy_id . \"policies\" : { \"unique_policy_id\" : { \"cedar_version\" : \"v4.0.0\" , \"name\" : \"Policy for Unique Id\" , \"description\" : \"simple policy example\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : { ... }, }, ... } unique_policy_id : ( String ) A uniqe policy ID used to for tracking and auditing purposes. name : ( String ) A name for the policy description : ( String ) A brief description of cedar policy creation_date : ( String ) Policy creating date in YYYY-MM-DDTHH:MM:SS.ssssss policy_content : ( String | Object ) The Cedar Policy. See policy_content below. policy_content # Either String or Object , where Object is preferred. Where Object - An object with encoding , content_type and body keys. For example: \"policy_content\" : { \"encoding\" : \"none\" , // can be one of \"none\" or \"base64\" \"content_type\" : \"cedar\" , // ONLY \"cedar\" for now due to limitations in cedar-policy crate \"body\" : \"permit(\\n principal is Jans::User,\\n action in [Jans::Action::\\\"Update\\\"],\\n resource is Jans::Issue\\n)when{\\n principal.country == resource.country\\n};\" } Where String - The policy in cedar format, encoded as Base64. For example: \"policy_content\" : \"cGVybWl0KAogICAgc...\" Example of policies # Here is a non-normative example of the policies field: \"policies\" : { \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-first\" , \"description\" : \"simple policy example for principal workload\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : \"cGVybWl0KAogICAgc...\" }, \"0fo1kl928Afa0sc9123scma0123891asklajsh1233ab\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-second\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : \"kJW1bWl0KA0g3CAxa...\" }, \"1fo1kl928Afa0sc9123scma0123891asklajsh1233ac\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-third\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : { \"encoding\" : \"none\" , \"content_type\" : \"cedar\" , \"body\" : \"permit(...) where {...}\" } }, \"2fo1kl928Afa0sc9123scma0123891asklajsh1233ad\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-fourth\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : { \"encoding\" : \"base64\" , \"content_type\" : \"cedar\" , \"body\" : \"kJW1bWl0KA0g3CAxa...\" } }, ... } Trusted Issuers Schema # This record contains the information needed to validate tokens from this issuer: \"identity_source\" : { \"some_unique_id\" : { \"name\" : \"name_of_the_trusted_issuer\" , \"description\" : \"description for the trusted issuer\" , \"openid_configuration_endpoint\" : \"https://<trusted-issuer-hostname>/.well-known/openid-configuration\" , \"access_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"jti\" , ... }, \"id_tokens\" : { ... }, \"userinfo_tokens\" : { ... }, \"tx_tokens\" : { ... }, } ... } name : ( String ) The name of the trusted issuer. description : ( String ) A brief description of the trusted issuer, providing context for administrators. openid_configuration_endpoint : ( String ) The HTTPS URL for the OpenID Connect configuration endpoint (usually found at /.well-known/openid-configuration ). identity_source : ( Object , optional ) Metadata related to the tokens issued by this issuer. access_tokens , id_tokens , userinfo_tokens , and tx_tokens : See: Token Metadata Schema . Token Metadata Schema # The Token Entity Metadata Schema defines how tokens are mapped, parsed, and transformed within Cedarling. It allows you to specify how to extract user IDs, roles, and other claims from a token using customizable parsers. { \"trusted\" : bool , \"principal_identifier\" : \"str\" , \"user_id\" : \"<field name in token (e.g., 'email', 'sub', 'uid', etc.) or '' if not used>\" , \"role_mapping\" : \"<field for role assignment (e.g., 'role', 'memberOf', etc.) or '' if not used>\" , \"claim_mapping\" : { \"mapping_target\" : { \"parser\" : \"<type of parser ('regex' or 'json')>\" , \"type\" : \"<type identifier (e.g., 'Acme::Email')>\" , \"...\" : \"Additional configurations specific to the parser\" }, }, } Role mapping # role_mapping : (String OR Array of String, Optional ) Indicates which field in the token should be used for role-based access control. If not needed, set to an empty string ( \"\" ). You can include a role_mapping in each token, all of them will be executed by Cedarling. If none role_mapping defined the Cedarling will try to find role in userinfo token in field role . Claim mapping # claim_mapping: Defines how to extract and transform specific claims from the token. Each claim can have its own parser ( regex or json ) and type ( Acme::email_address , Acme::Url , etc.). In regex attribute mapping like \"UID\": {\"attr\": \"uid\", \"type\":\"String\"}, , type field can contain possible variants: String - to string without transformation, Number - parse string to float64 (JSON number) if error returns default value Boolean - if string NOT empty map to true else false Note, use of regex named capture groups which is more readable by referring to parts of a regex match by descriptive names rather than numbers. For example, (?P<name>...) defines a named capture group where name is the identifier, and ... is the regex pattern for what you want to capture. When you use (?x) modifier in regexp, ensure that you escaped character # => \\# . example of mapping email_address and Url : ... \"claim_mapping\" : { \"email\" : { \"parser\" : \"regex\" , \"type\" : \"Test::email_address\" , \"regex_expression\" : \"^(?P<UID>[^@]+)@(?P<DOMAIN>.+)$\" , \"UID\" : { \"attr\" : \"uid\" , \"type\" : \"String\" }, \"DOMAIN\" : { \"attr\" : \"domain\" , \"type\" : \"String\" } }, \"profile\" : { \"parser\" : \"regex\" , \"type\" : \"Test::Url\" , \"regex_expression\" : \"(?x) ^(?P<SCHEME>[a-zA-Z][a-zA-Z0-9+.-]*):\\\\/\\\\/(?P<HOST>[^\\\\/:\\\\#?]+)(?::(?<PORT>\\\\d+))?(?P<PATH>\\\\/[^?\\\\#]*)?(?:\\\\?(?P<QUERY>[^\\\\#]*))?(?:(?P<FRAGMENT>.*))?\" , \"SCHEME\" : { \"attr\" : \"scheme\" , \"type\" : \"String\" }, \"HOST\" : { \"attr\" : \"host\" , \"type\" : \"String\" }, \"PORT\" : { \"attr\" : \"port\" , \"type\" : \"String\" }, \"PATH\" : { \"attr\" : \"path\" , \"type\" : \"String\" }, \"QUERY\" : { \"attr\" : \"query\" , \"type\" : \"String\" }, \"FRAGMENT\" : { \"attr\" : \"fragment\" , \"type\" : \"String\" } } } ... Example Policy store # Here is a non-normative example of a cedarling_store.json file: { \"cedar_version\" : \"v4.0.0\" , \"policies\" : { \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" : { \"description\" : \"simple policy example\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : \"cedar_policy_encoded_in_base64\" } }, \"schema\" : \"schema_encoded_in_base64\" , \"identity_source\" : { \"08c6c18a654f492adcf3fe069d729b4d9e6bf82605cb\" : { \"name\" : \"Google\" , \"description\" : \"Consumer IDP\" , \"openid_configuration_endpoint\" : \"https://accounts.google.com/.well-known/openid-configuration\" , \"access_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"\" , }, \"id_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"sub\" , \"role_mapping\" : \"\" , }, \"userinfo_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"role\" , }, \"tx_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"\" , }, } } } Policy and Schema Authoring # You can hand create your Cedar policies and schema in Visual Studio . Make sure you run the cedar command line tool to validate both your schema and policies. The easiest way to author your policy store is to use the Policy Designer in Agama Lab . This tool helps you define the policies, schema and trusted IDPs and to publish a policy store to a Github repository. Minimum supported cedar-policy schema # Here is example of a minimum supported cedar-policy schema : namespace Jans { entity id_token = {\"aud\": String,\"iss\": String, \"sub\": String}; entity Role; entity User in [Role] = {}; entity Access_token = {\"aud\": String,\"iss\": String, \"jti\": String, \"client_id\": String}; entity Workload = {}; entity Issue = {}; action \"Update\" appliesTo { principal: [Workload, User, Role], resource: [Issue], context: {} }; } You can extend all of this entites and add your own. Mandatory entities is: id_token , Role , User , Access_token , Workload . Issue entity and Update action are optinal. Is created for example, you can create others for your needs. Context and Resource entities you can pass during authorization request and next entites creating based on the JWT tokens: id_token - entity based on the id JWT token fields. ID for entity based in jti field. Role - define role of user. Mapping defined in Token Metadata Schema . Claim in JWT usually is string or array of string. Each Role is parent for User . So to check role in policy use operator in to check hierarchy. User - entity based on the id and userinfo JWT token fields. If id and userinfo JWT token fields has different sub value, userinfo JWT token will be ignored. ID for entity based in sub field. (will be changed in future) Access_token - entity based on the access JWT token fields. ID for entity based in jti field. Workload - entity based on the access JWT token fields. ID for entity based in client_id field. Note on test fixtures # You will notice that test fixtures in the cedarling code base are quite often in yaml rather than in json. yaml is intended for cedarling internal use only . The rationale is that yaml has excellent support for embedded, indented, multiline string values. That is far easier to read than base64 encoded json strings, and is beneficial for debugging and validation that test cases are correct.", "title": "Policy Store"}, {"location": "cedarling/cedarling-policy-store/#cedarling-policy-store", "text": "The Cedarling Policy Store uses a JSON file named cedarling_store.json to store all necessary data for evaluating policies and verifying JWT tokens. The structure includes the following key components: Cedar Schema : The Cedar schema encoded in Base64. Cedar Policies : The Cedar policies encoded in Base64. Trusted Issuers : Details about the trusted issuers (see below for syntax). Note: The cedarling_store.json file is only needed if the bootstrap properties: CEDARLING_LOCK ; CEDARLING_POLICY_STORE_URI ; and CEDARLING_POLICY_STORE_ID are not set to a local location. If you're fetching the policies remotely, you don't need a cedarling_store.json file.", "title": "Cedarling Policy Store"}, {"location": "cedarling/cedarling-policy-store/#json-schema", "text": "The JSON Schema accepted by cedarling is defined as follows: { \"cedar_version\" : \"v4.0.0\" , \"policy_stores\" : { \"some_unique_string_id\" : { \"name\" : \"TestPolicy\" , \"description\" : \"Once upon a time there was a Policy, that lived in a Store.\" , \"policies\" : { ... }, \"schema\" : { ... }, \"trusted_issuers\" : { ... } } } } cedar_version : ( String ) The version of Cedar policy . The protocols of this version will be followed when processing Cedar schema and policies. policies : ( Object ) Object containing one or more policy IDs as keys, with their corresponding objects as values. See: policies schema . schema : ( String | Object ) The Cedar Schema. See schema below. trusted_issuers : ( Object of {unique_id => IdentitySource}(#trusted-issuer-schema) ) List of metadata for Identity Sources.", "title": "JSON Schema"}, {"location": "cedarling/cedarling-policy-store/#schema", "text": "Either String or Object , where Object is preferred. Where Object - An object with encoding , content_type and body keys. For example: \"schema\" : { \"encoding\" : \"none\" , // can be one of \"none\" or \"base64\" \"content_type\" : \"cedar\" , // can be one of \"cedar\" or \"cedar-json\" \"body\" : \"namespace Jans {\\ntype Url = {\" hos t \": String, \" pa t h \": String, \" pro t ocol \": String};...\" } Where String - The schema in cedar-json format, encoded as Base64. For example: \"schema\" : \"cGVybWl0KAogICAgc...\"", "title": "schema"}, {"location": "cedarling/cedarling-policy-store/#cedar-policies-schema", "text": "The policies field describes the Cedar policies that will be used in Cedarling. Multiple policies can be defined, with each policy requiring a unique_policy_id . \"policies\" : { \"unique_policy_id\" : { \"cedar_version\" : \"v4.0.0\" , \"name\" : \"Policy for Unique Id\" , \"description\" : \"simple policy example\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : { ... }, }, ... } unique_policy_id : ( String ) A uniqe policy ID used to for tracking and auditing purposes. name : ( String ) A name for the policy description : ( String ) A brief description of cedar policy creation_date : ( String ) Policy creating date in YYYY-MM-DDTHH:MM:SS.ssssss policy_content : ( String | Object ) The Cedar Policy. See policy_content below.", "title": "Cedar Policies Schema"}, {"location": "cedarling/cedarling-policy-store/#policy_content", "text": "Either String or Object , where Object is preferred. Where Object - An object with encoding , content_type and body keys. For example: \"policy_content\" : { \"encoding\" : \"none\" , // can be one of \"none\" or \"base64\" \"content_type\" : \"cedar\" , // ONLY \"cedar\" for now due to limitations in cedar-policy crate \"body\" : \"permit(\\n principal is Jans::User,\\n action in [Jans::Action::\\\"Update\\\"],\\n resource is Jans::Issue\\n)when{\\n principal.country == resource.country\\n};\" } Where String - The policy in cedar format, encoded as Base64. For example: \"policy_content\" : \"cGVybWl0KAogICAgc...\"", "title": "policy_content"}, {"location": "cedarling/cedarling-policy-store/#example-of-policies", "text": "Here is a non-normative example of the policies field: \"policies\" : { \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-first\" , \"description\" : \"simple policy example for principal workload\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : \"cGVybWl0KAogICAgc...\" }, \"0fo1kl928Afa0sc9123scma0123891asklajsh1233ab\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-second\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : \"kJW1bWl0KA0g3CAxa...\" }, \"1fo1kl928Afa0sc9123scma0123891asklajsh1233ac\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-third\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : { \"encoding\" : \"none\" , \"content_type\" : \"cedar\" , \"body\" : \"permit(...) where {...}\" } }, \"2fo1kl928Afa0sc9123scma0123891asklajsh1233ad\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-fourth\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : { \"encoding\" : \"base64\" , \"content_type\" : \"cedar\" , \"body\" : \"kJW1bWl0KA0g3CAxa...\" } }, ... }", "title": "Example of policies"}, {"location": "cedarling/cedarling-policy-store/#trusted-issuers-schema", "text": "This record contains the information needed to validate tokens from this issuer: \"identity_source\" : { \"some_unique_id\" : { \"name\" : \"name_of_the_trusted_issuer\" , \"description\" : \"description for the trusted issuer\" , \"openid_configuration_endpoint\" : \"https://<trusted-issuer-hostname>/.well-known/openid-configuration\" , \"access_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"jti\" , ... }, \"id_tokens\" : { ... }, \"userinfo_tokens\" : { ... }, \"tx_tokens\" : { ... }, } ... } name : ( String ) The name of the trusted issuer. description : ( String ) A brief description of the trusted issuer, providing context for administrators. openid_configuration_endpoint : ( String ) The HTTPS URL for the OpenID Connect configuration endpoint (usually found at /.well-known/openid-configuration ). identity_source : ( Object , optional ) Metadata related to the tokens issued by this issuer. access_tokens , id_tokens , userinfo_tokens , and tx_tokens : See: Token Metadata Schema .", "title": "Trusted Issuers Schema"}, {"location": "cedarling/cedarling-policy-store/#token-metadata-schema", "text": "The Token Entity Metadata Schema defines how tokens are mapped, parsed, and transformed within Cedarling. It allows you to specify how to extract user IDs, roles, and other claims from a token using customizable parsers. { \"trusted\" : bool , \"principal_identifier\" : \"str\" , \"user_id\" : \"<field name in token (e.g., 'email', 'sub', 'uid', etc.) or '' if not used>\" , \"role_mapping\" : \"<field for role assignment (e.g., 'role', 'memberOf', etc.) or '' if not used>\" , \"claim_mapping\" : { \"mapping_target\" : { \"parser\" : \"<type of parser ('regex' or 'json')>\" , \"type\" : \"<type identifier (e.g., 'Acme::Email')>\" , \"...\" : \"Additional configurations specific to the parser\" }, }, }", "title": "Token Metadata Schema"}, {"location": "cedarling/cedarling-policy-store/#role-mapping", "text": "role_mapping : (String OR Array of String, Optional ) Indicates which field in the token should be used for role-based access control. If not needed, set to an empty string ( \"\" ). You can include a role_mapping in each token, all of them will be executed by Cedarling. If none role_mapping defined the Cedarling will try to find role in userinfo token in field role .", "title": "Role mapping"}, {"location": "cedarling/cedarling-policy-store/#claim-mapping", "text": "claim_mapping: Defines how to extract and transform specific claims from the token. Each claim can have its own parser ( regex or json ) and type ( Acme::email_address , Acme::Url , etc.). In regex attribute mapping like \"UID\": {\"attr\": \"uid\", \"type\":\"String\"}, , type field can contain possible variants: String - to string without transformation, Number - parse string to float64 (JSON number) if error returns default value Boolean - if string NOT empty map to true else false Note, use of regex named capture groups which is more readable by referring to parts of a regex match by descriptive names rather than numbers. For example, (?P<name>...) defines a named capture group where name is the identifier, and ... is the regex pattern for what you want to capture. When you use (?x) modifier in regexp, ensure that you escaped character # => \\# . example of mapping email_address and Url : ... \"claim_mapping\" : { \"email\" : { \"parser\" : \"regex\" , \"type\" : \"Test::email_address\" , \"regex_expression\" : \"^(?P<UID>[^@]+)@(?P<DOMAIN>.+)$\" , \"UID\" : { \"attr\" : \"uid\" , \"type\" : \"String\" }, \"DOMAIN\" : { \"attr\" : \"domain\" , \"type\" : \"String\" } }, \"profile\" : { \"parser\" : \"regex\" , \"type\" : \"Test::Url\" , \"regex_expression\" : \"(?x) ^(?P<SCHEME>[a-zA-Z][a-zA-Z0-9+.-]*):\\\\/\\\\/(?P<HOST>[^\\\\/:\\\\#?]+)(?::(?<PORT>\\\\d+))?(?P<PATH>\\\\/[^?\\\\#]*)?(?:\\\\?(?P<QUERY>[^\\\\#]*))?(?:(?P<FRAGMENT>.*))?\" , \"SCHEME\" : { \"attr\" : \"scheme\" , \"type\" : \"String\" }, \"HOST\" : { \"attr\" : \"host\" , \"type\" : \"String\" }, \"PORT\" : { \"attr\" : \"port\" , \"type\" : \"String\" }, \"PATH\" : { \"attr\" : \"path\" , \"type\" : \"String\" }, \"QUERY\" : { \"attr\" : \"query\" , \"type\" : \"String\" }, \"FRAGMENT\" : { \"attr\" : \"fragment\" , \"type\" : \"String\" } } } ...", "title": "Claim mapping"}, {"location": "cedarling/cedarling-policy-store/#example-policy-store", "text": "Here is a non-normative example of a cedarling_store.json file: { \"cedar_version\" : \"v4.0.0\" , \"policies\" : { \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" : { \"description\" : \"simple policy example\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : \"cedar_policy_encoded_in_base64\" } }, \"schema\" : \"schema_encoded_in_base64\" , \"identity_source\" : { \"08c6c18a654f492adcf3fe069d729b4d9e6bf82605cb\" : { \"name\" : \"Google\" , \"description\" : \"Consumer IDP\" , \"openid_configuration_endpoint\" : \"https://accounts.google.com/.well-known/openid-configuration\" , \"access_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"\" , }, \"id_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"sub\" , \"role_mapping\" : \"\" , }, \"userinfo_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"role\" , }, \"tx_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"\" , }, } } }", "title": "Example Policy store"}, {"location": "cedarling/cedarling-policy-store/#policy-and-schema-authoring", "text": "You can hand create your Cedar policies and schema in Visual Studio . Make sure you run the cedar command line tool to validate both your schema and policies. The easiest way to author your policy store is to use the Policy Designer in Agama Lab . This tool helps you define the policies, schema and trusted IDPs and to publish a policy store to a Github repository.", "title": "Policy and Schema Authoring"}, {"location": "cedarling/cedarling-policy-store/#minimum-supported-cedar-policy-schema", "text": "Here is example of a minimum supported cedar-policy schema : namespace Jans { entity id_token = {\"aud\": String,\"iss\": String, \"sub\": String}; entity Role; entity User in [Role] = {}; entity Access_token = {\"aud\": String,\"iss\": String, \"jti\": String, \"client_id\": String}; entity Workload = {}; entity Issue = {}; action \"Update\" appliesTo { principal: [Workload, User, Role], resource: [Issue], context: {} }; } You can extend all of this entites and add your own. Mandatory entities is: id_token , Role , User , Access_token , Workload . Issue entity and Update action are optinal. Is created for example, you can create others for your needs. Context and Resource entities you can pass during authorization request and next entites creating based on the JWT tokens: id_token - entity based on the id JWT token fields. ID for entity based in jti field. Role - define role of user. Mapping defined in Token Metadata Schema . Claim in JWT usually is string or array of string. Each Role is parent for User . So to check role in policy use operator in to check hierarchy. User - entity based on the id and userinfo JWT token fields. If id and userinfo JWT token fields has different sub value, userinfo JWT token will be ignored. ID for entity based in sub field. (will be changed in future) Access_token - entity based on the access JWT token fields. ID for entity based in jti field. Workload - entity based on the access JWT token fields. ID for entity based in client_id field.", "title": "Minimum supported cedar-policy schema"}, {"location": "cedarling/cedarling-policy-store/#note-on-test-fixtures", "text": "You will notice that test fixtures in the cedarling code base are quite often in yaml rather than in json. yaml is intended for cedarling internal use only . The rationale is that yaml has excellent support for embedded, indented, multiline string values. That is far easier to read than base64 encoded json strings, and is beneficial for debugging and validation that test cases are correct.", "title": "Note on test fixtures"}, {"location": "cedarling/cedarling-properties/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling", "properties"], "text": "Cedarling Properties # These Bootstrap Properties control default application level behavior. CEDARLING_APPLICATION_NAME : Human friendly identifier for this application CEDARLING_POLICY_STORE_URI : Location of policy store JSON, used if policy store is not local, or retreived from Lock Master. CEDARLING_POLICY_STORE_ID : The identifier of the policy store in case there is more then one policy_store_id in the policy store. CEDARLING_USER_AUTHZ : When enabled , Cedar engine authorization is queried for a User principal. CEDARLING_WORKLOAD_AUTHZ : When enabled , Cedar engine authorization is queried for a Workload principal. CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION : AND , OR CEDARLING_MAPPING_USER : Name of Cedar User schema entity if we don't want to use default. When specified cedarling try build defined entity (from schema) as user instead of default User entity defined in cedar schema. Works in namespace defined in the policy store. CEDARLING_MAPPING_WORKLOAD : Name of Cedar Workload schema entity CEDARLING_MAPPING_ID_TOKEN : Name of Cedar id_token schema entity CEDARLING_MAPPING_ACCESS_TOKEN : Name of Cedar access_token schema entity CEDARLING_MAPPING_USERINFO_TOKEN : Name of Cedar userinfo schema entity The following bootstrap properties are needed to configure log behavior: CEDARLING_LOG_STORAGE : off , memory , std_out CEDARLING_LOG_LEVEL : System Log Level See here . Default to WARN CEDARLING_LOG_STDOUT_TYPE : Either System , Metric , or Decision . Default to System. CEDARLING_LOG_LEVEL : Log level filter for logging. Log level has only System log type entries. TRACE is lowest. FATAL is highest. Possible variants: FATAL ERROR WARN INFO DEBUG TRACE CEDARLING_DECISION_LOG_USER_CLAIMS : List of claims to map from user entity, such as [\"sub\", \"email\", \"username\", ...] CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS : List of claims to map from user entity, such as [\"client_id\", \"rp_id\", ...] CEDARLING_DECISION_LOG_DEFAULT_JWT_ID : Token claims that will be used for decision logging. Default is \"jti\", but perhaps some other claim is needed. CEDARLING_LOG_TTL : in case of memory store, TTL (time to live) of log entities in seconds. The following bootstrap properties are needed to configure JWT and cryptographic behavior: CEDARLING_LOCAL_JWKS : JWKS file with public keys CEDARLING_LOCAL_POLICY_STORE : JSON object with policy store CEDARLING_POLICY_STORE_LOCAL_FN : Local file with JSON object with policy store CEDARLING_JWT_SIG_VALIDATION : Enabled | Disabled -- Whether to check the signature of all JWT tokens. This requires an iss is present. CEDARLING_JWT_STATUS_VALIDATION : Enabled | Disabled -- Whether to check the status of the JWT. On startup, the Cedarling should fetch and retreive the latest Status List JWT from the .well-known/openid-configuration via the status_list_endpoint claim and cache it. See the IETF Draft for more info. CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED : Only tokens signed with these algorithms are acceptable to the Cedarling. CEDARLING_AT_ISS_VALIDATION : When enabled, the iss claim must be present in access token and the scheme must be https . CEDARLING_AT_JTI_VALIDATION : When enabled, the jti claim must be present in access token. CEDARLING_AT_NBF_VALIDATION : When enabled, the nbf claim must be present in access token and the Cedarling should verify that the current date is after the nbf . CEDARLING_AT_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_IDT_ISS_VALIDATION : When enabled, the iss claim must be present in id_token and the scheme must be https . CEDARLING_IDT_SUB_VALIDATION : When enabled, the sub claim must be present in id_token. CEDARLING_IDT_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_IDT_IAT_VALIDATION : When enabled, the iat claim must be present in id_token. CEDARLING_IDT_AUD_VALIDATION : When enabled, the aud claim must be present in id_token. CEDARLING_USERINFO_ISS_VALIDATION : When enabled, the iss claim must be present and the scheme must be https . CEDARLING_USERINFO_SUB_VALIDATION : When enabled, the sub claim must be present in Userinfo JWT. CEDARLING_USERINFO_AUD_VALIDATION : When enabled, the aud claim must be present in Userinfo JWT. CEDARLING_USERINFO_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_ID_TOKEN_TRUST_MODE : Strict | None . Varying levels of validations based on the preference of the developer. Strict mode requires (1) id_token aud matches the access_token client_id ; (2) if a Userinfo token is present, the sub matches the id_token, and that the aud matches the access token client_id. The following bootstrap properties are only needed for enterprise deployments. CEDARLING_LOCK : Enabled | Disabled. If Enabled, the Cedarling will connect to the Lock Master for policies, and subscribe for SSE events. CEDARLING_LOCK_MASTER_CONFIGURATION_URI : Required if LOCK == Enabled . URI where Cedarling can get JSON file with all required metadata about Lock Master, i.e. .well-known/lock-master-configuration . CEDARLING_LOCK_DYNAMIC_CONFIGURATION : Enabled | Disabled, controls whether Cedarling should listen for SSE config updates. CEDARLING_LOCK_SSA_JWT : SSA for DCR in a Lock Master deployment. The Cedarling will validate this SSA JWT prior to DCR. CEDARLING_LOCK_LOG_INTERVAL : How often to send log messages to Lock Master (0 to turn off trasmission). CEDARLING_LOCK_HEALTH_INTERVAL : How often to send health messages to Lock Master (0 to turn off transmission). CEDARLING_LOCK_TELEMETRY_INTERVAL : How often to send telemetry messages to Lock Master (0 to turn off transmission). CEDARLING_LOCK_LISTEN_SSE : Enabled | Disabled: controls whether Cedarling should listen for updates from the Lock Server. User-Workload Boolean Operation # The CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION property specifies what boolean operation to use for the USER and WORKLOAD when making authz (authorization) decisions. Available Operations # AND : authz will be successful if USER AND WORKLOAD is valid. OR : authz will be successful if USER OR WORKLOAD is valid. ID Token Trust Mode # The level of validation for the ID Token JWT can be set to either None or Strict . None Mode # Setting the validation level to None will not check for the conditions outlined in Strict Mode . Strict Mode # Strict mode requires: The id_token 's aud matches the access_token 's client_id ; if a Userinfo token is present, the sub matches the id_token , and that the aud matches the access token's client_id . Local JWKS # A local JWKS can be used by setting the CEDARLING_LOCAL_JWKS bootstrap property to a path to a local JSON file. When providing a local Json Web Key Store (JWKS), the file must follow the following schema: { \"trusted_issuer_id\" : [ ... ] \"another_trusted_issuer_id\" : [ ... ] } Where keys are Trusted Issuer IDs assigned to each key store and the values contains the JSON Web Keys as defined in RFC 7517 . The trusted_issuers_id is used to tag a JWKS with a unique identifier and enables using multiple key stores. Loading the bootstrap config # There are multiple ways to load your bootstrap config: From a JSON file From a YAML file You can load from both file types using the following code snippet: use cedarling :: BootstrapConfig ; let config = BootstrapConfig :: load_from_file ( \"./path/to/your/config.json\" ). unwrap (); Loading From JSON # Below is an example of a bootstrap config in JSON format. Not all fields should be specified, almost all have default value. { \"CEDARLING_APPLICATION_NAME\" : \"My App\" , \"CEDARLING_POLICY_STORE_URI\" : \"\" , \"CEDARLING_POLICY_STORE_ID\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"CEDARLING_LOG_TYPE\" : \"memory\" , \"CEDARLING_LOG_LEVEL\" : \"INFO\" , \"CEDARLING_DECISION_LOG_USER_CLAIMS\" : [ \"sub\" , \"email\" , \"username\" ], \"CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS\" : [ \"client_id\" , \"rp_id\" ], \"CEDARLING_DECISION_LOG_DEFAULT_JWT_ID\" : \"jti\" , \"CEDARLING_LOG_TTL\" : 60 , \"CEDARLING_USER_AUTHZ\" : \"enabled\" , \"CEDARLING_WORKLOAD_AUTHZ\" : \"enabled\" , \"CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION\" : \"AND\" , \"CEDARLING_MAPPING_USER\" : \"CustomUser\" , \"CEDARLING_MAPPING_WORKLOAD\" : \"CustomWorkload\" , \"CEDARLING_MAPPING_ID_TOKEN\" : \"CustomIdToken\" , \"CEDARLING_MAPPING_ACCESS_TOKEN\" : \"CustomAccessToken\" , \"CEDARLING_MAPPING_USERINFO_TOKEN\" : \"CustomUserinfoToken\" , \"CEDARLING_LOCAL_JWKS\" : \"../test_files/local_jwks.json\" , \"CEDARLING_LOCAL_POLICY_STORE\" : null , \"CEDARLING_POLICY_STORE_LOCAL_FN\" : \"../test_files/policy-store_blobby.json\" , \"CEDARLING_JWT_SIG_VALIDATION\" : \"enabled\" , \"CEDARLING_JWT_STATUS_VALIDATION\" : \"disabled\" , \"CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED\" : [ \"HS256\" , \"RS256\" ], \"CEDARLING_AT_ISS_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_JTI_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_NBF_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_ISS_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_SUB_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_IAT_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_AUD_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_ISS_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_SUB_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_AUD_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_ID_TOKEN_TRUST_MODE\" : \"Strict\" , \"CEDARLING_LOCK\" : \"disabled\" , \"CEDARLING_LOCK_MASTER_CONFIGURATION_URI\" : null , \"CEDARLING_DYNAMIC_CONFIGURATION\" : \"disabled\" , \"CEDARLING_LOCK_SSA_JWT\" : null , \"CEDARLING_AUDIT_HEALTH_INTERVAL\" : 0 , \"CEDARLING_AUDIT_TELEMETRY_INTERVAL\" : 0 , \"CEDARLING_LISTEN_SSE\" : \"disabled\" } Note that properties set to \"disabled\" , an empty string \"\" , zero 0 , and null can be ommited since they are the defaults. Local JWKS # A local JWKS can be used by setting the CEDARLING_LOCAL_JWKS bootstrap property to a path to a local JSON file. When providing a local Json Web Key Store (JWKS), the file must follow the following schema: { \"trusted_issuer_id\" : [ ... ] \"another_trusted_issuer_id\" : [ ... ] } Where keys are Trusted Issuer IDs assigned to each key store and the values contains the JSON Web Keys as defined in RFC 7517 . The trusted_issuers_id is used to tag a JWKS with a unique identifier and enables using multiple key stores. Note that properties set to \"disabled\" , an empty string \"\" , zero 0 , and null can be ommited since they are the defaults. Loading From YAML # Below is an example of a bootstrap config in YAML format. Not all fields should be specified, almost all have default value. CEDARLING_APPLICATION_NAME : My App CEDARLING_POLICY_STORE_URI : '' CEDARLING_POLICY_STORE_ID : '840da5d85403f35ea76519ed1a18a33989f855bf1cf8' CEDARLING_LOG_TYPE : 'memory' CEDARLING_LOG_LEVEL : 'INFO' CEDARLING_DECISION_LOG_USER_CLAIMS : [ \"sub\" , \"email\" ] CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS : [ \"client_id\" , \"rp_id\" ] CEDARLING_LOG_TTL : 60 CEDARLING_USER_AUTHZ : 'enabled' CEDARLING_WORKLOAD_AUTHZ : 'enabled' CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION : 'AND' CEDARLING_MAPPING_USER : 'CustomUser' CEDARLING_MAPPING_WORKLOAD : 'CustomWorkload' CEDARLING_MAPPING_ID_TOKEN : 'CustomIdToken' CEDARLING_MAPPING_ACCESS_TOKEN : 'CustomAccessToken' CEDARLING_MAPPING_USERINFO_TOKEN : 'CustomUserinfoToken' CEDARLING_LOCAL_JWKS : '../test_files/local_jwks.json' CEDARLING_LOCAL_POLICY_STORE : null CEDARLING_POLICY_STORE_LOCAL_FN : '../test_files/policy-store_blobby.json' CEDARLING_JWT_SIG_VALIDATION : 'enabled' CEDARLING_JWT_STATUS_VALIDATION : 'disabled' CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED : - 'HS256' - 'RS256' CEDARLING_AT_ISS_VALIDATION : 'disabled' CEDARLING_AT_JTI_VALIDATION : 'disabled' CEDARLING_AT_NBF_VALIDATION : 'disabled' CEDARLING_AT_EXP_VALIDATION : 'enabled' CEDARLING_IDT_ISS_VALIDATION : 'enabled' CEDARLING_IDT_SUB_VALIDATION : 'enabled' CEDARLING_IDT_EXP_VALIDATION : 'enabled' CEDARLING_IDT_IAT_VALIDATION : 'enabled' CEDARLING_IDT_AUD_VALIDATION : 'enabled' CEDARLING_USERINFO_ISS_VALIDATION : 'enabled' CEDARLING_USERINFO_SUB_VALIDATION : 'enabled' CEDARLING_USERINFO_AUD_VALIDATION : 'enabled' CEDARLING_USERINFO_EXP_VALIDATION : 'enabled' CEDARLING_ID_TOKEN_TRUST_MODE : 'Strict' CEDARLING_LOCK : 'disabled' CEDARLING_LOCK_MASTER_CONFIGURATION_URI : null CEDARLING_DYNAMIC_CONFIGURATION : 'disabled' CEDARLING_LOCK_SSA_JWT : 0 CEDARLING_AUDIT_HEALTH_INTERVAL : 0 CEDARLING_AUDIT_TELEMETRY_INTERVAL : 0 CEDARLING_LISTEN_SSE : 'disabled' Note that properties set to 'disabled' , an empty string '' , zero 0 , and null can be ommited since they are the defaults.", "title": "Properties"}, {"location": "cedarling/cedarling-properties/#cedarling-properties", "text": "These Bootstrap Properties control default application level behavior. CEDARLING_APPLICATION_NAME : Human friendly identifier for this application CEDARLING_POLICY_STORE_URI : Location of policy store JSON, used if policy store is not local, or retreived from Lock Master. CEDARLING_POLICY_STORE_ID : The identifier of the policy store in case there is more then one policy_store_id in the policy store. CEDARLING_USER_AUTHZ : When enabled , Cedar engine authorization is queried for a User principal. CEDARLING_WORKLOAD_AUTHZ : When enabled , Cedar engine authorization is queried for a Workload principal. CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION : AND , OR CEDARLING_MAPPING_USER : Name of Cedar User schema entity if we don't want to use default. When specified cedarling try build defined entity (from schema) as user instead of default User entity defined in cedar schema. Works in namespace defined in the policy store. CEDARLING_MAPPING_WORKLOAD : Name of Cedar Workload schema entity CEDARLING_MAPPING_ID_TOKEN : Name of Cedar id_token schema entity CEDARLING_MAPPING_ACCESS_TOKEN : Name of Cedar access_token schema entity CEDARLING_MAPPING_USERINFO_TOKEN : Name of Cedar userinfo schema entity The following bootstrap properties are needed to configure log behavior: CEDARLING_LOG_STORAGE : off , memory , std_out CEDARLING_LOG_LEVEL : System Log Level See here . Default to WARN CEDARLING_LOG_STDOUT_TYPE : Either System , Metric , or Decision . Default to System. CEDARLING_LOG_LEVEL : Log level filter for logging. Log level has only System log type entries. TRACE is lowest. FATAL is highest. Possible variants: FATAL ERROR WARN INFO DEBUG TRACE CEDARLING_DECISION_LOG_USER_CLAIMS : List of claims to map from user entity, such as [\"sub\", \"email\", \"username\", ...] CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS : List of claims to map from user entity, such as [\"client_id\", \"rp_id\", ...] CEDARLING_DECISION_LOG_DEFAULT_JWT_ID : Token claims that will be used for decision logging. Default is \"jti\", but perhaps some other claim is needed. CEDARLING_LOG_TTL : in case of memory store, TTL (time to live) of log entities in seconds. The following bootstrap properties are needed to configure JWT and cryptographic behavior: CEDARLING_LOCAL_JWKS : JWKS file with public keys CEDARLING_LOCAL_POLICY_STORE : JSON object with policy store CEDARLING_POLICY_STORE_LOCAL_FN : Local file with JSON object with policy store CEDARLING_JWT_SIG_VALIDATION : Enabled | Disabled -- Whether to check the signature of all JWT tokens. This requires an iss is present. CEDARLING_JWT_STATUS_VALIDATION : Enabled | Disabled -- Whether to check the status of the JWT. On startup, the Cedarling should fetch and retreive the latest Status List JWT from the .well-known/openid-configuration via the status_list_endpoint claim and cache it. See the IETF Draft for more info. CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED : Only tokens signed with these algorithms are acceptable to the Cedarling. CEDARLING_AT_ISS_VALIDATION : When enabled, the iss claim must be present in access token and the scheme must be https . CEDARLING_AT_JTI_VALIDATION : When enabled, the jti claim must be present in access token. CEDARLING_AT_NBF_VALIDATION : When enabled, the nbf claim must be present in access token and the Cedarling should verify that the current date is after the nbf . CEDARLING_AT_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_IDT_ISS_VALIDATION : When enabled, the iss claim must be present in id_token and the scheme must be https . CEDARLING_IDT_SUB_VALIDATION : When enabled, the sub claim must be present in id_token. CEDARLING_IDT_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_IDT_IAT_VALIDATION : When enabled, the iat claim must be present in id_token. CEDARLING_IDT_AUD_VALIDATION : When enabled, the aud claim must be present in id_token. CEDARLING_USERINFO_ISS_VALIDATION : When enabled, the iss claim must be present and the scheme must be https . CEDARLING_USERINFO_SUB_VALIDATION : When enabled, the sub claim must be present in Userinfo JWT. CEDARLING_USERINFO_AUD_VALIDATION : When enabled, the aud claim must be present in Userinfo JWT. CEDARLING_USERINFO_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_ID_TOKEN_TRUST_MODE : Strict | None . Varying levels of validations based on the preference of the developer. Strict mode requires (1) id_token aud matches the access_token client_id ; (2) if a Userinfo token is present, the sub matches the id_token, and that the aud matches the access token client_id. The following bootstrap properties are only needed for enterprise deployments. CEDARLING_LOCK : Enabled | Disabled. If Enabled, the Cedarling will connect to the Lock Master for policies, and subscribe for SSE events. CEDARLING_LOCK_MASTER_CONFIGURATION_URI : Required if LOCK == Enabled . URI where Cedarling can get JSON file with all required metadata about Lock Master, i.e. .well-known/lock-master-configuration . CEDARLING_LOCK_DYNAMIC_CONFIGURATION : Enabled | Disabled, controls whether Cedarling should listen for SSE config updates. CEDARLING_LOCK_SSA_JWT : SSA for DCR in a Lock Master deployment. The Cedarling will validate this SSA JWT prior to DCR. CEDARLING_LOCK_LOG_INTERVAL : How often to send log messages to Lock Master (0 to turn off trasmission). CEDARLING_LOCK_HEALTH_INTERVAL : How often to send health messages to Lock Master (0 to turn off transmission). CEDARLING_LOCK_TELEMETRY_INTERVAL : How often to send telemetry messages to Lock Master (0 to turn off transmission). CEDARLING_LOCK_LISTEN_SSE : Enabled | Disabled: controls whether Cedarling should listen for updates from the Lock Server.", "title": "Cedarling Properties"}, {"location": "cedarling/cedarling-properties/#user-workload-boolean-operation", "text": "The CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION property specifies what boolean operation to use for the USER and WORKLOAD when making authz (authorization) decisions.", "title": "User-Workload Boolean Operation"}, {"location": "cedarling/cedarling-properties/#available-operations", "text": "AND : authz will be successful if USER AND WORKLOAD is valid. OR : authz will be successful if USER OR WORKLOAD is valid.", "title": "Available Operations"}, {"location": "cedarling/cedarling-properties/#id-token-trust-mode", "text": "The level of validation for the ID Token JWT can be set to either None or Strict .", "title": "ID Token Trust Mode"}, {"location": "cedarling/cedarling-properties/#none-mode", "text": "Setting the validation level to None will not check for the conditions outlined in Strict Mode .", "title": "None Mode"}, {"location": "cedarling/cedarling-properties/#strict-mode", "text": "Strict mode requires: The id_token 's aud matches the access_token 's client_id ; if a Userinfo token is present, the sub matches the id_token , and that the aud matches the access token's client_id .", "title": "Strict Mode"}, {"location": "cedarling/cedarling-properties/#local-jwks", "text": "A local JWKS can be used by setting the CEDARLING_LOCAL_JWKS bootstrap property to a path to a local JSON file. When providing a local Json Web Key Store (JWKS), the file must follow the following schema: { \"trusted_issuer_id\" : [ ... ] \"another_trusted_issuer_id\" : [ ... ] } Where keys are Trusted Issuer IDs assigned to each key store and the values contains the JSON Web Keys as defined in RFC 7517 . The trusted_issuers_id is used to tag a JWKS with a unique identifier and enables using multiple key stores.", "title": "Local JWKS"}, {"location": "cedarling/cedarling-properties/#loading-the-bootstrap-config", "text": "There are multiple ways to load your bootstrap config: From a JSON file From a YAML file You can load from both file types using the following code snippet: use cedarling :: BootstrapConfig ; let config = BootstrapConfig :: load_from_file ( \"./path/to/your/config.json\" ). unwrap ();", "title": "Loading the bootstrap config"}, {"location": "cedarling/cedarling-properties/#loading-from-json", "text": "Below is an example of a bootstrap config in JSON format. Not all fields should be specified, almost all have default value. { \"CEDARLING_APPLICATION_NAME\" : \"My App\" , \"CEDARLING_POLICY_STORE_URI\" : \"\" , \"CEDARLING_POLICY_STORE_ID\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"CEDARLING_LOG_TYPE\" : \"memory\" , \"CEDARLING_LOG_LEVEL\" : \"INFO\" , \"CEDARLING_DECISION_LOG_USER_CLAIMS\" : [ \"sub\" , \"email\" , \"username\" ], \"CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS\" : [ \"client_id\" , \"rp_id\" ], \"CEDARLING_DECISION_LOG_DEFAULT_JWT_ID\" : \"jti\" , \"CEDARLING_LOG_TTL\" : 60 , \"CEDARLING_USER_AUTHZ\" : \"enabled\" , \"CEDARLING_WORKLOAD_AUTHZ\" : \"enabled\" , \"CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION\" : \"AND\" , \"CEDARLING_MAPPING_USER\" : \"CustomUser\" , \"CEDARLING_MAPPING_WORKLOAD\" : \"CustomWorkload\" , \"CEDARLING_MAPPING_ID_TOKEN\" : \"CustomIdToken\" , \"CEDARLING_MAPPING_ACCESS_TOKEN\" : \"CustomAccessToken\" , \"CEDARLING_MAPPING_USERINFO_TOKEN\" : \"CustomUserinfoToken\" , \"CEDARLING_LOCAL_JWKS\" : \"../test_files/local_jwks.json\" , \"CEDARLING_LOCAL_POLICY_STORE\" : null , \"CEDARLING_POLICY_STORE_LOCAL_FN\" : \"../test_files/policy-store_blobby.json\" , \"CEDARLING_JWT_SIG_VALIDATION\" : \"enabled\" , \"CEDARLING_JWT_STATUS_VALIDATION\" : \"disabled\" , \"CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED\" : [ \"HS256\" , \"RS256\" ], \"CEDARLING_AT_ISS_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_JTI_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_NBF_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_ISS_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_SUB_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_IAT_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_AUD_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_ISS_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_SUB_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_AUD_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_ID_TOKEN_TRUST_MODE\" : \"Strict\" , \"CEDARLING_LOCK\" : \"disabled\" , \"CEDARLING_LOCK_MASTER_CONFIGURATION_URI\" : null , \"CEDARLING_DYNAMIC_CONFIGURATION\" : \"disabled\" , \"CEDARLING_LOCK_SSA_JWT\" : null , \"CEDARLING_AUDIT_HEALTH_INTERVAL\" : 0 , \"CEDARLING_AUDIT_TELEMETRY_INTERVAL\" : 0 , \"CEDARLING_LISTEN_SSE\" : \"disabled\" } Note that properties set to \"disabled\" , an empty string \"\" , zero 0 , and null can be ommited since they are the defaults.", "title": "Loading From JSON"}, {"location": "cedarling/cedarling-properties/#local-jwks_1", "text": "A local JWKS can be used by setting the CEDARLING_LOCAL_JWKS bootstrap property to a path to a local JSON file. When providing a local Json Web Key Store (JWKS), the file must follow the following schema: { \"trusted_issuer_id\" : [ ... ] \"another_trusted_issuer_id\" : [ ... ] } Where keys are Trusted Issuer IDs assigned to each key store and the values contains the JSON Web Keys as defined in RFC 7517 . The trusted_issuers_id is used to tag a JWKS with a unique identifier and enables using multiple key stores. Note that properties set to \"disabled\" , an empty string \"\" , zero 0 , and null can be ommited since they are the defaults.", "title": "Local JWKS"}, {"location": "cedarling/cedarling-properties/#loading-from-yaml", "text": "Below is an example of a bootstrap config in YAML format. Not all fields should be specified, almost all have default value. CEDARLING_APPLICATION_NAME : My App CEDARLING_POLICY_STORE_URI : '' CEDARLING_POLICY_STORE_ID : '840da5d85403f35ea76519ed1a18a33989f855bf1cf8' CEDARLING_LOG_TYPE : 'memory' CEDARLING_LOG_LEVEL : 'INFO' CEDARLING_DECISION_LOG_USER_CLAIMS : [ \"sub\" , \"email\" ] CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS : [ \"client_id\" , \"rp_id\" ] CEDARLING_LOG_TTL : 60 CEDARLING_USER_AUTHZ : 'enabled' CEDARLING_WORKLOAD_AUTHZ : 'enabled' CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION : 'AND' CEDARLING_MAPPING_USER : 'CustomUser' CEDARLING_MAPPING_WORKLOAD : 'CustomWorkload' CEDARLING_MAPPING_ID_TOKEN : 'CustomIdToken' CEDARLING_MAPPING_ACCESS_TOKEN : 'CustomAccessToken' CEDARLING_MAPPING_USERINFO_TOKEN : 'CustomUserinfoToken' CEDARLING_LOCAL_JWKS : '../test_files/local_jwks.json' CEDARLING_LOCAL_POLICY_STORE : null CEDARLING_POLICY_STORE_LOCAL_FN : '../test_files/policy-store_blobby.json' CEDARLING_JWT_SIG_VALIDATION : 'enabled' CEDARLING_JWT_STATUS_VALIDATION : 'disabled' CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED : - 'HS256' - 'RS256' CEDARLING_AT_ISS_VALIDATION : 'disabled' CEDARLING_AT_JTI_VALIDATION : 'disabled' CEDARLING_AT_NBF_VALIDATION : 'disabled' CEDARLING_AT_EXP_VALIDATION : 'enabled' CEDARLING_IDT_ISS_VALIDATION : 'enabled' CEDARLING_IDT_SUB_VALIDATION : 'enabled' CEDARLING_IDT_EXP_VALIDATION : 'enabled' CEDARLING_IDT_IAT_VALIDATION : 'enabled' CEDARLING_IDT_AUD_VALIDATION : 'enabled' CEDARLING_USERINFO_ISS_VALIDATION : 'enabled' CEDARLING_USERINFO_SUB_VALIDATION : 'enabled' CEDARLING_USERINFO_AUD_VALIDATION : 'enabled' CEDARLING_USERINFO_EXP_VALIDATION : 'enabled' CEDARLING_ID_TOKEN_TRUST_MODE : 'Strict' CEDARLING_LOCK : 'disabled' CEDARLING_LOCK_MASTER_CONFIGURATION_URI : null CEDARLING_DYNAMIC_CONFIGURATION : 'disabled' CEDARLING_LOCK_SSA_JWT : 0 CEDARLING_AUDIT_HEALTH_INTERVAL : 0 CEDARLING_AUDIT_TELEMETRY_INTERVAL : 0 CEDARLING_LISTEN_SSE : 'disabled' Note that properties set to 'disabled' , an empty string '' , zero 0 , and null can be ommited since they are the defaults.", "title": "Loading From YAML"}, {"location": "cedarling/cedarling-wasm/", "tags": ["cedarling", "wasm"], "text": "WASM for Cedarling # Cedarling provides a binding for JavaScript programs via the wasm-pack tool. This allows browser developers to use the cedarling crate in their code directly. Requirements # Rust 1.63 or greater Installed wasm-pack via cargo clang with wasm target support Building # Install wasm-pack by: cargo install wasm-pack Build cedarling wasm in release: wasm-pack build --release --target web wasm-pack automatically make optimization of wasm binary file, using wasm-opt . - Get result in the pkg folder. Including in projects # For using result files in browser project you need make result pkg folder accessible for loading in the browser so that you can later import the corresponding file from the browser. Here is example of code snippet: < script type = \"module\" > import initWasm , { init } from \"/pkg/cedarling_wasm.js\" ; async function main () { await initWasm (); // Initialize the WebAssembly module // init cedarling with `BOOTSTRAP` config let instance = await init ({ \"CEDARLING_APPLICATION_NAME\" : \"My App\" , \"CEDARLING_POLICY_STORE_URI\" : \"https://example.com/policy-store.json\" , \"CEDARLING_LOG_TYPE\" : \"memory\" , \"CEDARLING_LOG_LEVEL\" : \"INFO\" , \"CEDARLING_LOG_TTL\" : 120 , \"CEDARLING_DECISION_LOG_USER_CLAIMS \" : [ \"aud\" , \"sub\" , \"email\" , \"username\" ], \"CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS \" : [ \"aud\" , \"client_id\" , \"rp_id\" ], \"CEDARLING_USER_AUTHZ\" : \"enabled\" , \"CEDARLING_WORKLOAD_AUTHZ\" : \"enabled\" , \"CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION\" : \"AND\" , }); // make authorize request let result = await instance . authorize ({ \"tokens\" : { \"access_token\" : \"...\" , \"id_token\" : \"...\" , \"userinfo_token\" : \"...\" , }, \"action\" : 'Jans::Action::\"Read\"' , \"resource\" : { \"type\" : \"Jans::Application\" , \"id\" : \"some_id\" , \"app_id\" : \"application_id\" , \"name\" : \"Some Application\" , \"url\" : { \"host\" : \"jans.test\" , \"path\" : \"/protected-endpoint\" , \"protocol\" : \"http\" } }, \"context\" : { \"current_time\" : Math . floor ( Date . now () / 1000 ), \"device_health\" : [ \"Healthy\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"geolocation\" : [ \"America\" ], \"network\" : \"127.0.0.1\" , \"network_type\" : \"Local\" , \"operating_system\" : \"Linux\" , \"user_agent\" : \"Linux\" }, }); console . log ( \"result:\" , result ); } main (). catch ( console . error ); </ script > Usage # Before usage make sure that you have completed Building steps. You can find usage examples in the following locations: jans-cedarling/bindings/cedarling_wasm/index.html : A simple example demonstrating basic usage. jans-cedarling/bindings/cedarling_wasm/cedarling_app.html : A fully featured Cedarling browser app where you can test and validate your configuration. Defined API # /** * Create a new instance of the Cedarling application. * This function can take as config parameter the eather `Map` other `Object` */ export function init ( config : any ) : Promise < Cedarling > ; /** * The instance of the Cedarling application. */ export class Cedarling { /** * Create a new instance of the Cedarling application. * Assume that config is `Object` */ static new ( config : object ) : Promise < Cedarling > ; /** * Create a new instance of the Cedarling application. * Assume that config is `Map` */ static new_from_map ( config : Map < any , any > ) : Promise < Cedarling > ; /** * Authorize request * makes authorization decision based on the [`Request`] */ authorize ( request : any ) : Promise < AuthorizeResult > ; /** * Get logs and remove them from the storage. * Returns `Array` of `Map` */ pop_logs () : Array < any > ; /** * Get specific log entry. * Returns `Map` with values or `null`. */ get_log_by_id ( id : string ) : any ; /** * Returns a list of all log ids. * Returns `Array` of `String` */ get_log_ids () : Array < any > ; } /** * A WASM wrapper for the Rust `cedarling::AuthorizeResult` struct. * Represents the result of an authorization request. */ export class AuthorizeResult { /** * Convert `AuthorizeResult` to json string value */ json_string () : string ; /** * Result of authorization where principal is `Jans::Workload` */ workload? : AuthorizeResultResponse ; /** * Result of authorization where principal is `Jans::User` */ person? : AuthorizeResultResponse ; /** * Result of authorization * true means `ALLOW` * false means `Deny` * * this field is [`bool`] type to be compatible with [authzen Access Evaluation Decision](https://openid.github.io/authzen/#section-6.2.1). */ decision : boolean ; } /** * A WASM wrapper for the Rust `cedar_policy::Response` struct. * Represents the result of an authorization request. */ export class AuthorizeResultResponse { /** * Authorization decision */ readonly decision : boolean ; /** * Diagnostics providing more information on how this decision was reached */ readonly diagnostics : Diagnostics ; } /** * Diagnostics * =========== * * Provides detailed information about how a policy decision was made, including policies that contributed to the decision and any errors encountered during evaluation. */ export class Diagnostics { /** * `PolicyId`s of the policies that contributed to the decision. * If no policies applied to the request, this set will be empty. * * The ids should be treated as unordered, */ readonly reason : ( string )[]; /** * Errors that occurred during authorization. The errors should be * treated as unordered, since policies may be evaluated in any order. */ readonly errors : ( PolicyEvaluationError )[]; } /** * PolicyEvaluationError * ===================== * * Represents an error that occurred when evaluating a Cedar policy. */ export class PolicyEvaluationError { /** * Id of the policy with an error */ readonly id : string ; /** * Underlying evaluation error string representation */ readonly error : string ; }", "title": "WASM"}, {"location": "cedarling/cedarling-wasm/#wasm-for-cedarling", "text": "Cedarling provides a binding for JavaScript programs via the wasm-pack tool. This allows browser developers to use the cedarling crate in their code directly.", "title": "WASM for Cedarling"}, {"location": "cedarling/cedarling-wasm/#requirements", "text": "Rust 1.63 or greater Installed wasm-pack via cargo clang with wasm target support", "title": "Requirements"}, {"location": "cedarling/cedarling-wasm/#building", "text": "Install wasm-pack by: cargo install wasm-pack Build cedarling wasm in release: wasm-pack build --release --target web wasm-pack automatically make optimization of wasm binary file, using wasm-opt . - Get result in the pkg folder.", "title": "Building"}, {"location": "cedarling/cedarling-wasm/#including-in-projects", "text": "For using result files in browser project you need make result pkg folder accessible for loading in the browser so that you can later import the corresponding file from the browser. Here is example of code snippet: < script type = \"module\" > import initWasm , { init } from \"/pkg/cedarling_wasm.js\" ; async function main () { await initWasm (); // Initialize the WebAssembly module // init cedarling with `BOOTSTRAP` config let instance = await init ({ \"CEDARLING_APPLICATION_NAME\" : \"My App\" , \"CEDARLING_POLICY_STORE_URI\" : \"https://example.com/policy-store.json\" , \"CEDARLING_LOG_TYPE\" : \"memory\" , \"CEDARLING_LOG_LEVEL\" : \"INFO\" , \"CEDARLING_LOG_TTL\" : 120 , \"CEDARLING_DECISION_LOG_USER_CLAIMS \" : [ \"aud\" , \"sub\" , \"email\" , \"username\" ], \"CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS \" : [ \"aud\" , \"client_id\" , \"rp_id\" ], \"CEDARLING_USER_AUTHZ\" : \"enabled\" , \"CEDARLING_WORKLOAD_AUTHZ\" : \"enabled\" , \"CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION\" : \"AND\" , }); // make authorize request let result = await instance . authorize ({ \"tokens\" : { \"access_token\" : \"...\" , \"id_token\" : \"...\" , \"userinfo_token\" : \"...\" , }, \"action\" : 'Jans::Action::\"Read\"' , \"resource\" : { \"type\" : \"Jans::Application\" , \"id\" : \"some_id\" , \"app_id\" : \"application_id\" , \"name\" : \"Some Application\" , \"url\" : { \"host\" : \"jans.test\" , \"path\" : \"/protected-endpoint\" , \"protocol\" : \"http\" } }, \"context\" : { \"current_time\" : Math . floor ( Date . now () / 1000 ), \"device_health\" : [ \"Healthy\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"geolocation\" : [ \"America\" ], \"network\" : \"127.0.0.1\" , \"network_type\" : \"Local\" , \"operating_system\" : \"Linux\" , \"user_agent\" : \"Linux\" }, }); console . log ( \"result:\" , result ); } main (). catch ( console . error ); </ script >", "title": "Including in projects"}, {"location": "cedarling/cedarling-wasm/#usage", "text": "Before usage make sure that you have completed Building steps. You can find usage examples in the following locations: jans-cedarling/bindings/cedarling_wasm/index.html : A simple example demonstrating basic usage. jans-cedarling/bindings/cedarling_wasm/cedarling_app.html : A fully featured Cedarling browser app where you can test and validate your configuration.", "title": "Usage"}, {"location": "cedarling/cedarling-wasm/#defined-api", "text": "/** * Create a new instance of the Cedarling application. * This function can take as config parameter the eather `Map` other `Object` */ export function init ( config : any ) : Promise < Cedarling > ; /** * The instance of the Cedarling application. */ export class Cedarling { /** * Create a new instance of the Cedarling application. * Assume that config is `Object` */ static new ( config : object ) : Promise < Cedarling > ; /** * Create a new instance of the Cedarling application. * Assume that config is `Map` */ static new_from_map ( config : Map < any , any > ) : Promise < Cedarling > ; /** * Authorize request * makes authorization decision based on the [`Request`] */ authorize ( request : any ) : Promise < AuthorizeResult > ; /** * Get logs and remove them from the storage. * Returns `Array` of `Map` */ pop_logs () : Array < any > ; /** * Get specific log entry. * Returns `Map` with values or `null`. */ get_log_by_id ( id : string ) : any ; /** * Returns a list of all log ids. * Returns `Array` of `String` */ get_log_ids () : Array < any > ; } /** * A WASM wrapper for the Rust `cedarling::AuthorizeResult` struct. * Represents the result of an authorization request. */ export class AuthorizeResult { /** * Convert `AuthorizeResult` to json string value */ json_string () : string ; /** * Result of authorization where principal is `Jans::Workload` */ workload? : AuthorizeResultResponse ; /** * Result of authorization where principal is `Jans::User` */ person? : AuthorizeResultResponse ; /** * Result of authorization * true means `ALLOW` * false means `Deny` * * this field is [`bool`] type to be compatible with [authzen Access Evaluation Decision](https://openid.github.io/authzen/#section-6.2.1). */ decision : boolean ; } /** * A WASM wrapper for the Rust `cedar_policy::Response` struct. * Represents the result of an authorization request. */ export class AuthorizeResultResponse { /** * Authorization decision */ readonly decision : boolean ; /** * Diagnostics providing more information on how this decision was reached */ readonly diagnostics : Diagnostics ; } /** * Diagnostics * =========== * * Provides detailed information about how a policy decision was made, including policies that contributed to the decision and any errors encountered during evaluation. */ export class Diagnostics { /** * `PolicyId`s of the policies that contributed to the decision. * If no policies applied to the request, this set will be empty. * * The ids should be treated as unordered, */ readonly reason : ( string )[]; /** * Errors that occurred during authorization. The errors should be * treated as unordered, since policies may be evaluated in any order. */ readonly errors : ( PolicyEvaluationError )[]; } /** * PolicyEvaluationError * ===================== * * Represents an error that occurred when evaluating a Cedar policy. */ export class PolicyEvaluationError { /** * Id of the policy with an error */ readonly id : string ; /** * Underlying evaluation error string representation */ readonly error : string ; }", "title": "Defined API"}, {"location": "cedarling/python/sidecar/", "tags": ["cedarling", "python", "sidecar"], "text": "Flask Sidecar # The sidecar is a containerized Flask project that uses the cedarling_python binding and implements the AuthZen specification. This image can run alongside another service and uses cedarling to validate evaluation requests against a policy store. Docker setup # Ensure that you have installed docker and docker compose . Clone the Janssen repository Navigate to jans/jans-cedarling/flask-sidecar Edit the provided secrets/bootstrap.json file to your specifications. The configuration keys are described here . Run docker compose up For cloud deployments, please use the provided Dockerfile and pass your bootstrap configuration via the environment variable CEDARLING_BOOTSTRAP_CONFIG_FILE . The sidecar runs on port 5000. OpenAPI documentation is available at http://0.0.0.0:5000/swagger-ui Usage # The sidecar has one endpoint: /cedarling/evaluation . Example request to the evaluation endpoint: { \"subject\": { \"type\": \"string\", \"id\": \"string\" }, \"resource\": { \"type\": \"Jans::Application\", \"id\": \"some_id\", \"properties\": { \"app_id\": \"application_id\", \"name\": \"Some Application\", \"url\": { \"host\": \"jans.test\", \"path\": \"/protected-endpoint\", \"protocol\": \"http\" } } }, \"action\": { \"name\": \"Jans::Action::\\\"Read\\\"\" }, \"context\": { \"access_token\": \"...\", \"id_token\": \"...\", \"userinfo_token\": \"...\", \"device_health\": [ \"Healthy\" ], \"fraud_indicators\": [ \"Allowed\" ], \"geolocation\": [ \"America\" ], \"network\": \"127.0.0.1\", \"network_type\": \"Local\", \"operating_system\": \"Linux\", \"user_agent\": \"Linux\", \"current_time\": 1 } } Cedarling requires OpenID Userinfo, Access, and ID tokens to construct the principal entity, as described here . As per AuthZen specification, these values are sent in the context field of the payload. Conversely, the subject field is currently not used by cedarling. These 3 tokens are subsequently removed from the context object before it is passed to cedarling. Upon creating the principal, action, resource, and context entities, cedarling will evaluate these entities against the policies defined in the policy store. Then it will return a true/false decision. If the decision is false, the sidecar will analyze cedarling diagnostics and provide additional information for the admin. Example of true case: { \"decision\": true } Example of false case: { \"context\": { \"reason_admin\": { \"person diagnostics\": [], \"person error\": [], \"person evaluation\": \"DENY\", \"workload diagnostics\": [], \"workload evaluation\": \"DENY\", \"workload_error\": [] } }, \"decision\": false } In this example both the person and workload evaluations were DENY , so the decision was false. Additional information is returned in the context field as per AuthZen specification.", "title": "Sidecar"}, {"location": "cedarling/python/sidecar/#flask-sidecar", "text": "The sidecar is a containerized Flask project that uses the cedarling_python binding and implements the AuthZen specification. This image can run alongside another service and uses cedarling to validate evaluation requests against a policy store.", "title": "Flask Sidecar"}, {"location": "cedarling/python/sidecar/#docker-setup", "text": "Ensure that you have installed docker and docker compose . Clone the Janssen repository Navigate to jans/jans-cedarling/flask-sidecar Edit the provided secrets/bootstrap.json file to your specifications. The configuration keys are described here . Run docker compose up For cloud deployments, please use the provided Dockerfile and pass your bootstrap configuration via the environment variable CEDARLING_BOOTSTRAP_CONFIG_FILE . The sidecar runs on port 5000. OpenAPI documentation is available at http://0.0.0.0:5000/swagger-ui", "title": "Docker setup"}, {"location": "cedarling/python/sidecar/#usage", "text": "The sidecar has one endpoint: /cedarling/evaluation . Example request to the evaluation endpoint: { \"subject\": { \"type\": \"string\", \"id\": \"string\" }, \"resource\": { \"type\": \"Jans::Application\", \"id\": \"some_id\", \"properties\": { \"app_id\": \"application_id\", \"name\": \"Some Application\", \"url\": { \"host\": \"jans.test\", \"path\": \"/protected-endpoint\", \"protocol\": \"http\" } } }, \"action\": { \"name\": \"Jans::Action::\\\"Read\\\"\" }, \"context\": { \"access_token\": \"...\", \"id_token\": \"...\", \"userinfo_token\": \"...\", \"device_health\": [ \"Healthy\" ], \"fraud_indicators\": [ \"Allowed\" ], \"geolocation\": [ \"America\" ], \"network\": \"127.0.0.1\", \"network_type\": \"Local\", \"operating_system\": \"Linux\", \"user_agent\": \"Linux\", \"current_time\": 1 } } Cedarling requires OpenID Userinfo, Access, and ID tokens to construct the principal entity, as described here . As per AuthZen specification, these values are sent in the context field of the payload. Conversely, the subject field is currently not used by cedarling. These 3 tokens are subsequently removed from the context object before it is passed to cedarling. Upon creating the principal, action, resource, and context entities, cedarling will evaluate these entities against the policies defined in the policy store. Then it will return a true/false decision. If the decision is false, the sidecar will analyze cedarling diagnostics and provide additional information for the admin. Example of true case: { \"decision\": true } Example of false case: { \"context\": { \"reason_admin\": { \"person diagnostics\": [], \"person error\": [], \"person evaluation\": \"DENY\", \"workload diagnostics\": [], \"workload evaluation\": \"DENY\", \"workload_error\": [] } }, \"decision\": false } In this example both the person and workload evaluations were DENY , so the decision was false. Additional information is returned in the context field as per AuthZen specification.", "title": "Usage"}, {"location": "cedarling/python/usage/", "tags": ["cedarling", "python", "usage"], "text": "Python usage # In this example, we will show an example Python script that calls the cedarling_python module and calls the authorize() function. Before beginning, ensure that you have completed the building steps and are currently in a virtual Python environment that has the cedarling_python module installed. You can confirm this with pip list . Run the script jans/jans-cedarling/bindings/cedarling_python/example.py from within the virtual environment. Output # (venv) $ python example.py Policy store location not provided, use 'CEDARLING_LOCAL_POLICY_STORE' environment variable Used default policy store path: example_files/policy-store.json {\"id\":\"0193414e-9672-786a-986c-57f48d41c4e4\",\"time\":1731967489,\"log_type\":\"System\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"configuration parsed successfully\"} {\"id\":\"0193414e-9672-786a-986c-57f5379086c3\",\"time\":1731967489,\"log_type\":\"System\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"Cedarling Authz initialized successfully\",\"application_id\":\"TestApp\"} {\"id\":\"0193414e-9676-7d8a-b55b-3f0097355851\",\"time\":1731967489,\"log_type\":\"Decision\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"Result of authorize.\",\"application_id\":\"TestApp\",\"action\":\"Jans::Action::\\\"Read\\\"\",\"resource\":\"Jans::Application::\\\"some_id\\\"\",\"context\":{\"user_agent\":\"Linux\",\"operating_system\":\"Linux\",\"network_type\":\"Local\",\"network\":\"127.0.0.1\",\"geolocation\":[\"America\"],\"fraud_indicators\":[\"Allowed\"],\"device_health\":[\"Healthy\"],\"current_time\":1731967489},\"person_principal\":\"Jans::User::\\\"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\\\"\",\"person_diagnostics\":{\"reason\":[\"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\"],\"errors\":[]},\"person_decision\":\"ALLOW\",\"workload_principal\":\"Jans::Workload::\\\"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\\\"\",\"workload_diagnostics\":{\"reason\":[\"444da5d85403f35ea76519ed1a18a33989f855bf1cf8\"],\"errors\":[]},\"workload_decision\":\"ALLOW\",\"authorized\":true} Result of workload authorization: ALLOW Policy ID used: 444da5d85403f35ea76519ed1a18a33989f855bf1cf8 Errors during authorization: 0 Result of person authorization: ALLOW Policy ID used: 840da5d85403f35ea76519ed1a18a33989f855bf1cf8 Errors during authorization: 0 Explanation # Cedarling creates principal entities from the access, ID and userinfo tokens. The action, resource and context entities are declared in code. These four entities together form the PARC format that cedarling evaluates against policies provided in the policy store. The principal entities can be either User, Workload or Role. After forming the entities, cedarling evaluates them against the policies provided in the policy store. If entity is explicitly permitted by a policy, the result of the evaluation is ALLOW , otherwise it is DENY . In this case there are two policies in the store, one for User entities and one for Workload entities: @444da5d85403f35ea76519ed1a18a33989f855bf1cf8 permit( principal is Jans::Workload, action in [Jans::Action::\"Read\"], resource is Jans::Application )when{ resource.name == \"Some Application\" }; @840da5d85403f35ea76519ed1a18a33989f855bf1cf8 permit( principal is Jans::User, action in [Jans::Action::\"Read\"], resource is Jans::Application )when{ resource.name == \"Some Application\" }; These two policies say that a Principal entity (User or Workload) is allowed to execute a Read action on an Application resource when the resource is named \"Some Application\". As there are no policies for Role entities, the result of the evaluation for the Role entity is DENY . In the script, the action, resource and context entities are used to create the request and execute the authorize() call: action = 'Jans::Action::\"Read\"' resource = ResourceData . from_dict ({ \"type\" : \"Jans::Application\" , \"id\" : \"some_id\" , \"app_id\" : \"application_id\" , \"name\" : \"Some Application\" , \"url\" : { \"host\" : \"jans.test\" , \"path\" : \"/protected-endpoint\" , \"protocol\" : \"http\" } }) context = { \"current_time\" : int ( time . time ()), \"device_health\" : [ \"Healthy\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"geolocation\" : [ \"America\" ], \"network\" : \"127.0.0.1\" , \"network_type\" : \"Local\" , \"operating_system\" : \"Linux\" , \"user_agent\" : \"Linux\" } request = Request ( access_token , id_token , userinfo_token , action = action , resource = resource , context = context ) authorize_result = instance . authorize ( request ) assert authorize_result . is_allowed () Cedarling will return is_allowed() as True only if both the User and Workload entity evaluations are ALLOW . Exposed functions # The pyo3 binding for cedarling exposes a number of cedarling functions for you to use. The documentation on this can be found here .", "title": "How to use"}, {"location": "cedarling/python/usage/#python-usage", "text": "In this example, we will show an example Python script that calls the cedarling_python module and calls the authorize() function. Before beginning, ensure that you have completed the building steps and are currently in a virtual Python environment that has the cedarling_python module installed. You can confirm this with pip list . Run the script jans/jans-cedarling/bindings/cedarling_python/example.py from within the virtual environment.", "title": "Python usage"}, {"location": "cedarling/python/usage/#output", "text": "(venv) $ python example.py Policy store location not provided, use 'CEDARLING_LOCAL_POLICY_STORE' environment variable Used default policy store path: example_files/policy-store.json {\"id\":\"0193414e-9672-786a-986c-57f48d41c4e4\",\"time\":1731967489,\"log_type\":\"System\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"configuration parsed successfully\"} {\"id\":\"0193414e-9672-786a-986c-57f5379086c3\",\"time\":1731967489,\"log_type\":\"System\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"Cedarling Authz initialized successfully\",\"application_id\":\"TestApp\"} {\"id\":\"0193414e-9676-7d8a-b55b-3f0097355851\",\"time\":1731967489,\"log_type\":\"Decision\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"Result of authorize.\",\"application_id\":\"TestApp\",\"action\":\"Jans::Action::\\\"Read\\\"\",\"resource\":\"Jans::Application::\\\"some_id\\\"\",\"context\":{\"user_agent\":\"Linux\",\"operating_system\":\"Linux\",\"network_type\":\"Local\",\"network\":\"127.0.0.1\",\"geolocation\":[\"America\"],\"fraud_indicators\":[\"Allowed\"],\"device_health\":[\"Healthy\"],\"current_time\":1731967489},\"person_principal\":\"Jans::User::\\\"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\\\"\",\"person_diagnostics\":{\"reason\":[\"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\"],\"errors\":[]},\"person_decision\":\"ALLOW\",\"workload_principal\":\"Jans::Workload::\\\"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\\\"\",\"workload_diagnostics\":{\"reason\":[\"444da5d85403f35ea76519ed1a18a33989f855bf1cf8\"],\"errors\":[]},\"workload_decision\":\"ALLOW\",\"authorized\":true} Result of workload authorization: ALLOW Policy ID used: 444da5d85403f35ea76519ed1a18a33989f855bf1cf8 Errors during authorization: 0 Result of person authorization: ALLOW Policy ID used: 840da5d85403f35ea76519ed1a18a33989f855bf1cf8 Errors during authorization: 0", "title": "Output"}, {"location": "cedarling/python/usage/#explanation", "text": "Cedarling creates principal entities from the access, ID and userinfo tokens. The action, resource and context entities are declared in code. These four entities together form the PARC format that cedarling evaluates against policies provided in the policy store. The principal entities can be either User, Workload or Role. After forming the entities, cedarling evaluates them against the policies provided in the policy store. If entity is explicitly permitted by a policy, the result of the evaluation is ALLOW , otherwise it is DENY . In this case there are two policies in the store, one for User entities and one for Workload entities: @444da5d85403f35ea76519ed1a18a33989f855bf1cf8 permit( principal is Jans::Workload, action in [Jans::Action::\"Read\"], resource is Jans::Application )when{ resource.name == \"Some Application\" }; @840da5d85403f35ea76519ed1a18a33989f855bf1cf8 permit( principal is Jans::User, action in [Jans::Action::\"Read\"], resource is Jans::Application )when{ resource.name == \"Some Application\" }; These two policies say that a Principal entity (User or Workload) is allowed to execute a Read action on an Application resource when the resource is named \"Some Application\". As there are no policies for Role entities, the result of the evaluation for the Role entity is DENY . In the script, the action, resource and context entities are used to create the request and execute the authorize() call: action = 'Jans::Action::\"Read\"' resource = ResourceData . from_dict ({ \"type\" : \"Jans::Application\" , \"id\" : \"some_id\" , \"app_id\" : \"application_id\" , \"name\" : \"Some Application\" , \"url\" : { \"host\" : \"jans.test\" , \"path\" : \"/protected-endpoint\" , \"protocol\" : \"http\" } }) context = { \"current_time\" : int ( time . time ()), \"device_health\" : [ \"Healthy\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"geolocation\" : [ \"America\" ], \"network\" : \"127.0.0.1\" , \"network_type\" : \"Local\" , \"operating_system\" : \"Linux\" , \"user_agent\" : \"Linux\" } request = Request ( access_token , id_token , userinfo_token , action = action , resource = resource , context = context ) authorize_result = instance . authorize ( request ) assert authorize_result . is_allowed () Cedarling will return is_allowed() as True only if both the User and Workload entity evaluations are ALLOW .", "title": "Explanation"}, {"location": "cedarling/python/usage/#exposed-functions", "text": "The pyo3 binding for cedarling exposes a number of cedarling functions for you to use. The documentation on this can be found here .", "title": "Exposed functions"}, {"location": "contribute/developer-faq/", "tags": ["developer", "faq"], "text": "Developer FAQs # How to enable debug logs for jans-cli and TUI configuration tools # By default, logging is not enabled for CLI or TUI tools on Janssen Server. Follow the steps below to enable and configure logging for CLI and TUI tools: Log in as root user open config file for editing ~/.config/jans-cli.ini Update value for debug to true and add new entry for log_dir key with value pointing to directory where logs need to be generated. e.g debug = true log_dir = /opt/jans Close currently open TUI session if any and open a new one Logs should get available at location configured in log_dir in files cli_debug.log and dev-tui.log How to get certificate from Let's encrypt # Let's Encrypt is a CA that provides free CA certificates. You can use these certificates to enable HTTPS communication with Janssen Server. Refer to this guide from Let's Encrypt to know more. We have compiled a set of commands for different OS platforms to help you as a quick reference to generate Let's Encrypt CA certificates. Suse # sudo zypper -n install certbot sudo certbot certonly --webroot -w /srv/www/htdocs -d FQDN Ubuntu # sudo apt update && sudo apt install certbot python3-certbot-apache sudo certbot --apache -d FQDN To check certbot status sudo systemctl status certbot.timer To renew certificate run sudo certbot renew --dry-run RHEL # sudo yum install certbot python3-certbot-apache sudo certbot certonly --apache How to install Janssen Server OpenBanking for testing? # Note Use this installation for testing only Good understanding of Janssen Server installation process in general is a prerequisite. Here we are just highlighting steps without a lot of details. Visit installation documentation for complete understanding. This installation uses Gluu Testing certificate. Download Installer # wget https://raw.githubusercontent.com/JanssenProject/jans/nightly/jans-linux-setup/jans_setup/install.py -O install.py Execute Installer # python3 install.py --profile=openbanking --args=\"-ob-key-fn=/opt/jans/jans-setup/openbanking/static/ob-gluu-test.key -static-kid=ob-gluu-test -jwks-uri=https://ox.gluu.org/icrby8xcvbcv/ob/ob-gluu-test.jwks --disable-ob-auth-script -ob-alias=ob-gluu-test\" Please enter defaults for the following questions (press just enter key), it will download certificate from jwksUri Use external key? [Y|n] : y Openbanking Key File [/opt/jans/jans-setup/openbanking/static/ob-gluu-test.key] : Openbanking Certificate File [/root/obsigning.pem] : Openbanking Key Alias [ob-gluu-test] : Configure Certificate # jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key Test # This test uses Gluu Testing certificate. device authentication # After installation we have to complete device authentication to use openbanking. Testing using IM mode # launch jans-cli using below command jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key further testing is same as jans server Testing using command line mode # we can run below command at command line. for ex: jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key \u2013operation-id get-oauth-openid-clients same way we can run other commands. rest is same for jans and openbanking", "title": "Developer FAQ"}, {"location": "contribute/developer-faq/#developer-faqs", "text": "", "title": "Developer FAQs"}, {"location": "contribute/developer-faq/#how-to-enable-debug-logs-for-jans-cli-and-tui-configuration-tools", "text": "By default, logging is not enabled for CLI or TUI tools on Janssen Server. Follow the steps below to enable and configure logging for CLI and TUI tools: Log in as root user open config file for editing ~/.config/jans-cli.ini Update value for debug to true and add new entry for log_dir key with value pointing to directory where logs need to be generated. e.g debug = true log_dir = /opt/jans Close currently open TUI session if any and open a new one Logs should get available at location configured in log_dir in files cli_debug.log and dev-tui.log", "title": "How to enable debug logs for jans-cli and TUI configuration tools"}, {"location": "contribute/developer-faq/#how-to-get-certificate-from-lets-encrypt", "text": "Let's Encrypt is a CA that provides free CA certificates. You can use these certificates to enable HTTPS communication with Janssen Server. Refer to this guide from Let's Encrypt to know more. We have compiled a set of commands for different OS platforms to help you as a quick reference to generate Let's Encrypt CA certificates.", "title": "How to get certificate from Let's encrypt"}, {"location": "contribute/developer-faq/#suse", "text": "sudo zypper -n install certbot sudo certbot certonly --webroot -w /srv/www/htdocs -d FQDN", "title": "Suse"}, {"location": "contribute/developer-faq/#ubuntu", "text": "sudo apt update && sudo apt install certbot python3-certbot-apache sudo certbot --apache -d FQDN To check certbot status sudo systemctl status certbot.timer To renew certificate run sudo certbot renew --dry-run", "title": "Ubuntu"}, {"location": "contribute/developer-faq/#rhel", "text": "sudo yum install certbot python3-certbot-apache sudo certbot certonly --apache", "title": "RHEL"}, {"location": "contribute/developer-faq/#how-to-install-janssen-server-openbanking-for-testing", "text": "Note Use this installation for testing only Good understanding of Janssen Server installation process in general is a prerequisite. Here we are just highlighting steps without a lot of details. Visit installation documentation for complete understanding. This installation uses Gluu Testing certificate.", "title": "How to install Janssen Server OpenBanking for testing?"}, {"location": "contribute/developer-faq/#download-installer", "text": "wget https://raw.githubusercontent.com/JanssenProject/jans/nightly/jans-linux-setup/jans_setup/install.py -O install.py", "title": "Download Installer"}, {"location": "contribute/developer-faq/#execute-installer", "text": "python3 install.py --profile=openbanking --args=\"-ob-key-fn=/opt/jans/jans-setup/openbanking/static/ob-gluu-test.key -static-kid=ob-gluu-test -jwks-uri=https://ox.gluu.org/icrby8xcvbcv/ob/ob-gluu-test.jwks --disable-ob-auth-script -ob-alias=ob-gluu-test\" Please enter defaults for the following questions (press just enter key), it will download certificate from jwksUri Use external key? [Y|n] : y Openbanking Key File [/opt/jans/jans-setup/openbanking/static/ob-gluu-test.key] : Openbanking Certificate File [/root/obsigning.pem] : Openbanking Key Alias [ob-gluu-test] :", "title": "Execute Installer"}, {"location": "contribute/developer-faq/#configure-certificate", "text": "jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key", "title": "Configure Certificate"}, {"location": "contribute/developer-faq/#test", "text": "This test uses Gluu Testing certificate.", "title": "Test"}, {"location": "contribute/developer-faq/#device-authentication", "text": "After installation we have to complete device authentication to use openbanking.", "title": "device authentication"}, {"location": "contribute/developer-faq/#testing-using-im-mode", "text": "launch jans-cli using below command jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key further testing is same as jans server", "title": "Testing using IM mode"}, {"location": "contribute/developer-faq/#testing-using-command-line-mode", "text": "we can run below command at command line. for ex: jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key \u2013operation-id get-oauth-openid-clients same way we can run other commands. rest is same for jans and openbanking", "title": "Testing using command line mode"}, {"location": "contribute/development/", "text": "Developing for Janssen Project # Remote Debugging # Janssen Server modules run as Java processes. Hence, like any other Java process the JVM running the module can be configured to open a debug port where a remote debugger can be attached. The steps below will show how to configure auth-server module for remote debugging. Pass the command-line options to the JVM On the Janssen Server host, open the service config file /etc/default/jans-auth and add the following JVM parameters to as JAVA_OPTIONS -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=6001 This will open the port 6001 for the remote debugger. Any other port can also be used based on availability. Restart jans-auth services systemctl restart jans-auth.service Check if the port is open and accessible from within the Janssen Server host Use the jdb tool from JDK to test if the JVM port has been opened ./<path-to-JDK>/bin/jdb -attach 6001 if the port is open, it'll give you output like the below: Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... > press ctrl+c to come out of it. Ensure that the port is accessible from outside the host VM as well and firewalls are configured accordingly Connect to the remote port on the Janssen Server host from the developer workstation. Use any IDE (Intellij, Eclipse, etc.) to create and run a remote debugging profile. Provide IP and debug port of the Janssen Server host. For IntelliJIdea, create a debug configuration as below: Run Integration Tests with a Janssen Server VM # In this guide, we will look at steps to run the Janssen integration test suite against an installed Janssen Server. Component Setup # Instructions in this guide can be used if Janssen Server is installed on a VM. Developers can use a virtualization software (like VMWare) or use LxD containers to create VM on developer workstation or use a remote cloud VM. OS platform for Developer Workstation Steps in this guide are applicable to any OS platform a Developer workstation may have. Example commands given in this guide are for Ubuntu Linux based workstation. Install Janssen Server # Install the Janssen server using one of the methods described in the VM installation guide. Note the points below when following installation instructions. Make a note of the host name that you assign to the Janssen server during the installation. For this guide, the Janssen hostname would be janssen.op.io Choose to install with test data load. This can be achieved by using the -t switch when invoking the setup script from installation instructions. Use the VM installation guide for the complete set of instructions. Once the installation is complete, check if the .well-known end-points of the Janssen server from the browser. A successful response will ascertain that the The Janssen server running inside the local VM is healthy and also accessible from the developer's machine. Note Based on developer setup it may be necessary to add appropriate IP-HOST mapping to the developer workstation. For instance, on a Linux-based developer workstation, this means adding a mapping to /etc/hosts file. Make sure that VM's IP is mapped to a FQDN like janssen.op.io . Refering to VM with localhost or just IP will not work. URI for OpenID configuration .well-known endpoint: https://janssen.op.io/jans-auth/.well-known/openid-configuration The response received should be JSON formatted Janssen configuration details, similar to those below. { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://janssen.op.io\", \"userinfo_encryption_enc_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"authorization_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_generation_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/id\", \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"user_name\", \"formatted\", \"phone_mobile_number\", \"preferred_username\", \"inum\", \"locale\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"scope_to_claims_mapping\" : [ { \"user_name\" : [ \"user_name\" ] }, { \"https://jans.io/scim/users.write\" : [ ] }, { \"https://jans.io/scim/groups.read\" : [ ] }, { \"https://jans.io/scim/all-resources.search\" : [ ] }, { \"https://jans.io/scim/fido.write\" : [ ] }, { \"https://jans.io/scim/groups.write\" : [ ] }, { \"https://jans.io/scim/fido2.read\" : [ ] }, { \"https://jans.io/scim/fido.read\" : [ ] }, { \"https://jans.io/scim/fido2.write\" : [ ] Setup The Certificates # To run the tests against the installed Janssen Server, the workstation JRE needs to have the appropriate certificate installed. Update cacerts using the steps below: extract certificate for Janssen server with name janssen.op.io On Developer Workstation openssl s_client -connect test.local.jans.io:443 2 > & 1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/httpd.crt this command takes a few seconds to return. Update cacerts of your JRE which is being used by the code workspace. For example, /usr/lib/jvm/java-11-amazon-corretto . When running the command below, it will prompt for cert store password. Provide the correct password. The default password is changeit . keytool -import -alias janssen.op.io -keystore /usr/lib/jvm/java-11-amazon-corretto/lib/security/cacerts -file /tmp/httpd.crt Configure developer workspace # Now that we have Janssen Server running in a VM and it is accessible from the developer workstation as well, we will create and configure the code base on the developer workspace to run integration tests. Get Janssen server code from Janssen GitHub repository . Note the path to this location, we will refer to it as source-base . Janssen Server is composed of multiple modules. For example source-base/jans-auth-server , source-base/jans-link etc. Each module has its own set of tests. Below are the instructions for configuring each module for tests. What is a Profile directory? To run integration tests, the developer workspace needs to know details about he Janssen Server agaist which the tests are to be run. Janssen Server workspace holds this information in source-base/module/sub-module/profiles directory. The profiles directory can contain one or more sub-directories, each representing a profile(i.e a target Janssen Server). These profile directories are used to hold files that contain important information required to run tests. Developers can create one or more profiles and use them to run tests against different Janssen Servers. This guide uses Janssen Server hostname, janssen.op.io , as profile name. Configuring the jans-auth-server module # Configuring jans-auth-server module involves setting up profiles for client , server and agama sub-modules. Follow the steps below to configure the profile for the client and server sub-modules. Move to the module directory cd source-base/jans-auth-server As a precautionary measure, let's first remove any old profile artifacts from the jans-auth-server workspace. rm -rf ./jans-auth rm -rf ./client/profiles/janssen.op.io rm -rf ./server/profiles/janssen.op.io rm -rf ./agama/engine/profiles/janssen.op.io Since Janssen Server has been installed with test data, the installer also created the profile files required to run the test. These files are kept on the VM under /opt/jans/jans-setup/output/test/jans-auth directory. Copy over jans-auth directory from Janssen Server VM to source-base/jans-auth-server on developer workstation. Create new profile directories. mkdir -p ./client/profiles/janssen.op.io mkdir -p ./server/profiles/janssen.op.io mkdir -p ./agama/engine/profiles/janssen.op.io Copy the contents of jans-auth directory into the respective sub-module's janssen.op.io profile directory cp ./jans-auth/client/* ./client/profiles/janssen.op.io cp ./jans-auth/server/* ./server/profiles/janssen.op.io cp ./jans-auth/config-agama-test.properties ./agama/engine/profiles/janssen.op.io/config-agama-test.properties Copy keystore file profiles/default/client_keystore.p12 from default profile directory to the janssen.op.io profile directory cp -f ./client/profiles/default/client_keystore.p12 ./client/profiles/janssen.op.io cp -f ./server/profiles/default/client_keystore.p12 ./server/profiles/janssen.op.io Running The Tests # Each module in Janssen Server has its tests that have to be executed separately. For example, to run integration tests for jans-auth-server module, run the following maven command at the directory level: mvn -Dcfg=janssen.op.io test Configuring the jans-core module # This module does not require a profile setup. It can be built with below maven command. mvn clean compile install Configuring the jans-link module # This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install Configuring the jans-orm module # This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install Configuring the agama module # This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install Configuring the SCIM module # This module does not require a profile setup. It can be built with the below maven command. Profile setup for client and server modules # Many Janssen Server modules and sub-modules use test configuration stored in a directory named profile . The profile directory contains files that hold important information required to run tests. Developers can create one or more profiles and use them to run tests against different Janssen Servers. Since Janssen Server has been installed with test data, the installer also created the profile files required to run the test. For SCIM/client module, these files are kept on the VM under /opt/jans/jans-setup/output/test/scim-client directory. Copy over this directory to any location on the developer workstation. Follow the steps below to configure the profile for the client module. The same steps should be followed for setting up a profile for the server module. Under jans-scim/client/profiles directory, create a new directory and name it janssen.op.io Copy the contents of scim-client/client directory into the newly created janssen.op.io directory Post this, remove the scim-client directory. Now as the profile is setup, to build the jans-scim module and run tests, use the command below: mvn -Dcfg=janssen.op.io test Setup Janssen Schema with Test data # Useful Tools # While working with Janssen Server, either as developer or administrator, following tools can come in handy. jsonbin.io jwt.io oidcdebugger.com keytool.online", "title": "Development"}, {"location": "contribute/development/#developing-for-janssen-project", "text": "", "title": "Developing for Janssen Project"}, {"location": "contribute/development/#remote-debugging", "text": "Janssen Server modules run as Java processes. Hence, like any other Java process the JVM running the module can be configured to open a debug port where a remote debugger can be attached. The steps below will show how to configure auth-server module for remote debugging. Pass the command-line options to the JVM On the Janssen Server host, open the service config file /etc/default/jans-auth and add the following JVM parameters to as JAVA_OPTIONS -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=6001 This will open the port 6001 for the remote debugger. Any other port can also be used based on availability. Restart jans-auth services systemctl restart jans-auth.service Check if the port is open and accessible from within the Janssen Server host Use the jdb tool from JDK to test if the JVM port has been opened ./<path-to-JDK>/bin/jdb -attach 6001 if the port is open, it'll give you output like the below: Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... > press ctrl+c to come out of it. Ensure that the port is accessible from outside the host VM as well and firewalls are configured accordingly Connect to the remote port on the Janssen Server host from the developer workstation. Use any IDE (Intellij, Eclipse, etc.) to create and run a remote debugging profile. Provide IP and debug port of the Janssen Server host. For IntelliJIdea, create a debug configuration as below:", "title": "Remote Debugging"}, {"location": "contribute/development/#run-integration-tests-with-a-janssen-server-vm", "text": "In this guide, we will look at steps to run the Janssen integration test suite against an installed Janssen Server.", "title": "Run Integration Tests with a Janssen Server VM"}, {"location": "contribute/development/#component-setup", "text": "Instructions in this guide can be used if Janssen Server is installed on a VM. Developers can use a virtualization software (like VMWare) or use LxD containers to create VM on developer workstation or use a remote cloud VM. OS platform for Developer Workstation Steps in this guide are applicable to any OS platform a Developer workstation may have. Example commands given in this guide are for Ubuntu Linux based workstation.", "title": "Component Setup"}, {"location": "contribute/development/#install-janssen-server", "text": "Install the Janssen server using one of the methods described in the VM installation guide. Note the points below when following installation instructions. Make a note of the host name that you assign to the Janssen server during the installation. For this guide, the Janssen hostname would be janssen.op.io Choose to install with test data load. This can be achieved by using the -t switch when invoking the setup script from installation instructions. Use the VM installation guide for the complete set of instructions. Once the installation is complete, check if the .well-known end-points of the Janssen server from the browser. A successful response will ascertain that the The Janssen server running inside the local VM is healthy and also accessible from the developer's machine. Note Based on developer setup it may be necessary to add appropriate IP-HOST mapping to the developer workstation. For instance, on a Linux-based developer workstation, this means adding a mapping to /etc/hosts file. Make sure that VM's IP is mapped to a FQDN like janssen.op.io . Refering to VM with localhost or just IP will not work. URI for OpenID configuration .well-known endpoint: https://janssen.op.io/jans-auth/.well-known/openid-configuration The response received should be JSON formatted Janssen configuration details, similar to those below. { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://janssen.op.io\", \"userinfo_encryption_enc_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"authorization_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_generation_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/id\", \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"user_name\", \"formatted\", \"phone_mobile_number\", \"preferred_username\", \"inum\", \"locale\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"scope_to_claims_mapping\" : [ { \"user_name\" : [ \"user_name\" ] }, { \"https://jans.io/scim/users.write\" : [ ] }, { \"https://jans.io/scim/groups.read\" : [ ] }, { \"https://jans.io/scim/all-resources.search\" : [ ] }, { \"https://jans.io/scim/fido.write\" : [ ] }, { \"https://jans.io/scim/groups.write\" : [ ] }, { \"https://jans.io/scim/fido2.read\" : [ ] }, { \"https://jans.io/scim/fido.read\" : [ ] }, { \"https://jans.io/scim/fido2.write\" : [ ]", "title": "Install Janssen Server"}, {"location": "contribute/development/#setup-the-certificates", "text": "To run the tests against the installed Janssen Server, the workstation JRE needs to have the appropriate certificate installed. Update cacerts using the steps below: extract certificate for Janssen server with name janssen.op.io On Developer Workstation openssl s_client -connect test.local.jans.io:443 2 > & 1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/httpd.crt this command takes a few seconds to return. Update cacerts of your JRE which is being used by the code workspace. For example, /usr/lib/jvm/java-11-amazon-corretto . When running the command below, it will prompt for cert store password. Provide the correct password. The default password is changeit . keytool -import -alias janssen.op.io -keystore /usr/lib/jvm/java-11-amazon-corretto/lib/security/cacerts -file /tmp/httpd.crt", "title": "Setup The Certificates"}, {"location": "contribute/development/#configure-developer-workspace", "text": "Now that we have Janssen Server running in a VM and it is accessible from the developer workstation as well, we will create and configure the code base on the developer workspace to run integration tests. Get Janssen server code from Janssen GitHub repository . Note the path to this location, we will refer to it as source-base . Janssen Server is composed of multiple modules. For example source-base/jans-auth-server , source-base/jans-link etc. Each module has its own set of tests. Below are the instructions for configuring each module for tests. What is a Profile directory? To run integration tests, the developer workspace needs to know details about he Janssen Server agaist which the tests are to be run. Janssen Server workspace holds this information in source-base/module/sub-module/profiles directory. The profiles directory can contain one or more sub-directories, each representing a profile(i.e a target Janssen Server). These profile directories are used to hold files that contain important information required to run tests. Developers can create one or more profiles and use them to run tests against different Janssen Servers. This guide uses Janssen Server hostname, janssen.op.io , as profile name.", "title": "Configure developer workspace"}, {"location": "contribute/development/#configuring-the-jans-auth-server-module", "text": "Configuring jans-auth-server module involves setting up profiles for client , server and agama sub-modules. Follow the steps below to configure the profile for the client and server sub-modules. Move to the module directory cd source-base/jans-auth-server As a precautionary measure, let's first remove any old profile artifacts from the jans-auth-server workspace. rm -rf ./jans-auth rm -rf ./client/profiles/janssen.op.io rm -rf ./server/profiles/janssen.op.io rm -rf ./agama/engine/profiles/janssen.op.io Since Janssen Server has been installed with test data, the installer also created the profile files required to run the test. These files are kept on the VM under /opt/jans/jans-setup/output/test/jans-auth directory. Copy over jans-auth directory from Janssen Server VM to source-base/jans-auth-server on developer workstation. Create new profile directories. mkdir -p ./client/profiles/janssen.op.io mkdir -p ./server/profiles/janssen.op.io mkdir -p ./agama/engine/profiles/janssen.op.io Copy the contents of jans-auth directory into the respective sub-module's janssen.op.io profile directory cp ./jans-auth/client/* ./client/profiles/janssen.op.io cp ./jans-auth/server/* ./server/profiles/janssen.op.io cp ./jans-auth/config-agama-test.properties ./agama/engine/profiles/janssen.op.io/config-agama-test.properties Copy keystore file profiles/default/client_keystore.p12 from default profile directory to the janssen.op.io profile directory cp -f ./client/profiles/default/client_keystore.p12 ./client/profiles/janssen.op.io cp -f ./server/profiles/default/client_keystore.p12 ./server/profiles/janssen.op.io", "title": "Configuring the jans-auth-server module"}, {"location": "contribute/development/#running-the-tests", "text": "Each module in Janssen Server has its tests that have to be executed separately. For example, to run integration tests for jans-auth-server module, run the following maven command at the directory level: mvn -Dcfg=janssen.op.io test", "title": "Running The Tests"}, {"location": "contribute/development/#configuring-the-jans-core-module", "text": "This module does not require a profile setup. It can be built with below maven command. mvn clean compile install", "title": "Configuring the jans-core module"}, {"location": "contribute/development/#configuring-the-jans-link-module", "text": "This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install", "title": "Configuring the jans-link module"}, {"location": "contribute/development/#configuring-the-jans-orm-module", "text": "This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install", "title": "Configuring the jans-orm module"}, {"location": "contribute/development/#configuring-the-agama-module", "text": "This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install", "title": "Configuring the agama module"}, {"location": "contribute/development/#configuring-the-scim-module", "text": "This module does not require a profile setup. It can be built with the below maven command.", "title": "Configuring the SCIM module"}, {"location": "contribute/development/#profile-setup-for-client-and-server-modules", "text": "Many Janssen Server modules and sub-modules use test configuration stored in a directory named profile . The profile directory contains files that hold important information required to run tests. Developers can create one or more profiles and use them to run tests against different Janssen Servers. Since Janssen Server has been installed with test data, the installer also created the profile files required to run the test. For SCIM/client module, these files are kept on the VM under /opt/jans/jans-setup/output/test/scim-client directory. Copy over this directory to any location on the developer workstation. Follow the steps below to configure the profile for the client module. The same steps should be followed for setting up a profile for the server module. Under jans-scim/client/profiles directory, create a new directory and name it janssen.op.io Copy the contents of scim-client/client directory into the newly created janssen.op.io directory Post this, remove the scim-client directory. Now as the profile is setup, to build the jans-scim module and run tests, use the command below: mvn -Dcfg=janssen.op.io test", "title": "Profile setup for client and server modules"}, {"location": "contribute/development/#setup-janssen-schema-with-test-data", "text": "", "title": "Setup Janssen Schema with Test data"}, {"location": "contribute/development/#useful-tools", "text": "While working with Janssen Server, either as developer or administrator, following tools can come in handy. jsonbin.io jwt.io oidcdebugger.com keytool.online", "title": "Useful Tools"}, {"location": "contribute/testing/", "tags": ["administration", "contribute", "Testing", "Quality Assurance"], "text": "Test And Quality Assurance For Janssen Project # The Janssen Project is a large, complex project with tons of inter-dependency. If we aren't test-driven, anarchy will ensue. Every line of code at Janssen Project goes through various tests at different stages of development. Most of these tests are automated and executed as part of our CI-CD pipeline, while others are executed manually. Unit testing # Do not submit any code without a corresponding unit test. Also, any bug fixes should increment unit test coverage. All unit tests are executed with any subsequent Jenkins build. Component testing # Component testing uses real world use cases to exercise a portion of the software, using typical data inputs. Developers should document component stories and submit them to the component test library for the respective repository. A tester should be able to run component tests manually. Component tests should run automatically with each Jenkins build. The OpenID Foundation certification tests supplement the component testing library, and should be run for each major release of the software for which they are available. Performance testing # Performance tests are critical to optimization of the persistence and caching implementation. All major releases of the software should be tested for performance with all supported database and cache configurations using the Cloud Native distribution. The VM distribution will not be performance tested, as the main goal for this distribution is development and small deployments. The JMeter test tool should be used to generate the load. These tests are published so community members can run their own bench-marking analysis. HA Tests # HA tests should be run against the Cloud Native distribution, which by design is active-active with no single point of failure. The HA testing should simulate taking down various pieces of infrastructure, to see if authentications can still proceed. Also, what happens to transactions that were in progress during the crash? Penetration tests # Penetration testing is highly deployment specific. Depending on different implementations of the Janssen Project software, you may achieve different levels of risk mitigation. Thus it is important that organizations that operate their own IAM platform based on Janssen perform their own penetration testing. Dependency Vulnerabilities # Dependency vulnerabilities are monitored by Gihub. In addition we plan to use the Linux Foundation Community Bridge vulnerability detection platform. Testing Documentation Changes Locally # While contributing documentation to official Janssen Project documentation it is important to make sure that documents meet style guidelines and have been proofread to remove any typographical or grammatical errors. Janssen Project uses Material for MkDocs to create the documenation site. Before new content is pushed to the repository on GitHub, it should be tested locally by the author. Author can do this by deploying Material for MkDocs locally. High-level steps involve: Install Material for MkDocs Install required plugins Preview as you write Open Banking # We are working on developing this content under issue 2548 . If you\u2019d like to contribute the content, get started with the Contribution Guide How to test OpenBanking? # This test uses a Gluu Testing Certificate. device authentication # After installation, we have to complete device authentication to use OpenBanking. Testing using commnd line mode # We can run the below command on the command line. For example: jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key \u2013operation-id get-oauth-openid-clients in the same way we can run other commands. Rest of the testing is same for jans and openbanking. Release Quality Assurance # Once all the code changes for a particular release have been committed, we perform a set of tests and go through a list of checkpoints to make sure release candidate (RC) build is healthy and functioning well. Pre-release QA checklist # As part of pre-release QA check, we run a set of manual sanity checks on test environments with various deployment configurations. Test Environments # # OS Platform Persistance Type Deployment Type (VM/CN) Test 2 SUSE 15 Mysql VM installation and sanity testing 3 SUSE 15 Pgsql VM installation and sanity testing 5 RHEL 8 Mysql VM installation and sanity testing 6 RHEL 8 Pgsql VM installation and sanity testing 8 Ubuntu20 Mysql VM installation and sanity testing 9 Ubuntu20 Pgsql VM installation and sanity testing 11 Ubuntu22 Mysql VM installation and sanity testing 12 Ubuntu22 Pgsql VM installation and sanity testing Sanity checks # Review functioning of .well-known endpoints for OpenId, Fido, UMA, SCIM modules Test device authentication flow using TUI Test password authentication flow using Janssen Server Tent Test Agama project deployment and functioning Post-release QA checklist # # QA Checks 1 Package installation verification on all OS Platforms as in pre-release tests", "title": "Testing"}, {"location": "contribute/testing/#test-and-quality-assurance-for-janssen-project", "text": "The Janssen Project is a large, complex project with tons of inter-dependency. If we aren't test-driven, anarchy will ensue. Every line of code at Janssen Project goes through various tests at different stages of development. Most of these tests are automated and executed as part of our CI-CD pipeline, while others are executed manually.", "title": "Test And Quality Assurance For Janssen Project"}, {"location": "contribute/testing/#unit-testing", "text": "Do not submit any code without a corresponding unit test. Also, any bug fixes should increment unit test coverage. All unit tests are executed with any subsequent Jenkins build.", "title": "Unit testing"}, {"location": "contribute/testing/#component-testing", "text": "Component testing uses real world use cases to exercise a portion of the software, using typical data inputs. Developers should document component stories and submit them to the component test library for the respective repository. A tester should be able to run component tests manually. Component tests should run automatically with each Jenkins build. The OpenID Foundation certification tests supplement the component testing library, and should be run for each major release of the software for which they are available.", "title": "Component testing"}, {"location": "contribute/testing/#performance-testing", "text": "Performance tests are critical to optimization of the persistence and caching implementation. All major releases of the software should be tested for performance with all supported database and cache configurations using the Cloud Native distribution. The VM distribution will not be performance tested, as the main goal for this distribution is development and small deployments. The JMeter test tool should be used to generate the load. These tests are published so community members can run their own bench-marking analysis.", "title": "Performance testing"}, {"location": "contribute/testing/#ha-tests", "text": "HA tests should be run against the Cloud Native distribution, which by design is active-active with no single point of failure. The HA testing should simulate taking down various pieces of infrastructure, to see if authentications can still proceed. Also, what happens to transactions that were in progress during the crash?", "title": "HA Tests"}, {"location": "contribute/testing/#penetration-tests", "text": "Penetration testing is highly deployment specific. Depending on different implementations of the Janssen Project software, you may achieve different levels of risk mitigation. Thus it is important that organizations that operate their own IAM platform based on Janssen perform their own penetration testing.", "title": "Penetration tests"}, {"location": "contribute/testing/#dependency-vulnerabilities", "text": "Dependency vulnerabilities are monitored by Gihub. In addition we plan to use the Linux Foundation Community Bridge vulnerability detection platform.", "title": "Dependency Vulnerabilities"}, {"location": "contribute/testing/#testing-documentation-changes-locally", "text": "While contributing documentation to official Janssen Project documentation it is important to make sure that documents meet style guidelines and have been proofread to remove any typographical or grammatical errors. Janssen Project uses Material for MkDocs to create the documenation site. Before new content is pushed to the repository on GitHub, it should be tested locally by the author. Author can do this by deploying Material for MkDocs locally. High-level steps involve: Install Material for MkDocs Install required plugins Preview as you write", "title": "Testing Documentation Changes Locally"}, {"location": "contribute/testing/#open-banking", "text": "We are working on developing this content under issue 2548 . If you\u2019d like to contribute the content, get started with the Contribution Guide", "title": "Open Banking"}, {"location": "contribute/testing/#how-to-test-openbanking", "text": "This test uses a Gluu Testing Certificate.", "title": "How to test OpenBanking?"}, {"location": "contribute/testing/#device-authentication", "text": "After installation, we have to complete device authentication to use OpenBanking.", "title": "device authentication"}, {"location": "contribute/testing/#testing-using-commnd-line-mode", "text": "We can run the below command on the command line. For example: jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key \u2013operation-id get-oauth-openid-clients in the same way we can run other commands. Rest of the testing is same for jans and openbanking.", "title": "Testing using commnd line mode"}, {"location": "contribute/testing/#release-quality-assurance", "text": "Once all the code changes for a particular release have been committed, we perform a set of tests and go through a list of checkpoints to make sure release candidate (RC) build is healthy and functioning well.", "title": "Release Quality Assurance"}, {"location": "contribute/testing/#pre-release-qa-checklist", "text": "As part of pre-release QA check, we run a set of manual sanity checks on test environments with various deployment configurations.", "title": "Pre-release QA checklist"}, {"location": "contribute/testing/#test-environments", "text": "# OS Platform Persistance Type Deployment Type (VM/CN) Test 2 SUSE 15 Mysql VM installation and sanity testing 3 SUSE 15 Pgsql VM installation and sanity testing 5 RHEL 8 Mysql VM installation and sanity testing 6 RHEL 8 Pgsql VM installation and sanity testing 8 Ubuntu20 Mysql VM installation and sanity testing 9 Ubuntu20 Pgsql VM installation and sanity testing 11 Ubuntu22 Mysql VM installation and sanity testing 12 Ubuntu22 Pgsql VM installation and sanity testing", "title": "Test Environments"}, {"location": "contribute/testing/#sanity-checks", "text": "Review functioning of .well-known endpoints for OpenId, Fido, UMA, SCIM modules Test device authentication flow using TUI Test password authentication flow using Janssen Server Tent Test Agama project deployment and functioning", "title": "Sanity checks"}, {"location": "contribute/testing/#post-release-qa-checklist", "text": "# QA Checks 1 Package installation verification on all OS Platforms as in pre-release tests", "title": "Post-release QA checklist"}, {"location": "contribute/ci-cd/release-process/", "tags": ["Release", "faq"], "text": "Release Process # The release process starts on scheduled times detailed in the milestones of the Janssen project. The release manager is responsible for coordinating the release process and ensuring that all steps are completed. The process is as follows: Release Planning : The release manager creates a release plan that normally includes the release date, the version number, and the main features that will be included in the release. The release plan is shared with the team for review and feedback. Feature Freeze : The release manager announces the feature freeze date. After this date, no new features will be added to the release. The team focuses on fixing bugs and improving the quality of the release. QA starts testing the release. Code Freeze : The release manager announces the code freeze date. After this date, no new code will be added to the release. The team focuses on fixing bugs and improving the quality of the release. QA team verifies testing the release. Release Candidate : The release manager creates a release candidate and shares it with the team for testing. The team tests the release candidate and reports any issues found. The release manager fixes the issues and creates a new release candidate. This process continues until the release candidate is stable. This is normally done via a PR process and release branch following the structure release-<version> . Release : The release manager creates the final release and shares it with the team. The team tests the final release and reports any issues found. The release manager fixes the issues and creates a new release. This process continues until the final release is stable. Release Notes : The release manager creates the release notes and shares them with the team. The release notes include the version number, the main features included in the release, and any known issues. The release notes are shared with the community. This process is automated and picked up through conventional commits developers submit. Release Announcement : The release manager announces the release to the community. The announcement includes the version number, the main features included in the release, and any known issues. The announcement is shared on the Janssen website, the Janssen blog, and social media. The release manager also sends an email to the Janssen mailing list. Post-Release : The release manager monitors the release and addresses any issues that arise. The team continues to work on the next release. Release Retrospective : The release manager conducts a retrospective to review the release process and identify areas for improvement. The team provides feedback on the release process. The release manager uses this feedback to improve the release process for future releases. Next Release Planning : The release manager starts planning the next release. The process starts again from step 1. A branch release-<version> is created for the next dev and snapshot release with a similar process from step 1 and is merged into main . Future plans # We are planning a full move to SemVer for all Janssen projects that will be scheduled bi-weekly. In this move, the Google release-please GitHub workflow will be activated to automatically release the projects according to the conventional commits submitted.", "title": "Release Process"}, {"location": "contribute/ci-cd/release-process/#release-process", "text": "The release process starts on scheduled times detailed in the milestones of the Janssen project. The release manager is responsible for coordinating the release process and ensuring that all steps are completed. The process is as follows: Release Planning : The release manager creates a release plan that normally includes the release date, the version number, and the main features that will be included in the release. The release plan is shared with the team for review and feedback. Feature Freeze : The release manager announces the feature freeze date. After this date, no new features will be added to the release. The team focuses on fixing bugs and improving the quality of the release. QA starts testing the release. Code Freeze : The release manager announces the code freeze date. After this date, no new code will be added to the release. The team focuses on fixing bugs and improving the quality of the release. QA team verifies testing the release. Release Candidate : The release manager creates a release candidate and shares it with the team for testing. The team tests the release candidate and reports any issues found. The release manager fixes the issues and creates a new release candidate. This process continues until the release candidate is stable. This is normally done via a PR process and release branch following the structure release-<version> . Release : The release manager creates the final release and shares it with the team. The team tests the final release and reports any issues found. The release manager fixes the issues and creates a new release. This process continues until the final release is stable. Release Notes : The release manager creates the release notes and shares them with the team. The release notes include the version number, the main features included in the release, and any known issues. The release notes are shared with the community. This process is automated and picked up through conventional commits developers submit. Release Announcement : The release manager announces the release to the community. The announcement includes the version number, the main features included in the release, and any known issues. The announcement is shared on the Janssen website, the Janssen blog, and social media. The release manager also sends an email to the Janssen mailing list. Post-Release : The release manager monitors the release and addresses any issues that arise. The team continues to work on the next release. Release Retrospective : The release manager conducts a retrospective to review the release process and identify areas for improvement. The team provides feedback on the release process. The release manager uses this feedback to improve the release process for future releases. Next Release Planning : The release manager starts planning the next release. The process starts again from step 1. A branch release-<version> is created for the next dev and snapshot release with a similar process from step 1 and is merged into main .", "title": "Release Process"}, {"location": "contribute/ci-cd/release-process/#future-plans", "text": "We are planning a full move to SemVer for all Janssen projects that will be scheduled bi-weekly. In this move, the Google release-please GitHub workflow will be activated to automatically release the projects according to the conventional commits submitted.", "title": "Future plans"}, {"location": "contribute/implementation-design/agama/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Agama"}, {"location": "contribute/implementation-design/agama/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/agama/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/agama/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "contribute/implementation-design/jans-auth-server/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "jans-auth-server"}, {"location": "contribute/implementation-design/jans-auth-server/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/jans-auth-server/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/jans-auth-server/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "contribute/implementation-design/jans-cli/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "jans-cli"}, {"location": "contribute/implementation-design/jans-cli/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/jans-cli/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/jans-cli/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "contribute/implementation-design/jans-config-api/", "tags": ["developer", "config-api"], "text": "Overview # Janssen Config API # Janssen(Jans) Config API is an application programming interface (API) gateway managing configuring of various Janssen modules. Diagram reference Jans Config API features: # Jans Config API uses REST endpoints to communicate. Jans Config API endpoint are OAuth 2.0 protected. More details here Jans Config API plugin architecture can be used to add new features. More details here . Config API endpoint can be used to create new user, clients, scopes, etc. This data is stores into the same persistence store as the Jans-Auth server. Jans Config API Flow # sequenceDiagram title Jans Config API request flow autonumber participant Admin participant Admin UI participant Config API participant Auth Server participant Jans Persistence Admin->>Admin UI: Create Client note over Admin UI: Click on plus sign to Create Client and Save button to create new client Config API->>Auth Server: Introspect Token Auth Server->>Config API: Returns Introspection Response Config API->>Config API: Successful validation of token claim with Introspection Response Config API->>Jans Persistence: Validate and persist client data Config API->>Admin UI: Returns persistence status Admin : Administrator of the application. Will use Admin UI to configure application. Admin UI : Gluu graphical user interface for the administrators to manage configuration and other properties of Jans Auth Server via Jans Config API. Config API : Jans API gateway for configuring Janssen modules like Jans Auth Server, fido2, SCIM, etc. Auth Server : Janssen federated identity with comprehensive implementation of OpenID Connect. Used for introspection of access token in this flow. Jans Persistence : Jans Persistence layer to persist data in backend.", "title": "jans-config-api"}, {"location": "contribute/implementation-design/jans-config-api/#overview", "text": "", "title": "Overview"}, {"location": "contribute/implementation-design/jans-config-api/#janssen-config-api", "text": "Janssen(Jans) Config API is an application programming interface (API) gateway managing configuring of various Janssen modules. Diagram reference", "title": "Janssen Config API"}, {"location": "contribute/implementation-design/jans-config-api/#jans-config-api-features", "text": "Jans Config API uses REST endpoints to communicate. Jans Config API endpoint are OAuth 2.0 protected. More details here Jans Config API plugin architecture can be used to add new features. More details here . Config API endpoint can be used to create new user, clients, scopes, etc. This data is stores into the same persistence store as the Jans-Auth server.", "title": "Jans Config API features:"}, {"location": "contribute/implementation-design/jans-config-api/#jans-config-api-flow", "text": "sequenceDiagram title Jans Config API request flow autonumber participant Admin participant Admin UI participant Config API participant Auth Server participant Jans Persistence Admin->>Admin UI: Create Client note over Admin UI: Click on plus sign to Create Client and Save button to create new client Config API->>Auth Server: Introspect Token Auth Server->>Config API: Returns Introspection Response Config API->>Config API: Successful validation of token claim with Introspection Response Config API->>Jans Persistence: Validate and persist client data Config API->>Admin UI: Returns persistence status Admin : Administrator of the application. Will use Admin UI to configure application. Admin UI : Gluu graphical user interface for the administrators to manage configuration and other properties of Jans Auth Server via Jans Config API. Config API : Jans API gateway for configuring Janssen modules like Jans Auth Server, fido2, SCIM, etc. Auth Server : Janssen federated identity with comprehensive implementation of OpenID Connect. Used for introspection of access token in this flow. Jans Persistence : Jans Persistence layer to persist data in backend.", "title": "Jans Config API Flow"}, {"location": "contribute/implementation-design/jans-core/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "jans-core"}, {"location": "contribute/implementation-design/jans-core/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/jans-core/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/jans-core/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "contribute/implementation-design/jans-fido2/", "tags": ["developer", "fido"], "text": "Overview # Janssen's FIDO2 server # FIDO2 as an open standard for authentication is based on public key cryptography. Janssen's FIDO2 server - a component inside the Janssen project enables users of RPs to enroll and authenticate themselves using U2F keys, FIDO2 keys or inbuilt platform authenticator. 1. The FIDO2 server uses REST endpoints to communicate with an RP via an https connection. 2. The FIDO2 server implements the FIDO Metadata Service (MDS3) defined by FIDO Alliance. 3. The FIDO2 server stores user data into the same persistence store as the Jans-Auth server. (PostgreSQL, MYSQL etc.) Components of the FIDO2 ecosystem in Janssen # Diagram reference User : User of an application, the one who possesses the Authenticator and who's role is to pass the Test of User Presence (TUP) (touch device, look, speak etc.). WebAuthn API : A global web standard for password-less FIDO2 authentication, implemented by most browsers (Google Chrome, Mozilla Firefox, Microsoft Edge, Apple Safari, Opera, Microsoft edge). It provides clients access to the underlying capabilities of the Authenticator. WebAuthn offers a very good user experience, there is no need for any additional browser plugin to be installed. WebAuthn API: enables clients to make requests to authenticators with regards to : creation of a new key-pair provide an assertion about a key report capabilities (capability exists but not offered in Janssen's FIDO2 offering) manage a PIN. (capability exists but not offered in Janssen's FIDO2 offering) Authenticator : A device which holds the private key. It prompts the user to perform a certain gesture. It can be a platform authenticator that is built into the client device or a roaming authenticator that is connected to the client device through USB, BLE, or NFC. Relying Party : The RP ( jans-auth or casa ) implements a Javascript Client which makes a registration and authentication request to the WebAuthn API. The Relying Party ID is the DNS domain where the FIDO2 device will be registered and used. CTAP2 : Simple and lightweight hardware protocol that enables Authenticators to talk with Supported browsers. FIDO2 Server Janssen's FIDO server is a standalone server communicates with the RP using an API which can be obtained by querying the following URL : https://<myjans-server>/.well-known/fido2-configuration Response: { \"version\": \"1.1\", \"issuer\": \"https://<myjans-server>\", \"attestation\": { \"base_path\": \"https://<myjans-server>/jans-fido2/restv1/attestation\", \"options_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/attestation/options\", \"result_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/attestation/result\" }, \"assertion\": { \"base_path\": \"https://<myjans-server>/jans-fido2/restv1/assertion\", \"options_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/assertion/options\", \"result_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/assertion/result\" } } The two main functionalities are: 1. Attestation 2. Assertion The authenticator credentials obtained after querying the WebAuthn API is forwarded to the FIDO2 server for attestation or assertion. Interception script : In the Janssen ecosystem, the authentication flow that comprises of the calls to WebAuthn API and the FIDO server is achieved using an interception script, details of it can be found here . Attestation formats supported by Janssen's FIDO server # Packed (FIDO2) : The most used attestation format TPM : Attestation for Windows10 devices Android key attestation : Attestation for android devices. Android SafetyNet : Any Android devices running 7+ FIDO U2F : Legacy U2F authenticators Apple Anonymous : Apple devices do attestations differently. None Backward compatibility with U2F authenticators # The FIDO server offers registration and authentication using legacy U2F authenticators. References # https://www.w3.org/TR/webauthn-2/ http://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html Tools # https://jwt.io/ \u2013 For JWT decoding and debugging https://www.base64decode.org/ \u2013 For Decoding Base64 to UTF8 https://fidoalliance.org/certification/fido-certified-products/ - To browse authenticators listed with FIDO Alliance", "title": "jans-fido2"}, {"location": "contribute/implementation-design/jans-fido2/#overview", "text": "", "title": "Overview"}, {"location": "contribute/implementation-design/jans-fido2/#janssens-fido2-server", "text": "FIDO2 as an open standard for authentication is based on public key cryptography. Janssen's FIDO2 server - a component inside the Janssen project enables users of RPs to enroll and authenticate themselves using U2F keys, FIDO2 keys or inbuilt platform authenticator. 1. The FIDO2 server uses REST endpoints to communicate with an RP via an https connection. 2. The FIDO2 server implements the FIDO Metadata Service (MDS3) defined by FIDO Alliance. 3. The FIDO2 server stores user data into the same persistence store as the Jans-Auth server. (PostgreSQL, MYSQL etc.)", "title": "Janssen's FIDO2 server"}, {"location": "contribute/implementation-design/jans-fido2/#components-of-the-fido2-ecosystem-in-janssen", "text": "Diagram reference User : User of an application, the one who possesses the Authenticator and who's role is to pass the Test of User Presence (TUP) (touch device, look, speak etc.). WebAuthn API : A global web standard for password-less FIDO2 authentication, implemented by most browsers (Google Chrome, Mozilla Firefox, Microsoft Edge, Apple Safari, Opera, Microsoft edge). It provides clients access to the underlying capabilities of the Authenticator. WebAuthn offers a very good user experience, there is no need for any additional browser plugin to be installed. WebAuthn API: enables clients to make requests to authenticators with regards to : creation of a new key-pair provide an assertion about a key report capabilities (capability exists but not offered in Janssen's FIDO2 offering) manage a PIN. (capability exists but not offered in Janssen's FIDO2 offering) Authenticator : A device which holds the private key. It prompts the user to perform a certain gesture. It can be a platform authenticator that is built into the client device or a roaming authenticator that is connected to the client device through USB, BLE, or NFC. Relying Party : The RP ( jans-auth or casa ) implements a Javascript Client which makes a registration and authentication request to the WebAuthn API. The Relying Party ID is the DNS domain where the FIDO2 device will be registered and used. CTAP2 : Simple and lightweight hardware protocol that enables Authenticators to talk with Supported browsers. FIDO2 Server Janssen's FIDO server is a standalone server communicates with the RP using an API which can be obtained by querying the following URL : https://<myjans-server>/.well-known/fido2-configuration Response: { \"version\": \"1.1\", \"issuer\": \"https://<myjans-server>\", \"attestation\": { \"base_path\": \"https://<myjans-server>/jans-fido2/restv1/attestation\", \"options_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/attestation/options\", \"result_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/attestation/result\" }, \"assertion\": { \"base_path\": \"https://<myjans-server>/jans-fido2/restv1/assertion\", \"options_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/assertion/options\", \"result_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/assertion/result\" } } The two main functionalities are: 1. Attestation 2. Assertion The authenticator credentials obtained after querying the WebAuthn API is forwarded to the FIDO2 server for attestation or assertion. Interception script : In the Janssen ecosystem, the authentication flow that comprises of the calls to WebAuthn API and the FIDO server is achieved using an interception script, details of it can be found here .", "title": "Components of the FIDO2 ecosystem in Janssen"}, {"location": "contribute/implementation-design/jans-fido2/#attestation-formats-supported-by-janssens-fido-server", "text": "Packed (FIDO2) : The most used attestation format TPM : Attestation for Windows10 devices Android key attestation : Attestation for android devices. Android SafetyNet : Any Android devices running 7+ FIDO U2F : Legacy U2F authenticators Apple Anonymous : Apple devices do attestations differently. None", "title": "Attestation formats supported by Janssen's FIDO server"}, {"location": "contribute/implementation-design/jans-fido2/#backward-compatibility-with-u2f-authenticators", "text": "The FIDO server offers registration and authentication using legacy U2F authenticators.", "title": "Backward compatibility with U2F authenticators"}, {"location": "contribute/implementation-design/jans-fido2/#references", "text": "https://www.w3.org/TR/webauthn-2/ http://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html", "title": "References"}, {"location": "contribute/implementation-design/jans-fido2/#tools", "text": "https://jwt.io/ \u2013 For JWT decoding and debugging https://www.base64decode.org/ \u2013 For Decoding Base64 to UTF8 https://fidoalliance.org/certification/fido-certified-products/ - To browse authenticators listed with FIDO Alliance", "title": "Tools"}, {"location": "contribute/implementation-design/jans-orm/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "jans-orm"}, {"location": "contribute/implementation-design/jans-orm/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/jans-orm/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/jans-orm/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "contribute/implementation-design/jans-scim/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "jans-scim"}, {"location": "contribute/implementation-design/jans-scim/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/jans-scim/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/jans-scim/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "governance/charter/", "tags": ["governance", "charter"], "text": "Technical Charter (the \u201cCharter\u201d) for Janssen Project a Series of LF Projects, LLC # Adopted December 8, 2020 This Charter sets forth the responsibilities and procedures for technical contribution to, and oversight of, the Janssen open source project, which has been established as Janssen Project a Series of LF Projects, LLC (the \u201cProject\u201d). LF Projects, LLC (\u201cLF Projects\u201d) is a Delaware series limited liability company. All contributors (including committers, maintainers, and other technical positions) and other participants in the Project (collectively, \u201cCollaborators\u201d) must comply with the terms of this Charter. Mission and Scope of the Project The mission of the Project is to develop and maintain a cloud native identity and authorization platform that comprehensively implements OAuth, OpenID Connect and the User Managed Access protocol, while maintaining flexibility and horizontal scalability. The scope of the Project includes collaborative development under the Project License (as defined herein) supporting the mission, including documentation, testing, integration and the creation of other artifacts that aid the development, deployment, operation or adoption of the open source project. Technical Steering Committee The Technical Steering Committee (the \u201cTSC\u201d) will be responsible for all technical oversight of the open source Project. The TSC voting members are initially the Project\u2019s Committers. At the inception of the project, the Committers of the Project will be as set forth within the \u201cCONTRIBUTING\u201d file within the Project\u2019s code repository. The TSC may choose an alternative approach for determining the voting members of the TSC, and any such alternative approach will be documented in the CONTRIBUTING file. Any meetings of the Technical Steering Committee are intended to be open to the public, and can be conducted electronically, via teleconference, or in person. TSC projects generally will involve Contributors and Committers. The TSC may adopt or modify roles so long as the roles are documented in the CONTRIBUTING file. Unless otherwise documented: Contributors include anyone in the technical community that contributes code, documentation, or other technical artifacts to the Project; Committers are Contributors who have earned the ability to modify (\u201ccommit\u201d) source code, documentation or other technical artifacts in a project\u2019s repository; and A Contributor may become a Committer by a majority approval of the existing Committers. A Committer may be removed by a majority approval of the other existing Committers. Participation in the Project through becoming a Contributor and Committer is open to anyone so long as they abide by the terms of this Charter. The TSC may (1) establish work flow procedures for the submission, approval, and closure/archiving of projects, (2) set requirements for the promotion of Contributors to Committer status, as applicable, and (3) amend, adjust, refine and/or eliminate the roles of Contributors, and Committers, and create new roles, and publicly document any TSC roles, as it sees fit. The TSC may elect a TSC Chair, who will preside over meetings of the TSC and will serve until their resignation or replacement by the TSC. Responsibilities: The TSC will be responsible for all aspects of oversight relating to the Project, which may include: coordinating the technical direction of the Project; approving project or system proposals (including, but not limited to, incubation, deprecation, and changes to a sub-project\u2019s scope); organizing sub-projects and removing sub-projects; creating sub-committees or working groups to focus on cross-project technical issues and requirements; appointing representatives to work with other open source or open standards communities; establishing community norms, workflows, issuing releases, and security issue reporting policies; approving and implementing policies and processes for contributing (to be published in the CONTRIBUTING file) and coordinating with the series manager of the Project (as provided for in the Series Agreement, the \u201cSeries Manager\u201d) to resolve matters or concerns that may arise as set forth in Section 7 of this Charter; discussions, seeking consensus, and where necessary, voting on technical matters relating to the code base that affect multiple projects; and coordinating any marketing, events, or communications regarding the Project. TSC Voting While the Project aims to operate as a consensus-based community, if any TSC decision requires a vote to move the Project forward, the voting members of the TSC will vote on a one vote per voting member basis. Quorum for TSC meetings requires at least fifty percent of all voting members of the TSC to be present. The TSC may continue to meet if quorum is not met but will be prevented from making any decisions at the meeting. Except as provided in Section 7.iii. and 8.i, decisions by vote at a meeting require a majority vote of those in attendance, provided quorum is met. Decisions made by electronic vote without a meeting require a majority vote of all voting members of the TSC. In the event a vote cannot be resolved by the TSC, any voting member of the TSC may refer the matter to the Series Manager for assistance in reaching a resolution. Compliance with Policies This Charter is subject to the Series Agreement for the Project and the Operating Agreement of LF Projects. Contributors will comply with the policies of LF Projects as may be adopted and amended by LF Projects, including, without limitation the policies listed at https://lfprojects.org/policies/. The TSC may adopt a code of conduct (\u201cCoC\u201d) for the Project, which is subject to approval by the Series Manager. In the event that a Project-specific CoC has not been approved, the LF Projects Code of Conduct listed at https://lfprojects.org/policies will apply for all Collaborators in the Project. When amending or adopting any policy applicable to the Project, LF Projects will publish such policy, as to be amended or adopted, on its web site at least 30 days prior to such policy taking effect; provided, however, that in the case of any amendment of the Trademark Policy or Terms of Use of LF Projects, any such amendment is effective upon publication on LF Project\u2019s web site. All Collaborators must allow open participation from any individual or organization meeting the requirements for contributing under this Charter and any policies adopted for all Collaborators by the TSC, regardless of competitive interests. Put another way, the Project community must not seek to exclude any participant based on any criteria, requirement, or reason other than those that are reasonable and applied on a non-discriminatory basis to all Collaborators in the Project community. The Project will operate in a transparent, open, collaborative, and ethical manner at all times. The output of all Project discussions, proposals, timelines, decisions, and status should be made open and easily visible to all. Any potential violations of this requirement should be reported immediately to the Series Manager. Community Assets LF Projects will hold title to all trade or service marks used by the Project (\u201cProject Trademarks\u201d), whether based on common law or registered rights. Project Trademarks will be transferred and assigned to LF Projects to hold on behalf of the Project. Any use of any Project Trademarks by Collaborators in the Project will be in accordance with the license from LF Projects and inure to the benefit of LF Projects. The Project will, as permitted and in accordance with such license from LF Projects, develop and own all Project GitHub and social media accounts, and domain name registrations created by the Project community. Under no circumstances will LF Projects be expected or required to undertake any action on behalf of the Project that is inconsistent with the tax-exempt status or purpose, as applicable, of LFP, Inc. or LF Projects, LLC. General Rules and Operations. The Project will: engage in the work of the Project in a professional manner consistent with maintaining a cohesive community, while also maintaining the goodwill and esteem of LF Projects, LFP, Inc. and other partner organizations in the open source community; and respect the rights of all trademark owners, including any branding and trademark usage guidelines. Intellectual Property Policy Collaborators acknowledge that the copyright in all new contributions will be retained by the copyright holder as independent works of authorship and that no contributor or copyright holder will be required to assign copyrights to the Project. Except as described in Section 7.iii., all contributions to the Project are subject to the following: All new inbound code contributions to the Project must be made using the Apache License, Version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 (the \u201cProject License\u201d). All new inbound code contributions must also be accompanied by a Developer Certificate of Origin ( http://developercertificate.org ) sign-off in the source code system that is submitted through a TSC-approved contribution process which will bind the authorized contributor and, if not self-employed, their employer to the applicable license; All outbound code will be made available under the Project License. Documentation will be received and made available by the Project under the Creative Commons Attribution 4.0 International License (available at http://creativecommons.org/licenses/by/4.0/ ). The Project may seek to integrate and contribute back to other open source projects (\u201cUpstream Projects\u201d). In such cases, the Project will conform to all license requirements of the Upstream Projects, including dependencies, leveraged by the Project. Upstream Project code contributions not stored within the Project\u2019s main code repository will comply with the contribution process and license terms for the applicable Upstream Project. The TSC may approve the use of an alternative license or licenses for inbound or outbound contributions on an exception basis. To request an exception, please describe the contribution, the alternative open source license(s), and the justification for using an alternative open source license for the Project. License exceptions must be approved by a two-thirds vote of the entire TSC. Contributed files should contain license information, such as SPDX short form identifiers, indicating the open source license or licenses pertaining to the file. Amendments This charter may be amended by a two-thirds vote of the entire TSC and is subject to approval by LF Projects.", "title": "Charter"}, {"location": "governance/charter/#technical-charter-the-charter-for-janssen-project-a-series-of-lf-projects-llc", "text": "Adopted December 8, 2020 This Charter sets forth the responsibilities and procedures for technical contribution to, and oversight of, the Janssen open source project, which has been established as Janssen Project a Series of LF Projects, LLC (the \u201cProject\u201d). LF Projects, LLC (\u201cLF Projects\u201d) is a Delaware series limited liability company. All contributors (including committers, maintainers, and other technical positions) and other participants in the Project (collectively, \u201cCollaborators\u201d) must comply with the terms of this Charter. Mission and Scope of the Project The mission of the Project is to develop and maintain a cloud native identity and authorization platform that comprehensively implements OAuth, OpenID Connect and the User Managed Access protocol, while maintaining flexibility and horizontal scalability. The scope of the Project includes collaborative development under the Project License (as defined herein) supporting the mission, including documentation, testing, integration and the creation of other artifacts that aid the development, deployment, operation or adoption of the open source project. Technical Steering Committee The Technical Steering Committee (the \u201cTSC\u201d) will be responsible for all technical oversight of the open source Project. The TSC voting members are initially the Project\u2019s Committers. At the inception of the project, the Committers of the Project will be as set forth within the \u201cCONTRIBUTING\u201d file within the Project\u2019s code repository. The TSC may choose an alternative approach for determining the voting members of the TSC, and any such alternative approach will be documented in the CONTRIBUTING file. Any meetings of the Technical Steering Committee are intended to be open to the public, and can be conducted electronically, via teleconference, or in person. TSC projects generally will involve Contributors and Committers. The TSC may adopt or modify roles so long as the roles are documented in the CONTRIBUTING file. Unless otherwise documented: Contributors include anyone in the technical community that contributes code, documentation, or other technical artifacts to the Project; Committers are Contributors who have earned the ability to modify (\u201ccommit\u201d) source code, documentation or other technical artifacts in a project\u2019s repository; and A Contributor may become a Committer by a majority approval of the existing Committers. A Committer may be removed by a majority approval of the other existing Committers. Participation in the Project through becoming a Contributor and Committer is open to anyone so long as they abide by the terms of this Charter. The TSC may (1) establish work flow procedures for the submission, approval, and closure/archiving of projects, (2) set requirements for the promotion of Contributors to Committer status, as applicable, and (3) amend, adjust, refine and/or eliminate the roles of Contributors, and Committers, and create new roles, and publicly document any TSC roles, as it sees fit. The TSC may elect a TSC Chair, who will preside over meetings of the TSC and will serve until their resignation or replacement by the TSC. Responsibilities: The TSC will be responsible for all aspects of oversight relating to the Project, which may include: coordinating the technical direction of the Project; approving project or system proposals (including, but not limited to, incubation, deprecation, and changes to a sub-project\u2019s scope); organizing sub-projects and removing sub-projects; creating sub-committees or working groups to focus on cross-project technical issues and requirements; appointing representatives to work with other open source or open standards communities; establishing community norms, workflows, issuing releases, and security issue reporting policies; approving and implementing policies and processes for contributing (to be published in the CONTRIBUTING file) and coordinating with the series manager of the Project (as provided for in the Series Agreement, the \u201cSeries Manager\u201d) to resolve matters or concerns that may arise as set forth in Section 7 of this Charter; discussions, seeking consensus, and where necessary, voting on technical matters relating to the code base that affect multiple projects; and coordinating any marketing, events, or communications regarding the Project. TSC Voting While the Project aims to operate as a consensus-based community, if any TSC decision requires a vote to move the Project forward, the voting members of the TSC will vote on a one vote per voting member basis. Quorum for TSC meetings requires at least fifty percent of all voting members of the TSC to be present. The TSC may continue to meet if quorum is not met but will be prevented from making any decisions at the meeting. Except as provided in Section 7.iii. and 8.i, decisions by vote at a meeting require a majority vote of those in attendance, provided quorum is met. Decisions made by electronic vote without a meeting require a majority vote of all voting members of the TSC. In the event a vote cannot be resolved by the TSC, any voting member of the TSC may refer the matter to the Series Manager for assistance in reaching a resolution. Compliance with Policies This Charter is subject to the Series Agreement for the Project and the Operating Agreement of LF Projects. Contributors will comply with the policies of LF Projects as may be adopted and amended by LF Projects, including, without limitation the policies listed at https://lfprojects.org/policies/. The TSC may adopt a code of conduct (\u201cCoC\u201d) for the Project, which is subject to approval by the Series Manager. In the event that a Project-specific CoC has not been approved, the LF Projects Code of Conduct listed at https://lfprojects.org/policies will apply for all Collaborators in the Project. When amending or adopting any policy applicable to the Project, LF Projects will publish such policy, as to be amended or adopted, on its web site at least 30 days prior to such policy taking effect; provided, however, that in the case of any amendment of the Trademark Policy or Terms of Use of LF Projects, any such amendment is effective upon publication on LF Project\u2019s web site. All Collaborators must allow open participation from any individual or organization meeting the requirements for contributing under this Charter and any policies adopted for all Collaborators by the TSC, regardless of competitive interests. Put another way, the Project community must not seek to exclude any participant based on any criteria, requirement, or reason other than those that are reasonable and applied on a non-discriminatory basis to all Collaborators in the Project community. The Project will operate in a transparent, open, collaborative, and ethical manner at all times. The output of all Project discussions, proposals, timelines, decisions, and status should be made open and easily visible to all. Any potential violations of this requirement should be reported immediately to the Series Manager. Community Assets LF Projects will hold title to all trade or service marks used by the Project (\u201cProject Trademarks\u201d), whether based on common law or registered rights. Project Trademarks will be transferred and assigned to LF Projects to hold on behalf of the Project. Any use of any Project Trademarks by Collaborators in the Project will be in accordance with the license from LF Projects and inure to the benefit of LF Projects. The Project will, as permitted and in accordance with such license from LF Projects, develop and own all Project GitHub and social media accounts, and domain name registrations created by the Project community. Under no circumstances will LF Projects be expected or required to undertake any action on behalf of the Project that is inconsistent with the tax-exempt status or purpose, as applicable, of LFP, Inc. or LF Projects, LLC. General Rules and Operations. The Project will: engage in the work of the Project in a professional manner consistent with maintaining a cohesive community, while also maintaining the goodwill and esteem of LF Projects, LFP, Inc. and other partner organizations in the open source community; and respect the rights of all trademark owners, including any branding and trademark usage guidelines. Intellectual Property Policy Collaborators acknowledge that the copyright in all new contributions will be retained by the copyright holder as independent works of authorship and that no contributor or copyright holder will be required to assign copyrights to the Project. Except as described in Section 7.iii., all contributions to the Project are subject to the following: All new inbound code contributions to the Project must be made using the Apache License, Version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 (the \u201cProject License\u201d). All new inbound code contributions must also be accompanied by a Developer Certificate of Origin ( http://developercertificate.org ) sign-off in the source code system that is submitted through a TSC-approved contribution process which will bind the authorized contributor and, if not self-employed, their employer to the applicable license; All outbound code will be made available under the Project License. Documentation will be received and made available by the Project under the Creative Commons Attribution 4.0 International License (available at http://creativecommons.org/licenses/by/4.0/ ). The Project may seek to integrate and contribute back to other open source projects (\u201cUpstream Projects\u201d). In such cases, the Project will conform to all license requirements of the Upstream Projects, including dependencies, leveraged by the Project. Upstream Project code contributions not stored within the Project\u2019s main code repository will comply with the contribution process and license terms for the applicable Upstream Project. The TSC may approve the use of an alternative license or licenses for inbound or outbound contributions on an exception basis. To request an exception, please describe the contribution, the alternative open source license(s), and the justification for using an alternative open source license for the Project. License exceptions must be approved by a two-thirds vote of the entire TSC. Contributed files should contain license information, such as SPDX short form identifiers, indicating the open source license or licenses pertaining to the file. Amendments This charter may be amended by a two-thirds vote of the entire TSC and is subject to approval by LF Projects.", "title": "Technical Charter (the \u201cCharter\u201d) for Janssen Project a Series of LF Projects, LLC"}, {"location": "governance/copyright-notices/", "tags": ["governance", "copyrights"], "text": "Copyrights # Ownership of Copyrights in Janssen Project Contributions # When source code, documentation and other content is contributed to the Janssen Project, the copyrights in those contributions remain owned by the original copyright holders. The copyrights are not assigned to the Janssen Project. Instead, they are licensed for distribution as part of the project. Whether a project uses a DCO or a CLA, the original copyright holders retain their copyrights. Copyright Notices # The Janssen Project does not require or recommend that every contributor include their copyright notice in contributed files. See below for more details on why not. Instead, we recommend using a more general statement in a form similar to the following: Copyright The Janssen Project Authors. Copyright The Janssen Project Contributors. Copyright Contributors to the Janssen Project. These statements are intended to communicate the following: - the work is copyrighted; - the contributors of the code licensed it, but retain ownership of their copyrights; and - it was licensed for distribution as part of the named project. By using a common format, the project avoids having to deal with names of copyright holders, years or ranges of years, and variations on the (c) symbol. This aims to minimize the burden on developers and maintainers as well as redistributors of the code. What if I want my copyright notice included? # Please note that it is not wrong , and it is acceptable, if a contributor wishes to keep their own copyright notices on their contributions. The above is a recommended format for ease of use, but is not mandated by the Janssen Project. If you are contributing on behalf of your employer, you may wish to discuss with your legal department about whether they will require you to include a copyright notice identifying them as the copyright holder in contributions. What about Third Party Code? # If a file only contains code that originates from a third party source who didn't contribute it themselves, then you would not want to add the notices above. (In a similar vein, you wouldn't add a notice identifying you as the copyright holder either, if you didn't own it.) Just preserve the existing copyright and license notices as they are. If, however, you add copyrightable content to a pre-existing file from another project, then at that point you could add a copyright notice similar to the one above. Don't Change Someone Else's Notice without their Permission # You should not change or remove someone else's copyright notice unless they have expressly permitted you to do so. This includes third parties' notices in pre-existing code. Why not list every copyright holder? # There are several reasons why the Janssen Project doesn't require or recommend trying to list every copyright holder for contributions to every file: Copyright notices are not mandatory in order for the contributor to retain ownership of their copyright. Copyright notices are rarely kept up to date as a file evolves, resulting in inaccurate statements. Trying to keep notices up to date, or to correct notices that have become inaccurate, increases the burden on developers without tangible benefit. Developers and maintainers often do not want to have to worry about e.g. whether a minor contribution (such as a typo fix) means that a new copyright notice should be added. Adding many different copyright notices may increase the burden on downstream distributors, if their license compliance processes involve reproducing notices. The specific individual or legal entity that owns the copyright might not be known to the contributor; it could be you, your employer, or some other entity.", "title": "Copyright-notice"}, {"location": "governance/copyright-notices/#copyrights", "text": "", "title": "Copyrights"}, {"location": "governance/copyright-notices/#ownership-of-copyrights-in-janssen-project-contributions", "text": "When source code, documentation and other content is contributed to the Janssen Project, the copyrights in those contributions remain owned by the original copyright holders. The copyrights are not assigned to the Janssen Project. Instead, they are licensed for distribution as part of the project. Whether a project uses a DCO or a CLA, the original copyright holders retain their copyrights.", "title": "Ownership of Copyrights in Janssen Project Contributions"}, {"location": "governance/copyright-notices/#copyright-notices", "text": "The Janssen Project does not require or recommend that every contributor include their copyright notice in contributed files. See below for more details on why not. Instead, we recommend using a more general statement in a form similar to the following: Copyright The Janssen Project Authors. Copyright The Janssen Project Contributors. Copyright Contributors to the Janssen Project. These statements are intended to communicate the following: - the work is copyrighted; - the contributors of the code licensed it, but retain ownership of their copyrights; and - it was licensed for distribution as part of the named project. By using a common format, the project avoids having to deal with names of copyright holders, years or ranges of years, and variations on the (c) symbol. This aims to minimize the burden on developers and maintainers as well as redistributors of the code.", "title": "Copyright Notices"}, {"location": "governance/copyright-notices/#what-if-i-want-my-copyright-notice-included", "text": "Please note that it is not wrong , and it is acceptable, if a contributor wishes to keep their own copyright notices on their contributions. The above is a recommended format for ease of use, but is not mandated by the Janssen Project. If you are contributing on behalf of your employer, you may wish to discuss with your legal department about whether they will require you to include a copyright notice identifying them as the copyright holder in contributions.", "title": "What if I want my copyright notice included?"}, {"location": "governance/copyright-notices/#what-about-third-party-code", "text": "If a file only contains code that originates from a third party source who didn't contribute it themselves, then you would not want to add the notices above. (In a similar vein, you wouldn't add a notice identifying you as the copyright holder either, if you didn't own it.) Just preserve the existing copyright and license notices as they are. If, however, you add copyrightable content to a pre-existing file from another project, then at that point you could add a copyright notice similar to the one above.", "title": "What about Third Party Code?"}, {"location": "governance/copyright-notices/#dont-change-someone-elses-notice-without-their-permission", "text": "You should not change or remove someone else's copyright notice unless they have expressly permitted you to do so. This includes third parties' notices in pre-existing code.", "title": "Don't Change Someone Else's Notice without their Permission"}, {"location": "governance/copyright-notices/#why-not-list-every-copyright-holder", "text": "There are several reasons why the Janssen Project doesn't require or recommend trying to list every copyright holder for contributions to every file: Copyright notices are not mandatory in order for the contributor to retain ownership of their copyright. Copyright notices are rarely kept up to date as a file evolves, resulting in inaccurate statements. Trying to keep notices up to date, or to correct notices that have become inaccurate, increases the burden on developers without tangible benefit. Developers and maintainers often do not want to have to worry about e.g. whether a minor contribution (such as a typo fix) means that a new copyright notice should be added. Adding many different copyright notices may increase the burden on downstream distributors, if their license compliance processes involve reproducing notices. The specific individual or legal entity that owns the copyright might not be known to the contributor; it could be you, your employer, or some other entity.", "title": "Why not list every copyright holder?"}, {"location": "governance/triage/", "tags": ["governance", "triage"], "text": "Janssen Triage Process and labels # Triage process is used to quickly screen and categorise new issues and PRs. Aim is to determine characteristics of new PRs/issues and take quick actions if possible. Triage process is a contineous process. As new issues/PRs come in, the community initiates discussions, add labels, ask for more details. This process does not wait for triage call or a meeting to be called. Community holds triage calls at a regular cadence. Triage calls are mainly utilised to discuss issue/PR where concensus is not yet reached and to pick up anything which is not yet triaged. It is encouraged to complete triage outside of triage call to improve velocity. Stages in triage process: # Name Description Needs triage When a new issue or PR is created, it is automatically labeled as needs-triage . The label indicates that this issue is missing some of the metadata. Metadata such as the missing owner. Or the owner needs to add metadata labels for effort , priority , kind and component. Once these labels are added, the owner should remove this label and add ready-for-triage label. Ready for triage This label indicates that the issue has enough information and can be triaged. Triaged All issues/PRs with the label ready-for-triage will be reviewed by core members of the community who have permission to add triaged label. Reviewer reviews issue/PR to check if the issue/PR is fully triaged and can be added to backlog without discussion on triage call. At this point, the label triaged is added and the label ready-for-triage is removed. We expect most of the isseus and PRs will be able to follow above path and quickly move out of triage process without waiting for triage call. Issues/PRs which still doesn't have triaged label, or has needs-discussion label, will be discussed during triage call. Labels # Github labels help us annotate issues/PRs with additional data. Janssen community uses labels, as detailed below, to communicate information and help making decisions about issues/PRs. Communication labels # These labels communicate status of current triage process for an issue/PR or indicate where community contribution is required. Most of communication labels would be replaced by other labels as triage process progresses and issue enters active development. For example, help wanted label would be removed once issue gets under active development and a community members takes ownership of the issue. Below is the list of labels which fall under this category: Label Indicates That needs-triage issue/PR needs triaging ready-for-triage that sufficient details has been added to the issue/PR in form of labels and is ready for triage review triaged Issue/PR is fully triaged needs-information Indicates that creator needs to add more information to issue/PR in order to be meaningfully triaged. When adding this label, also comment on the issue about what information is needed needs-discussion Indicates that issue needs discussion during triage meeting. When adding this label, also comment on the issue about what is it that demands discussion on this issue good first issue Indicates to the community that this issue suitable for first time contributor help wanted Indicates to the community that this issue has complexity which is suitable for contribution from any external contributor Metadata labels # These labels enrich issue/PR with metadata that will help during triage process and active development. These labels may not be removed from issue/PR, though value of labels may change as development progresses. For example, effort label may change from effort-3 to effort-8 as we understand issue in more detail. Below is the list of labels in this category: Label Indicates That Details comp-<module> Major Janssen components needing change in order to fix this issue/PR. For example, if this issue/PR would require change in files under fido2 module (under jans/fido2) , then apply comp-jans-fido2 label e.g comp-jans-auth-server , comp-jans-fido2 , area-<concern> Cross-cutting concerns involved in fixing this issue/PR. For example, if changes introduced by this issue/PR will need changes in documentation and need to be mentioned in release notes as well, then apply area-documentation , area-release-notes . area-CI should be applied when changes are required in artifacts relevent to automation, CI build infrastructure or release management process. An example of such artifact would be Github workflow scripts located under .github/workflows Labels available: area-documentation , area-release-notes , area-CI kind-bug Issue/PR is a bug in existing functionality kind-enhancement Issue/PR is an enhancement to an existing functionality kind-feature Issue/PR is new feature request kind-question Issue/PR is a question that can be addressed via pointers to documentation or user education kind-duplicate Issue/PR is a duplicate of existing issue/PR. Original issue should be mentioned in the comments using Duplicate of reply kind-dependencies Fix for Issue/PR pertains to external dependencies effort-1 Relative effort required for completion effort-2 Relative effort required for completion effort-3 Relative effort required for completion effort-5 Relative effort required for completion effort-8 Relative effort required for completion effort-13 Relative effort required for completion effort-21 Relative effort required for completion priority-0 An issue that causes a full outage, breakage, or major function unavailability for everyone, without any known workaround. The issue must be fixed immediately, taking precedence over all other work. Should receive updates at least once per day. priority-1 An issue that significantly impacts a large percentage of users; if there is a workaround it is partial or overly painful. The issue should be resolved before the next release. priority-2 The issue is important to a large percentage of users, with a workaround. Issues that are significantly ugly or painful (especially first-use or install-time issues). Issues with workarounds that would otherwise be P0 or P1. priority-3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent. priority-4 A relatively minor issue that is not relevant to core functions, or relates only to the attractiveness or pleasantness of use of the system. Good to have but not necessary changes/fixes. priority-5 The team acknowledges the request but (due to any number of reasons) does not plan to work on or accept contributions for this request. The issue remains open for discussion. Bot labeling methodology # The following labels are automatically assigned to Issues and PRs in GitHub following the schema provided in this file . Label Method comp-<module> The bot will detect from the title the component between the parentheses. feat(jans-auth-server): detect will result in the label comp-jans-auth-server added to the issue or PR. In a PR these labels are also detected by modified files path area-<concern> The bot will detect from the title the area appropriate. ci: adding something new to our ci will result in the label area-CI added to the issue or PR. In a PR these labels are also detected by modified files path. kind-bug The bot will detect this from the conventional commit written title kind-enhancement The bot will detect this from the conventional commit written title kind-feature The bot will detect this from the conventional commit written title kind-question Issue/PR is a question that can be addressed via pointers to documentation or user education kind-dependencies The bot will detect this from the conventional commit written title", "title": "Triage"}, {"location": "governance/triage/#janssen-triage-process-and-labels", "text": "Triage process is used to quickly screen and categorise new issues and PRs. Aim is to determine characteristics of new PRs/issues and take quick actions if possible. Triage process is a contineous process. As new issues/PRs come in, the community initiates discussions, add labels, ask for more details. This process does not wait for triage call or a meeting to be called. Community holds triage calls at a regular cadence. Triage calls are mainly utilised to discuss issue/PR where concensus is not yet reached and to pick up anything which is not yet triaged. It is encouraged to complete triage outside of triage call to improve velocity.", "title": "Janssen Triage Process and labels"}, {"location": "governance/triage/#stages-in-triage-process", "text": "Name Description Needs triage When a new issue or PR is created, it is automatically labeled as needs-triage . The label indicates that this issue is missing some of the metadata. Metadata such as the missing owner. Or the owner needs to add metadata labels for effort , priority , kind and component. Once these labels are added, the owner should remove this label and add ready-for-triage label. Ready for triage This label indicates that the issue has enough information and can be triaged. Triaged All issues/PRs with the label ready-for-triage will be reviewed by core members of the community who have permission to add triaged label. Reviewer reviews issue/PR to check if the issue/PR is fully triaged and can be added to backlog without discussion on triage call. At this point, the label triaged is added and the label ready-for-triage is removed. We expect most of the isseus and PRs will be able to follow above path and quickly move out of triage process without waiting for triage call. Issues/PRs which still doesn't have triaged label, or has needs-discussion label, will be discussed during triage call.", "title": "Stages in triage process:"}, {"location": "governance/triage/#labels", "text": "Github labels help us annotate issues/PRs with additional data. Janssen community uses labels, as detailed below, to communicate information and help making decisions about issues/PRs.", "title": "Labels"}, {"location": "governance/triage/#communication-labels", "text": "These labels communicate status of current triage process for an issue/PR or indicate where community contribution is required. Most of communication labels would be replaced by other labels as triage process progresses and issue enters active development. For example, help wanted label would be removed once issue gets under active development and a community members takes ownership of the issue. Below is the list of labels which fall under this category: Label Indicates That needs-triage issue/PR needs triaging ready-for-triage that sufficient details has been added to the issue/PR in form of labels and is ready for triage review triaged Issue/PR is fully triaged needs-information Indicates that creator needs to add more information to issue/PR in order to be meaningfully triaged. When adding this label, also comment on the issue about what information is needed needs-discussion Indicates that issue needs discussion during triage meeting. When adding this label, also comment on the issue about what is it that demands discussion on this issue good first issue Indicates to the community that this issue suitable for first time contributor help wanted Indicates to the community that this issue has complexity which is suitable for contribution from any external contributor", "title": "Communication labels"}, {"location": "governance/triage/#metadata-labels", "text": "These labels enrich issue/PR with metadata that will help during triage process and active development. These labels may not be removed from issue/PR, though value of labels may change as development progresses. For example, effort label may change from effort-3 to effort-8 as we understand issue in more detail. Below is the list of labels in this category: Label Indicates That Details comp-<module> Major Janssen components needing change in order to fix this issue/PR. For example, if this issue/PR would require change in files under fido2 module (under jans/fido2) , then apply comp-jans-fido2 label e.g comp-jans-auth-server , comp-jans-fido2 , area-<concern> Cross-cutting concerns involved in fixing this issue/PR. For example, if changes introduced by this issue/PR will need changes in documentation and need to be mentioned in release notes as well, then apply area-documentation , area-release-notes . area-CI should be applied when changes are required in artifacts relevent to automation, CI build infrastructure or release management process. An example of such artifact would be Github workflow scripts located under .github/workflows Labels available: area-documentation , area-release-notes , area-CI kind-bug Issue/PR is a bug in existing functionality kind-enhancement Issue/PR is an enhancement to an existing functionality kind-feature Issue/PR is new feature request kind-question Issue/PR is a question that can be addressed via pointers to documentation or user education kind-duplicate Issue/PR is a duplicate of existing issue/PR. Original issue should be mentioned in the comments using Duplicate of reply kind-dependencies Fix for Issue/PR pertains to external dependencies effort-1 Relative effort required for completion effort-2 Relative effort required for completion effort-3 Relative effort required for completion effort-5 Relative effort required for completion effort-8 Relative effort required for completion effort-13 Relative effort required for completion effort-21 Relative effort required for completion priority-0 An issue that causes a full outage, breakage, or major function unavailability for everyone, without any known workaround. The issue must be fixed immediately, taking precedence over all other work. Should receive updates at least once per day. priority-1 An issue that significantly impacts a large percentage of users; if there is a workaround it is partial or overly painful. The issue should be resolved before the next release. priority-2 The issue is important to a large percentage of users, with a workaround. Issues that are significantly ugly or painful (especially first-use or install-time issues). Issues with workarounds that would otherwise be P0 or P1. priority-3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent. priority-4 A relatively minor issue that is not relevant to core functions, or relates only to the attractiveness or pleasantness of use of the system. Good to have but not necessary changes/fixes. priority-5 The team acknowledges the request but (due to any number of reasons) does not plan to work on or accept contributions for this request. The issue remains open for discussion.", "title": "Metadata labels"}, {"location": "governance/triage/#bot-labeling-methodology", "text": "The following labels are automatically assigned to Issues and PRs in GitHub following the schema provided in this file . Label Method comp-<module> The bot will detect from the title the component between the parentheses. feat(jans-auth-server): detect will result in the label comp-jans-auth-server added to the issue or PR. In a PR these labels are also detected by modified files path area-<concern> The bot will detect from the title the area appropriate. ci: adding something new to our ci will result in the label area-CI added to the issue or PR. In a PR these labels are also detected by modified files path. kind-bug The bot will detect this from the conventional commit written title kind-enhancement The bot will detect this from the conventional commit written title kind-feature The bot will detect this from the conventional commit written title kind-question Issue/PR is a question that can be addressed via pointers to documentation or user education kind-dependencies The bot will detect this from the conventional commit written title", "title": "Bot labeling methodology"}, {"location": "janssen-server/auth-server/config/", "tags": ["administration", "auth-server", "configuration"], "text": "Configuration Overview # In some ways, this whole Auth Server admin guide is about configuration. But you have to start somewhere! This page provides a quick overview before you dive in! Config Server # The Configuration Server is a JSON/REST API that writes to the database, generates the keys, and does much of the other work you need to make your Janssen Project infrastructure solve your digital identity challenges. See the Config API Guide for more information. Tools # API - you can call the configuration endpoints with the API tool of your choice, like curl . With this mechanism, you can use client credential grant to obtain an OAuth token--just make sure it has the required scope to call the method / endpoint. See the Curl Guide for more info. CLI - The CLI, or Command Line Interface, calls the API for you. It uses the device flow to authenticate the person who is behind the config changes. See the Configuration CLI Guide for more info. TUI - The TUI, or Text User Interface, is a menu-based interactive tool that provides a more intuitive experience. When you make changes via the TUI, it also creates a log of the equivalent CLI command, in case you want a shortcut next time around. See the TUI Guide for more info. Client versus Server Configuration # Some behaviors are controlled at the server level. For example, should your Auth Server allow dynamic client registration? Other features you can configure either at the server or client level. For example, do you want user claims in an id_token ? Maybe you always want them (server), or maybe only sometimes (client). See the JSON Configuration/Properties for an overview of the server level configuration options. For client configuration options, see the Client Schema page. Interception Scripts # Janssen is a very flexible platform, that lets you customize many of the flows to meet your exact requirements. The black magic behind this flexibility is interception scripts--these are standard programming interfaces that enable you to add or change the behavior of Jans endpoints. Just to give one example, perhaps you need to add data from an external API into an OAuth access token? In this case, you could use the Update Token interception script. There are around 20 of these scripts. For a full list, see the Scripts Documentation . Customization # You don't want out of the box look and feel provided by Janssen. We know we are UX-challenged, backend developer geeks. Check out the Customization Guide for info about how to add adapt the user facing content to achieve your UX dreams. Operations # Janssen Project software has to run somewhere, right now... either on VM's or in containers. There are specifics instructions about each contained in these docs. Database and Cache # One of the biggest challenges in running the Janssen Platform is persistence. Make sure you understand how Janssen Project stores your data, or in some cases, caches it.", "title": "Auth Server Config"}, {"location": "janssen-server/auth-server/config/#configuration-overview", "text": "In some ways, this whole Auth Server admin guide is about configuration. But you have to start somewhere! This page provides a quick overview before you dive in!", "title": "Configuration Overview"}, {"location": "janssen-server/auth-server/config/#config-server", "text": "The Configuration Server is a JSON/REST API that writes to the database, generates the keys, and does much of the other work you need to make your Janssen Project infrastructure solve your digital identity challenges. See the Config API Guide for more information.", "title": "Config Server"}, {"location": "janssen-server/auth-server/config/#tools", "text": "API - you can call the configuration endpoints with the API tool of your choice, like curl . With this mechanism, you can use client credential grant to obtain an OAuth token--just make sure it has the required scope to call the method / endpoint. See the Curl Guide for more info. CLI - The CLI, or Command Line Interface, calls the API for you. It uses the device flow to authenticate the person who is behind the config changes. See the Configuration CLI Guide for more info. TUI - The TUI, or Text User Interface, is a menu-based interactive tool that provides a more intuitive experience. When you make changes via the TUI, it also creates a log of the equivalent CLI command, in case you want a shortcut next time around. See the TUI Guide for more info.", "title": "Tools"}, {"location": "janssen-server/auth-server/config/#client-versus-server-configuration", "text": "Some behaviors are controlled at the server level. For example, should your Auth Server allow dynamic client registration? Other features you can configure either at the server or client level. For example, do you want user claims in an id_token ? Maybe you always want them (server), or maybe only sometimes (client). See the JSON Configuration/Properties for an overview of the server level configuration options. For client configuration options, see the Client Schema page.", "title": "Client versus Server Configuration"}, {"location": "janssen-server/auth-server/config/#interception-scripts", "text": "Janssen is a very flexible platform, that lets you customize many of the flows to meet your exact requirements. The black magic behind this flexibility is interception scripts--these are standard programming interfaces that enable you to add or change the behavior of Jans endpoints. Just to give one example, perhaps you need to add data from an external API into an OAuth access token? In this case, you could use the Update Token interception script. There are around 20 of these scripts. For a full list, see the Scripts Documentation .", "title": "Interception Scripts"}, {"location": "janssen-server/auth-server/config/#customization", "text": "You don't want out of the box look and feel provided by Janssen. We know we are UX-challenged, backend developer geeks. Check out the Customization Guide for info about how to add adapt the user facing content to achieve your UX dreams.", "title": "Customization"}, {"location": "janssen-server/auth-server/config/#operations", "text": "Janssen Project software has to run somewhere, right now... either on VM's or in containers. There are specifics instructions about each contained in these docs.", "title": "Operations"}, {"location": "janssen-server/auth-server/config/#database-and-cache", "text": "One of the biggest challenges in running the Janssen Platform is persistence. Make sure you understand how Janssen Project stores your data, or in some cases, caches it.", "title": "Database and Cache"}, {"location": "janssen-server/auth-server/client-management/client-authn/", "tags": ["administration", "client", "authentication"], "text": "Client Authentication # Janssen Server supports authentication at the token endpoint for confidential clients. Confidential clients have to specify a preferred method of authentication during the client registration process. Client authentication is defined by OAuth and OpenID Connect client authentication section and in Metadata section property token_endpoint_auth_method Supported Authentication Methods # List of supported authentication methods are listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration The token_endpoint_auth_methods_supported claim in the response specifies the list of all the supported methods. Authentication Methods # Authentication methods can be broadly categorised in two categories: Shared key based Private( or asymmetric) key based While shared key based authentication is simpler to implement, it is less secure than a private key based authentication. This is primarily because when using shared key based authentication, the client secret is transmitted between the client and the authorization server. This makes the authentication vulnerable to theft attacks. There are more reasons to prefer private key over shared secret as listed in this section Characteristics table below shows side-by-side comparison of various supported authentication methods. Method Secret Not Sent in Clear Signed Only client has secret Expiry Token Binding client_secret_basic client_secret_post client_secret_jwt private_key_jwt tls_client_auth self_signed_tls_client_auth client_secret_basic # Default authentication method for Janssen Server. It authenticates clients using method described in client authentication section of OAuth framework. client_secret_post # client_secret_post method authenticates clients using method described in client authentication section of OAuth framework by adding client credentials in request body. client_secret_jwt # Like client_secret_basic and client_secret_post methods, this method is also based on a shared secret that client receives from Janssen Server. But instead of sending secret back to authorization server everytime, the client creates a JWT using an HMAC SHA algorithm where the shared secret is used as the key. This method is more secure than the client_secret_basic and client_secret_post due to following reasons: Secret which is shared once will never be transmitted again JWT can have expiration time, beyond which the same JWT can not be used. This reduces the time window for replay of the same token in case it is compromised. This method is further described in OpenId Connect specification, section 9 . Client Configuration For Using client_secret_jwt # Janssen Server clients should specify the preferred algorithm for use with this method during client configuration. Algorithms supported by Janssen Server are listed in the response of Janssen Server's well-known configuration endpoint . From the response, the claim token_endpoint_auth_signing_alg_values_supported lists the supported algorithms. To specify preferred algorithm for a client, using Janssen Text-based UI(TUI) , navigate via Auth Server -> Get or add clients -> encryption/signing -> TODO: which exact properties. private_key_jwt # private_key_jwt is private key based method where secret is not shared between client and authorization server. Instead, the client generates an JSON Web Token(JWT) which is shared with the Janssen Server. Upon receiving JWT singned by client's private key, the Janssen Server can validate this JWT using public keys supplied by client at the time of registration. The client can supply public keys in form of JSON Web Key Set(JWKS) or provide a URI where the client publishes its JWKS. Providing JWKS URI is preferred method as it enable easy key rotations without client having to update JWKS manualy. Check jwks and jwks_uri elements in OIDC client metadata section for more details. This authentication method is further described in OpenId Connect specification, section 9 . Janssen server implements signing and encryption mechanism following the guidelines in section 10 of OpenId Connect specification. Clients should choose the algorithm to sign and encrypt JWT as per their security requirements. Security Features Of Private Key Authentication # This method of authentication is more secure than the methods relying on shared key due to following features. Secure Storage : Hardware Security Module(HSM) or Trusted Platform Module(TPM) can be used to securely store private key and sign using it at client side. These modules make it impossible to access private key from outside. Smaller footprint : Unlike shared secret, where client secret resides on authorization server as well as client, the private key only exists on client. This reduced footprint reduces potential risks. Limited Time Validity : JWT can be set to expire after a certain duration. Similarly, client certificates can be made to expire. This makes it harder to execute replay attacks using a compromised token or certificate. Implementation Steps # Below are the high-level steps involved in using private_key_jwt authentication method: Create JWK private key Derive JWK public key for the private key. Public key JWK should be provided to Janssen Server at the time of registration Create JWT header and payload as described in section 9 of specification Sign JWT with a signing algorithm Client code that implements above steps should leverage any of the secure and trusted library that implements these functions. A non-exhaustive list of such libraries can be found at jwt.io . Psudocode implementation for Java based client using nimbus-jose-jwt library can be found here Client Configuration For Using private_key_jwt # Janssen Server clients can specify signing and encryption keys using client configuration. Clients can either specify JWKS as value or as reference URI. To specify JWKS values or reference URI, using Janssen Text-based UI(TUI) , navigate via Auth Server -> Get or add clients -> encryption/signing -> set value for Client JWKS URI or Client JWKS . tls_client_auth # During TLS handshake, the client authenticates with Janssen Server using X.509 certificate that is issued by a Certificate Authority(CA). This is mutual TLS based authentication method. Benefit of using mutual TLS based authentication is that the authorization server binds the token with the certificate. This provides enhanced security where it is possible to check that the token belongs to the intended client. This authentication mechanism is defined in mTLS specification for OAuth2 self_signed_tls_client_auth # Client authenticates with Janssen Server using self signed X.509 certificate during TLS handshake. Use of self-signed certificate removes the dependency of public key infrastructure(PKIX). This is mutual TLS based authentication method. Benefit of using mutual TLS based authentication is that the authorization server binds the token with the certificate. This provides enhanced security where it is possible to check that the token belongs to the intended client. This authentication mechanism is defined in mTLS specification for OAuth2 none # The Client does not authenticate itself at the Token Endpoint, either because it uses only the Implicit Flow (and so does not use the Token Endpoint) or because it is a Public Client with no Client Secret or other authentication mechanism. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Client Authentication"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client-authentication", "text": "Janssen Server supports authentication at the token endpoint for confidential clients. Confidential clients have to specify a preferred method of authentication during the client registration process. Client authentication is defined by OAuth and OpenID Connect client authentication section and in Metadata section property token_endpoint_auth_method", "title": "Client Authentication"}, {"location": "janssen-server/auth-server/client-management/client-authn/#supported-authentication-methods", "text": "List of supported authentication methods are listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration The token_endpoint_auth_methods_supported claim in the response specifies the list of all the supported methods.", "title": "Supported Authentication Methods"}, {"location": "janssen-server/auth-server/client-management/client-authn/#authentication-methods", "text": "Authentication methods can be broadly categorised in two categories: Shared key based Private( or asymmetric) key based While shared key based authentication is simpler to implement, it is less secure than a private key based authentication. This is primarily because when using shared key based authentication, the client secret is transmitted between the client and the authorization server. This makes the authentication vulnerable to theft attacks. There are more reasons to prefer private key over shared secret as listed in this section Characteristics table below shows side-by-side comparison of various supported authentication methods. Method Secret Not Sent in Clear Signed Only client has secret Expiry Token Binding client_secret_basic client_secret_post client_secret_jwt private_key_jwt tls_client_auth self_signed_tls_client_auth", "title": "Authentication Methods"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client_secret_basic", "text": "Default authentication method for Janssen Server. It authenticates clients using method described in client authentication section of OAuth framework.", "title": "client_secret_basic"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client_secret_post", "text": "client_secret_post method authenticates clients using method described in client authentication section of OAuth framework by adding client credentials in request body.", "title": "client_secret_post"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client_secret_jwt", "text": "Like client_secret_basic and client_secret_post methods, this method is also based on a shared secret that client receives from Janssen Server. But instead of sending secret back to authorization server everytime, the client creates a JWT using an HMAC SHA algorithm where the shared secret is used as the key. This method is more secure than the client_secret_basic and client_secret_post due to following reasons: Secret which is shared once will never be transmitted again JWT can have expiration time, beyond which the same JWT can not be used. This reduces the time window for replay of the same token in case it is compromised. This method is further described in OpenId Connect specification, section 9 .", "title": "client_secret_jwt"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client-configuration-for-using-client_secret_jwt", "text": "Janssen Server clients should specify the preferred algorithm for use with this method during client configuration. Algorithms supported by Janssen Server are listed in the response of Janssen Server's well-known configuration endpoint . From the response, the claim token_endpoint_auth_signing_alg_values_supported lists the supported algorithms. To specify preferred algorithm for a client, using Janssen Text-based UI(TUI) , navigate via Auth Server -> Get or add clients -> encryption/signing -> TODO: which exact properties.", "title": "Client Configuration For Using client_secret_jwt"}, {"location": "janssen-server/auth-server/client-management/client-authn/#private_key_jwt", "text": "private_key_jwt is private key based method where secret is not shared between client and authorization server. Instead, the client generates an JSON Web Token(JWT) which is shared with the Janssen Server. Upon receiving JWT singned by client's private key, the Janssen Server can validate this JWT using public keys supplied by client at the time of registration. The client can supply public keys in form of JSON Web Key Set(JWKS) or provide a URI where the client publishes its JWKS. Providing JWKS URI is preferred method as it enable easy key rotations without client having to update JWKS manualy. Check jwks and jwks_uri elements in OIDC client metadata section for more details. This authentication method is further described in OpenId Connect specification, section 9 . Janssen server implements signing and encryption mechanism following the guidelines in section 10 of OpenId Connect specification. Clients should choose the algorithm to sign and encrypt JWT as per their security requirements.", "title": "private_key_jwt"}, {"location": "janssen-server/auth-server/client-management/client-authn/#security-features-of-private-key-authentication", "text": "This method of authentication is more secure than the methods relying on shared key due to following features. Secure Storage : Hardware Security Module(HSM) or Trusted Platform Module(TPM) can be used to securely store private key and sign using it at client side. These modules make it impossible to access private key from outside. Smaller footprint : Unlike shared secret, where client secret resides on authorization server as well as client, the private key only exists on client. This reduced footprint reduces potential risks. Limited Time Validity : JWT can be set to expire after a certain duration. Similarly, client certificates can be made to expire. This makes it harder to execute replay attacks using a compromised token or certificate.", "title": "Security Features Of Private Key Authentication"}, {"location": "janssen-server/auth-server/client-management/client-authn/#implementation-steps", "text": "Below are the high-level steps involved in using private_key_jwt authentication method: Create JWK private key Derive JWK public key for the private key. Public key JWK should be provided to Janssen Server at the time of registration Create JWT header and payload as described in section 9 of specification Sign JWT with a signing algorithm Client code that implements above steps should leverage any of the secure and trusted library that implements these functions. A non-exhaustive list of such libraries can be found at jwt.io . Psudocode implementation for Java based client using nimbus-jose-jwt library can be found here", "title": "Implementation Steps"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client-configuration-for-using-private_key_jwt", "text": "Janssen Server clients can specify signing and encryption keys using client configuration. Clients can either specify JWKS as value or as reference URI. To specify JWKS values or reference URI, using Janssen Text-based UI(TUI) , navigate via Auth Server -> Get or add clients -> encryption/signing -> set value for Client JWKS URI or Client JWKS .", "title": "Client Configuration For Using private_key_jwt"}, {"location": "janssen-server/auth-server/client-management/client-authn/#tls_client_auth", "text": "During TLS handshake, the client authenticates with Janssen Server using X.509 certificate that is issued by a Certificate Authority(CA). This is mutual TLS based authentication method. Benefit of using mutual TLS based authentication is that the authorization server binds the token with the certificate. This provides enhanced security where it is possible to check that the token belongs to the intended client. This authentication mechanism is defined in mTLS specification for OAuth2", "title": "tls_client_auth"}, {"location": "janssen-server/auth-server/client-management/client-authn/#self_signed_tls_client_auth", "text": "Client authenticates with Janssen Server using self signed X.509 certificate during TLS handshake. Use of self-signed certificate removes the dependency of public key infrastructure(PKIX). This is mutual TLS based authentication method. Benefit of using mutual TLS based authentication is that the authorization server binds the token with the certificate. This provides enhanced security where it is possible to check that the token belongs to the intended client. This authentication mechanism is defined in mTLS specification for OAuth2", "title": "self_signed_tls_client_auth"}, {"location": "janssen-server/auth-server/client-management/client-authn/#none", "text": "The Client does not authenticate itself at the Token Endpoint, either because it uses only the Implicit Flow (and so does not use the Token Endpoint) or because it is a Public Client with no Client Secret or other authentication mechanism.", "title": "none"}, {"location": "janssen-server/auth-server/client-management/client-authn/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/client-management/client-configuration/", "tags": ["administration", "client", "configuration"], "text": "Client Configuration # This document covers some important configuration elements of client configuration. How these elements are configured for a client has an impact on aspects like client security. Redirect URI # Redirect URI is the most basic and at times the only parameter needed for registering a client. It is defined in OAuth framework and OpenId Connect specification . The client can register a list of URIs as a value for redirect URI parameter. Redirect URI can be any valid URI . Redirect URI should be an absolute URI . For instance, URI should not have wildcard characters. As recommended here Redirect Regex : Janssen Server enables clients to allow redirect URIs that conform to a regular expression(regex) pattern. While validating redirect URIs received in an incoming request, the Janssen Server first looks at the list of statically registered URI as part of Redirect URIs and then checks if any of the redirect URI from the request matches with the regex provided by the client. Great care should be exercised when using regex to ensure that it accurately matches with the intended patterns only. This feature can be turned on or off via feature flag When using client type as web , the redirect URI generally takes the form of <schema>://<host-name>:<port>/<path> . It must use https schema. The exception to schema rule is made when localhost or loopback ip 127.0.0.1 is used as the hostname. Prefer to use the loopback IP instead of localhost as hostname to facilitate local testing as recommended in OAuth 2.0 native app specification section 8.3 Janssen Server supports all methods of redirection used by native apps . Use of Private-Use URI (or custom URL) is supported by allowing redirect URI to take the form of reverse DNS name, for example, com.example.app . URLs for loopback interface redirection are also supported. When the client registers multiple redirect URIs (Janssen Server accepts a list of URIs separated by space), be aware that Janssen Server will use these, one by one for validation purposes and the validation stops at the first match. If there are multiple registered redirect_uris, and the client is using pairwise subject identifiers, the Client MUST also register a sector_identifier_uri . This is required to keep the pairwise subject identifiers consistent across various domains under the same administrative control. Refer to pairwise algorithm section of OpenId Connect specification for more details. Cryptography # Janssen Server allows clients to configure static set of keys using JWKS or specify a URI as JWKS URI where client is exposing its key set. For client who can host keys and expose a URI, it is recommended to use JWKS URI instead of static JWKS key set. Using JWKS URI enables client to rotate its cryptographic keys without having to change the client configuration on Janssen Server. Available Algorithms for Encryption and Signing # The client can select algorithms for cryptographic and encryption during client configuration. Janssen Server supports a list of algorithms as listed in response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claims that list supported algorithms: id_token_encryption_alg_values_supported id_token_signing_alg_values_supported userinfo_encryption_enc_values_supported userinfo_signing_alg_values_supported userinfo_encryption_alg_values_supported access_token_signing_alg_values_supported request_object_signing_alg_values_supported request_object_encryption_alg_values_supported request_object_encryption_alg_values_supported Recommendations # RSA keys with a minimum 2048 bits if using RSA cryptography Elliptic Curve keys with a minimum of 160 bits if using Elliptic Curve cryptography Client secret should have a minimum of 128 bits if using symmetric key cryptography Sign with PS256 (RSASSA-PSS using SHA-256 and MGF1 with SHA-256) or ES256 (ECDSA using P-256 and SHA-256) Grants # Supported Grant Types # Grant defines how a client interacts with the token endpoint to get the tokens. Janssen Server supports grant types defined by OAuth 2.0, OAuth 2.1, and extension grants defined by other RFCs. A complete list of supported grant types can be found in the response of the Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claim grant_types_supported lists all the supported grant types in the response. Configuring Grant Type For Client # Janssen Server will allow requests from a client with grant types that the client is configured to use. Client can be configured to use or not use certain grant types using CLI or TUI tools. Recommendations For Using Grant Types and Flows # Developers should use the grant types based on the ability of the client to protect the client credentials as well as the security profile of the deployment. If the client software is a server-side component that can securely store the client credentials, such a client is called a confidential client. As opposed to that, if the application requesting access token is entirely running on a browser, where it is not possible to store client credentials securely, such a client is called a public client. Along with the grant type to be used, developers also need to choose which flow should be used to get the required tokens. The table below shows grant types and flows that should be used for various use-cases. Client Type Recommended Grant Type Flow Backend App (Example: batch processes) that need to access its own resources client_credentials Client Credentials Server backend of a web-application needs access token authorization_code Authorization Code Web-application that needs user information via id_token on browser and access token on backend authorization_code Hybrid Flow Browser based single page applications or Mobile applications authorization_code Authorization Code with PKCE Browser based single page applications or Mobile applications that only intend to get id_token - Implicit Flow with Form Post Input constrained devices (Example: TV) urn:ietf:params:oauth:grant-type:device_code Device Flow Highly trusted applications where redirect based flows are not feasible to implement password Resource Owner Password Flow Note Certain grant types should not be used together. For example, implicit flow with hybrid flow. Or using authorization code flow with hybrid flow. This allows a downgrade attack from more secure flow to less secure flow. Pre-authorization # If the OAuth authorization prompt should not be displayed to end users, set this field to True. This is useful for SSO to internal clients (not a third party) where there is no need to prompt the person to approve the release of information. Response Types # Client sends response_type request parameter when sending request to authorization endpoint. Using this parameter, the client informs the authorization server of the desired grant. Response type parameter is defined in the OAuth 2.0 framework. Janssen Server supports response types defined by OAuth 2.0, OAuth 2.1.The complete list of supported response types can be found in the response of the Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claim response_types_supported lists all the supported grant types in the response. When registering client using dynamic client registration, if the response_type parameter is not specified, it'll default to code . Response Type Recommendations # Avoid using response type token . This response type is deprecated by OAuth 2.1. Grant types allowed for a client determines which response types are permitted in authorization requests. Make sure appropriate grant types are configured in Janssen Server client configuration. Janssen Server will reject authorization requests containing response types not permitted for respective client. Client expiration # Client expiration is set based on dynamicRegistrationExpirationTime AS configuration property or otherwise if dcrForbidExpirationTimeInRequest is false then it is set with Dynamic Client Registration Request via lifetime parameter which expected value in seconds. Client also can be cleaned up by inactivity period which is set via cleanUpInactiveClientAfterHoursOfInactivity AS configuration property. By default it has 0 value (which means it is off). Client activity time is tracked/recorded each time client is used for authentication or authorization (date is written in jansLastAccessTime client attribute). Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "Configuration"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#client-configuration", "text": "This document covers some important configuration elements of client configuration. How these elements are configured for a client has an impact on aspects like client security.", "title": "Client Configuration"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#redirect-uri", "text": "Redirect URI is the most basic and at times the only parameter needed for registering a client. It is defined in OAuth framework and OpenId Connect specification . The client can register a list of URIs as a value for redirect URI parameter. Redirect URI can be any valid URI . Redirect URI should be an absolute URI . For instance, URI should not have wildcard characters. As recommended here Redirect Regex : Janssen Server enables clients to allow redirect URIs that conform to a regular expression(regex) pattern. While validating redirect URIs received in an incoming request, the Janssen Server first looks at the list of statically registered URI as part of Redirect URIs and then checks if any of the redirect URI from the request matches with the regex provided by the client. Great care should be exercised when using regex to ensure that it accurately matches with the intended patterns only. This feature can be turned on or off via feature flag When using client type as web , the redirect URI generally takes the form of <schema>://<host-name>:<port>/<path> . It must use https schema. The exception to schema rule is made when localhost or loopback ip 127.0.0.1 is used as the hostname. Prefer to use the loopback IP instead of localhost as hostname to facilitate local testing as recommended in OAuth 2.0 native app specification section 8.3 Janssen Server supports all methods of redirection used by native apps . Use of Private-Use URI (or custom URL) is supported by allowing redirect URI to take the form of reverse DNS name, for example, com.example.app . URLs for loopback interface redirection are also supported. When the client registers multiple redirect URIs (Janssen Server accepts a list of URIs separated by space), be aware that Janssen Server will use these, one by one for validation purposes and the validation stops at the first match. If there are multiple registered redirect_uris, and the client is using pairwise subject identifiers, the Client MUST also register a sector_identifier_uri . This is required to keep the pairwise subject identifiers consistent across various domains under the same administrative control. Refer to pairwise algorithm section of OpenId Connect specification for more details.", "title": "Redirect URI"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#cryptography", "text": "Janssen Server allows clients to configure static set of keys using JWKS or specify a URI as JWKS URI where client is exposing its key set. For client who can host keys and expose a URI, it is recommended to use JWKS URI instead of static JWKS key set. Using JWKS URI enables client to rotate its cryptographic keys without having to change the client configuration on Janssen Server.", "title": "Cryptography"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#available-algorithms-for-encryption-and-signing", "text": "The client can select algorithms for cryptographic and encryption during client configuration. Janssen Server supports a list of algorithms as listed in response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claims that list supported algorithms: id_token_encryption_alg_values_supported id_token_signing_alg_values_supported userinfo_encryption_enc_values_supported userinfo_signing_alg_values_supported userinfo_encryption_alg_values_supported access_token_signing_alg_values_supported request_object_signing_alg_values_supported request_object_encryption_alg_values_supported request_object_encryption_alg_values_supported", "title": "Available Algorithms for Encryption and Signing"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#recommendations", "text": "RSA keys with a minimum 2048 bits if using RSA cryptography Elliptic Curve keys with a minimum of 160 bits if using Elliptic Curve cryptography Client secret should have a minimum of 128 bits if using symmetric key cryptography Sign with PS256 (RSASSA-PSS using SHA-256 and MGF1 with SHA-256) or ES256 (ECDSA using P-256 and SHA-256)", "title": "Recommendations"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#grants", "text": "", "title": "Grants"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#supported-grant-types", "text": "Grant defines how a client interacts with the token endpoint to get the tokens. Janssen Server supports grant types defined by OAuth 2.0, OAuth 2.1, and extension grants defined by other RFCs. A complete list of supported grant types can be found in the response of the Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claim grant_types_supported lists all the supported grant types in the response.", "title": "Supported Grant Types"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#configuring-grant-type-for-client", "text": "Janssen Server will allow requests from a client with grant types that the client is configured to use. Client can be configured to use or not use certain grant types using CLI or TUI tools.", "title": "Configuring Grant Type For Client"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#recommendations-for-using-grant-types-and-flows", "text": "Developers should use the grant types based on the ability of the client to protect the client credentials as well as the security profile of the deployment. If the client software is a server-side component that can securely store the client credentials, such a client is called a confidential client. As opposed to that, if the application requesting access token is entirely running on a browser, where it is not possible to store client credentials securely, such a client is called a public client. Along with the grant type to be used, developers also need to choose which flow should be used to get the required tokens. The table below shows grant types and flows that should be used for various use-cases. Client Type Recommended Grant Type Flow Backend App (Example: batch processes) that need to access its own resources client_credentials Client Credentials Server backend of a web-application needs access token authorization_code Authorization Code Web-application that needs user information via id_token on browser and access token on backend authorization_code Hybrid Flow Browser based single page applications or Mobile applications authorization_code Authorization Code with PKCE Browser based single page applications or Mobile applications that only intend to get id_token - Implicit Flow with Form Post Input constrained devices (Example: TV) urn:ietf:params:oauth:grant-type:device_code Device Flow Highly trusted applications where redirect based flows are not feasible to implement password Resource Owner Password Flow Note Certain grant types should not be used together. For example, implicit flow with hybrid flow. Or using authorization code flow with hybrid flow. This allows a downgrade attack from more secure flow to less secure flow.", "title": "Recommendations For Using Grant Types and Flows"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#pre-authorization", "text": "If the OAuth authorization prompt should not be displayed to end users, set this field to True. This is useful for SSO to internal clients (not a third party) where there is no need to prompt the person to approve the release of information.", "title": "Pre-authorization"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#response-types", "text": "Client sends response_type request parameter when sending request to authorization endpoint. Using this parameter, the client informs the authorization server of the desired grant. Response type parameter is defined in the OAuth 2.0 framework. Janssen Server supports response types defined by OAuth 2.0, OAuth 2.1.The complete list of supported response types can be found in the response of the Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claim response_types_supported lists all the supported grant types in the response. When registering client using dynamic client registration, if the response_type parameter is not specified, it'll default to code .", "title": "Response Types"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#response-type-recommendations", "text": "Avoid using response type token . This response type is deprecated by OAuth 2.1. Grant types allowed for a client determines which response types are permitted in authorization requests. Make sure appropriate grant types are configured in Janssen Server client configuration. Janssen Server will reject authorization requests containing response types not permitted for respective client.", "title": "Response Type Recommendations"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#client-expiration", "text": "Client expiration is set based on dynamicRegistrationExpirationTime AS configuration property or otherwise if dcrForbidExpirationTimeInRequest is false then it is set with Dynamic Client Registration Request via lifetime parameter which expected value in seconds. Client also can be cleaned up by inactivity period which is set via cleanUpInactiveClientAfterHoursOfInactivity AS configuration property. By default it has 0 value (which means it is off). Client activity time is tracked/recorded each time client is used for authentication or authorization (date is written in jansLastAccessTime client attribute). Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "Client expiration"}, {"location": "janssen-server/auth-server/client-management/client-schema/", "tags": ["administration", "client", "schema"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Client Schema"}, {"location": "janssen-server/auth-server/client-management/client-schema/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/client-management/client-schema/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/client-management/client-schema/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/client-management/client-scripts/", "tags": ["administration", "client", "scripts"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Client Scripts"}, {"location": "janssen-server/auth-server/client-management/client-scripts/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/client-management/client-scripts/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/client-management/client-scripts/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/", "tags": ["administration", "client", "sector-identifier"], "text": "Sector Identifier # Janssen Server supports sector identifier URI and pairwise subject IDs for OpenId Connect relying party. As defined in OpenId Connect core specification , the sector identifiers value is used to derive pairwise subject IDs. Janssen Server also supports Sector Identifier URI as part of client configuration. Sector Identifier URI when used with pairwise subject type, enables a group of websites under the same administrative control to receive the same subject identifiers. Sector Identifier URI also allows clients to change the host component of the redirect URI and still keep the subject identifiers unchanged. Configuring Sector Identifier # Janssen Server runs below mentioned checks on value configured for Sector Identifier URI : URI should have a https schema URI should be accessible to Janssen Server and the response should be a valid JSON array of redirect URIs All redirect URI received in response must exist in the list of the redirect URI provided by the client at the registration time Note If the client can not host an endpoint that will be reachable by Sector Identifier URI , then in order to use the pairwise subject IDs, the client must supply a Redirect URI list where URIs have the same host component. The host component value will be used as the sector identifier. Configuration With Pairwise Subject Type # How sector identifier value is used to derive value for the pairwise subject identifier is detailed in the OIDC core specification . Janssen Server allows clients/RPs to set subject type. The public subject type is the default and the client/RP can choose to use the pairwise type. When using TUI, this can be configured from the client configuration screen below: When the pairwise subject type is selected, the value for Sector Identifier URI can be left blank if all redirect URIs have the same host component. If the list of redirect URIs contains multiple host names, providing a Sector Identifier URI is a must. When Sector Identifier URI is provided, the host component of the URI is used as a sector identifier. Configuration Properties # Janssen Server allows customization concerning sector identifiers using the properties below: sectorIdentifierCacheLifetimeInMinutes shareSubjectIdBetweenClientsWithSameSectorId Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Sector Identifiers"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/#sector-identifier", "text": "Janssen Server supports sector identifier URI and pairwise subject IDs for OpenId Connect relying party. As defined in OpenId Connect core specification , the sector identifiers value is used to derive pairwise subject IDs. Janssen Server also supports Sector Identifier URI as part of client configuration. Sector Identifier URI when used with pairwise subject type, enables a group of websites under the same administrative control to receive the same subject identifiers. Sector Identifier URI also allows clients to change the host component of the redirect URI and still keep the subject identifiers unchanged.", "title": "Sector Identifier"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/#configuring-sector-identifier", "text": "Janssen Server runs below mentioned checks on value configured for Sector Identifier URI : URI should have a https schema URI should be accessible to Janssen Server and the response should be a valid JSON array of redirect URIs All redirect URI received in response must exist in the list of the redirect URI provided by the client at the registration time Note If the client can not host an endpoint that will be reachable by Sector Identifier URI , then in order to use the pairwise subject IDs, the client must supply a Redirect URI list where URIs have the same host component. The host component value will be used as the sector identifier.", "title": "Configuring Sector Identifier"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/#configuration-with-pairwise-subject-type", "text": "How sector identifier value is used to derive value for the pairwise subject identifier is detailed in the OIDC core specification . Janssen Server allows clients/RPs to set subject type. The public subject type is the default and the client/RP can choose to use the pairwise type. When using TUI, this can be configured from the client configuration screen below: When the pairwise subject type is selected, the value for Sector Identifier URI can be left blank if all redirect URIs have the same host component. If the list of redirect URIs contains multiple host names, providing a Sector Identifier URI is a must. When Sector Identifier URI is provided, the host component of the URI is used as a sector identifier.", "title": "Configuration With Pairwise Subject Type"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/#configuration-properties", "text": "Janssen Server allows customization concerning sector identifiers using the properties below: sectorIdentifierCacheLifetimeInMinutes shareSubjectIdBetweenClientsWithSameSectorId", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/client-management/software-statements/", "tags": ["administration", "client", "software statements"], "text": "Software Statements # Software Statement is defined by OAuth dynamic client registration RFC 7591 as A digitally signed or MACed JSON Web Token (JWT) that asserts metadata values about the client software. Janssen Server supports usage of software statements during dynamic client registration. Use During Dynamic Client Registration # Janssen Server supports dynamic client registration using software statements. It can be used as software statements or as software statement assertions (SSA) to register client dynamically. Janssen Server also provides SSA endpoint to create and manage SSAs on the server. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Software Statements"}, {"location": "janssen-server/auth-server/client-management/software-statements/#software-statements", "text": "Software Statement is defined by OAuth dynamic client registration RFC 7591 as A digitally signed or MACed JSON Web Token (JWT) that asserts metadata values about the client software. Janssen Server supports usage of software statements during dynamic client registration.", "title": "Software Statements"}, {"location": "janssen-server/auth-server/client-management/software-statements/#use-during-dynamic-client-registration", "text": "Janssen Server supports dynamic client registration using software statements. It can be used as software statements or as software statement assertions (SSA) to register client dynamically. Janssen Server also provides SSA endpoint to create and manage SSAs on the server.", "title": "Use During Dynamic Client Registration"}, {"location": "janssen-server/auth-server/client-management/software-statements/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/crypto/key-generation/", "tags": ["administration", "auth-server", "cryptography", "key generation"], "text": "Key Generation # Generating Cryptographic Keys # The Jans Server is compatible with the Java KeyGenerator to create new cryptographic keys if needed. Backup # Backup jansConfWebKeys attribute data of jansAppConf entity from persistence. Location of this attribute is: o=jans > ou=configuration > ou=jans-auth Backup jans-auth-keys.p12 from /etc/certs/ [N.B] Below if Keystore location is anywhere except /etc/certs/ no need to backup. Key Generate # To get KeyGenerator, run the following command inside the terminal. You can put expiration according to your own policy. For testing purpose we are keeping it 2 days. /opt/jre/bin/java -Dlog4j.defaultInitOverride=true -cp /opt/dist/jans/jans-auth-client-jar-with-dependencies.jar io.jans.as.client.util.KeyGenerator -keystore /etc/certs/jans-auth-keys.p12 -keypasswd <Password> -sig_keys RS256 RS384 -enc_keys RSA1_5 RSA-OAEP -key_ops_type ALL -dnname \"CN=jansAuth CA Certificates\" -expiration 2 > /etc/certs/jans-auth-keys.json Note -key_ops_type ALL parameter which sets purpose of the keys generated by key generator. Possible values are: \"connect\" - connect keys (that is what we already have) \"ssa\" - ssa keys which has expiration set to 50 years (it ignores \"expiration\" parameters) \"all\" - generate both \"connect\" and \"ssa\" keys. Usually should be done during initial setup. Lets see our newly generated crypto keys keytool -list -v -keystore /etc/certs/jans-auth-keys.p12 -storetype pkcs12 -storepass <password> The jans implementation of KeyGenerator accepts the following arguments: Argument Description -dnname DN of certificate issuer -key_length Length of hash key -enc_keys Encryption keys to generate (For example: RSA_OAEP, RSA1_5) -expiration Expiration in days -expiration_hours Expiration in hours -h Show help -key_ops_type Purpose of the key, possible values: connect, ssa, all -keypasswd Key Store password -keystore Key Store file (such as /etc/certs/jans-auth-keys.p12) -sig_keys Signature keys to generate. (For example: RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512) _keyId Key name suffix -test_prop_file Test property file used for test purpose only", "title": "Key Rotation and Generation"}, {"location": "janssen-server/auth-server/crypto/key-generation/#key-generation", "text": "", "title": "Key Generation"}, {"location": "janssen-server/auth-server/crypto/key-generation/#generating-cryptographic-keys", "text": "The Jans Server is compatible with the Java KeyGenerator to create new cryptographic keys if needed.", "title": "Generating Cryptographic Keys"}, {"location": "janssen-server/auth-server/crypto/key-generation/#backup", "text": "Backup jansConfWebKeys attribute data of jansAppConf entity from persistence. Location of this attribute is: o=jans > ou=configuration > ou=jans-auth Backup jans-auth-keys.p12 from /etc/certs/ [N.B] Below if Keystore location is anywhere except /etc/certs/ no need to backup.", "title": "Backup"}, {"location": "janssen-server/auth-server/crypto/key-generation/#key-generate", "text": "To get KeyGenerator, run the following command inside the terminal. You can put expiration according to your own policy. For testing purpose we are keeping it 2 days. /opt/jre/bin/java -Dlog4j.defaultInitOverride=true -cp /opt/dist/jans/jans-auth-client-jar-with-dependencies.jar io.jans.as.client.util.KeyGenerator -keystore /etc/certs/jans-auth-keys.p12 -keypasswd <Password> -sig_keys RS256 RS384 -enc_keys RSA1_5 RSA-OAEP -key_ops_type ALL -dnname \"CN=jansAuth CA Certificates\" -expiration 2 > /etc/certs/jans-auth-keys.json Note -key_ops_type ALL parameter which sets purpose of the keys generated by key generator. Possible values are: \"connect\" - connect keys (that is what we already have) \"ssa\" - ssa keys which has expiration set to 50 years (it ignores \"expiration\" parameters) \"all\" - generate both \"connect\" and \"ssa\" keys. Usually should be done during initial setup. Lets see our newly generated crypto keys keytool -list -v -keystore /etc/certs/jans-auth-keys.p12 -storetype pkcs12 -storepass <password> The jans implementation of KeyGenerator accepts the following arguments: Argument Description -dnname DN of certificate issuer -key_length Length of hash key -enc_keys Encryption keys to generate (For example: RSA_OAEP, RSA1_5) -expiration Expiration in days -expiration_hours Expiration in hours -h Show help -key_ops_type Purpose of the key, possible values: connect, ssa, all -keypasswd Key Store password -keystore Key Store file (such as /etc/certs/jans-auth-keys.p12) -sig_keys Signature keys to generate. (For example: RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512) _keyId Key name suffix -test_prop_file Test property file used for test purpose only", "title": "Key Generate"}, {"location": "janssen-server/auth-server/crypto/key-storage/", "tags": ["administration", "auth-server", "cryptography", "key-storage"], "text": "Overview # A Java KeyStore is a file that contains set of aliases. Every alias can contain private key and public key and certificate (additional property info about owner of they key) or only public key and certificate. KeyStore stores the following type of data: - Private Keys; - Public Keys and Certificates; - Secret Keys. KeyStore are used by follow crypto primitives: - asymetric encryption; - digital signature; - symmetric-key algorithm. Janssen Key Storages # Janssen Key Storages # Janssen KeyStore files contain: - Private Keys; - Public Keys and Certificates. Supported Formats of Key Storages # There is some set of standardized KeyStore formats. Janssen applications use follow KeyStore formats: - JKS : Java KeyStore format (proprietary keystore implementation provided by the SUN provider). KeyStore file extensions: .jks , .keystore , .ks ; - PKCS#12 : Personal Information Exchange Syntax, developed by RSA Security. PKCS #12 defines an archive file format for storing many cryptography objects as a single file. KeyStore file extensions: .pkcs12 , .p12 , .pfx ; - BCFKS : Bouncy Castle FIPS Key Store (BCFKS) format supports storage of certificates and private keys using AES-CCM and PBKDF2 algorithms, providing greater security than the standard JKS and PKCS12 implementations. Support for BCFKS format is implemented, using BCFIPS Crypto Provider (https://www.bouncycastle.org/fips_java_roadmap.html). KeyStore file extensions: .bcfks , bcf , bcfips . Installed KeyStore files # Janssen installs KeyStore files in the directory: /etc/certs . Follow Keystore files are used by Janssen: jans-auth-keys.pkcs12 smtp-keys.pkcs12 . jans-auth-keys.pkcs12 # Here is the example of the file: /etc/certs/jans-auth-keys.pkcs12 (list of entries/aliases). keytool -list -v -storetype PKCS12 -keystore /etc/certs/jans-auth-keys.pkcs12 -storepass gNzpzYj5h8i1 Keystore type: PKCS12 Keystore provider: SUN Your keystore contains 31 entries Alias name: connect_3c83ba3a-7a62-49e7-8478-b6d3e242e549_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a81e8386d6774110b12a292a7185c454359b9b6d67a3f5aef587e9395db04166 Valid from: Thu Aug 17 05:21:05 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 4F:FD:3A:E6:61:D8:8E:0F:61:A4:AA:DE:D7:E4:F4:28:5E:EE:39:20 SHA256: 52:15:67:CE:0B:56:1C:CD:CE:C9:39:4C:11:25:B8:73:13:7F:7F:91:BB:E4:1A:3F:48:8D:B0:DC:01:D0:55:3D Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_45c2ce16-6d5b-47d4-be40-c4da48ba49d3_enc_ecdh-es+a128kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: c6fdff1d75c83e32519a94133f9954de22a2aea4fb20ef669bce2221c08cf21f Valid from: Thu Aug 17 05:21:17 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 02:35:E7:FC:50:47:4A:3A:EA:54:EE:92:CA:75:14:D0:A4:E0:0C:45 SHA256: 19:18:8F:68:68:A2:FE:E2:03:BC:E6:2E:87:24:D4:E9:B0:64:D8:44:7D:32:A1:DE:1C:1B:8E:9A:96:3F:32:5A Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_5365f93a-368d-4643-8708-1f4b31b62d47_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4d561c04da6bbe50ea15720e6c6898d35793e711eabc9eaa02ad7ed9dafa148b Valid from: Thu Aug 17 05:21:14 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: C7:B4:1A:9A:15:59:E6:45:AC:77:C7:1C:E4:7D:F2:01:EC:4B:59:AD SHA256: 75:11:06:F5:74:D7:B4:C4:0A:57:A5:88:AA:91:F9:57:4C:78:BE:D2:68:1F:0E:AF:0B:CA:16:2F:0F:FE:17:EA Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_5b5da374-2ccb-40ca-8544-9338fe7427ff_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 235fc012863b7291c3370978761a2df6a14796cc601b0fec801b84aa7281b116 Valid from: Thu Aug 17 05:21:03 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 17:33:24:FC:C8:F7:0C:10:7B:0A:30:5B:28:6E:30:AC:13:A5:FD:36 SHA256: E5:05:5A:7E:00:93:2E:8B:3E:AE:91:D5:B5:B5:1A:A9:51:37:FE:72:29:02:83:20:F7:6F:BC:BE:D9:FF:23:7E Signature algorithm name: SHA384withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_6218efa5-197e-49f5-919f-769e6d0aaaec_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 304513446352446c48e39017e3044545e0e2a4a71c36899eacfac775606e958d Valid from: Thu Aug 17 05:21:08 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: BE:27:21:18:F4:D4:F6:71:D9:4A:DF:A0:3F:F2:20:76:E1:3E:DD:05 SHA256: 39:FB:09:EC:BD:62:CF:B2:8B:6A:7F:D9:AF:34:64:7C:50:53:E9:E1:14:01:FE:35:B3:B6:03:8D:C6:E3:A3:68 Signature algorithm name: SHA512withECDSA Subject Public Key Algorithm: 521-bit EC (secp521r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_6dbf485d-9d78-49d0-b977-72608ca6b727_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6310f2b2c5fe5e9354d6352140bedf9efe986ed1c44e68d6dda2ccb46038a14c Valid from: Thu Aug 17 05:21:04 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: E1:78:BA:84:C1:9A:9F:6D:FF:32:1B:F4:D9:4E:AE:AE:23:A9:7F:52 SHA256: EF:C9:B8:40:82:E1:16:B2:7B:2C:E9:E4:47:17:5D:C2:AB:D7:AA:16:EE:11:95:19:F7:52:7C:20:E9:3C:82:91 Signature algorithm name: SHA512withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_7325add6-aaa6-4e4c-bfee-968fa7eba793_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ea8c7dfe1d28f4ff9f686f0eccd5b3d06c50d80b4751713cce0052997027c90f Valid from: Thu Aug 17 05:21:10 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 2D:71:05:C2:5C:5A:50:CD:C7:64:42:69:03:8B:BC:66:6F:F7:E3:2A SHA256: C8:DD:E9:2E:49:91:04:25:29:48:6F:CA:01:0B:6F:17:CA:29:01:C5:4D:2B:AF:3F:A3:25:03:16:12:34:5C:48 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_829abf33-03f1-4f35-a42e-bca49f992df4_enc_ecdh-es+a256kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 24c62ce19733ddce99573c073bfa890e29d48fbc4a1b4365748fdc0c420b793a Valid from: Thu Aug 17 05:21:18 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 66:FC:23:8E:08:80:2A:C8:74:08:A5:37:C2:6D:8F:68:AB:23:7E:D3 SHA256: 27:7B:A3:5D:E2:F3:6D:15:52:F8:D0:03:0A:7D:D5:B5:32:B9:4E:93:F1:C3:14:98:CA:98:E9:53:84:45:24:4C Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_87933d28-0523-4bd2-a078-a94e32887b04_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 276ab34dca0e41236756ae0863ebd5e16ea0b209645128f54da0c0dc1c12b64c Valid from: Thu Aug 17 05:21:06 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 53:23:C9:45:4D:D2:29:70:BA:EB:27:EB:83:66:AB:4C:B9:56:9E:83 SHA256: 42:38:33:97:94:ED:58:51:D4:F1:C8:E5:2E:AB:56:05:B0:1D:79:05:33:51:DA:0F:41:E9:E8:59:11:B8:0F:57 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256k1) key (disabled) Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_8d71b86c-5b81-444c-afdf-bb3da4de11e4_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d8344594dfcce15695d56f30178bc2a38bf3d432756bfd15a69242b3348876dd Valid from: Thu Aug 17 05:21:02 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 5D:75:82:47:5F:80:F9:2F:41:48:CF:01:9F:EE:66:0E:71:37:FA:83 SHA256: D1:92:1C:B1:D0:29:B8:23:73:FA:2E:89:11:2D:F1:8F:5E:2E:FE:B0:80:D1:CC:60:1B:B3:46:82:BA:04:9E:4B Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_9574dff8-1f98-421d-91bf-a760a18be2d2_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a92efd444e5ea4ac9cd573aa66746b3b90adf465d20ad1abb25d903619f30d6c Valid from: Thu Aug 17 05:21:11 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 29:CF:94:A6:DF:1E:85:59:A4:C1:62:1F:95:AB:67:31:1B:2D:07:6C SHA256: E5:72:DE:3F:C5:96:63:21:AB:82:B4:64:00:E6:19:9B:2C:B0:6D:7C:C6:8C:3D:5B:21:58:6A:3D:D1:CC:54:0D Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_9f70c848-95b6-48fe-a9e9-79b374848e28_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 46d231ec4e06d52ce1d5a4950f2f91ffc5dd107f5ac7a422225d55fb0004ae26 Valid from: Thu Aug 17 05:21:13 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: A5:82:D0:70:8D:19:A5:5D:DE:4D:CC:52:AE:FB:F4:FF:EF:1A:56:AE SHA256: BB:FA:F0:82:DC:71:84:90:74:C1:33:D9:BC:AE:35:EA:DD:6B:35:95:CE:45:DB:94:E9:9B:E9:39:A4:47:CD:B2 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_a28e886e-090b-42c3-b437-92c91106c0c1_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4f03840af117cdff5a44ae7f12050ead8934d460134a35088ba5cb3782046b9e Valid from: Thu Aug 17 05:21:16 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 24:00:50:A1:B6:FD:F3:EC:19:95:CE:0F:BA:4E:AE:C5:64:57:F7:0C SHA256: BC:02:64:A2:1E:B6:B3:BD:BE:15:8E:E6:8B:CA:1E:00:A0:13:D9:40:72:7E:93:0F:40:DB:58:B5:56:1B:08:54 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_b7920896-d087-4668-9ee5-66fd3cf56694_enc_rsa-oaep-256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 16d9f709786c58f4343b2fce290cafa4130cb706cae25bcc98970742879d6f1d Valid from: Thu Aug 17 05:21:15 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 28:B3:2B:59:0B:BF:DB:F1:05:63:27:C3:9B:CD:35:14:54:A9:A3:16 SHA256: D9:55:37:5E:2E:AE:48:3E:72:DF:39:E2:0B:D8:79:4F:A3:21:33:EF:DA:DF:24:22:8B:42:08:61:E5:7F:F8:9F Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_c50ce977-00c0-4f4a-8594-1a0bc3935f88_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: c1992dccc3c0635dea6f34ac0f03414cc5f2422883dde72e8c07ea3fba66e865 Valid from: Thu Aug 17 05:21:09 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 65:CC:C8:CF:EA:54:C8:2C:27:31:59:34:5E:69:41:CE:09:37:EB:6B SHA256: C0:C8:68:75:BE:C1:CC:9F:4B:19:5E:23:9B:F4:3B:E8:E3:CE:B7:84:35:29:C0:8C:12:63:1E:B4:81:6B:23:99 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_e99b9f12-cbf5-4d5e-9156-12f112d7b4a3_sig_eddsa Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 523b5a9b1edbb4ac08435f1f86c7d810be34535e0bc02b073baeab6d9f35ca75 Valid from: Thu Aug 17 05:21:12 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: EB:D3:5F:54:76:44:D1:01:5F:39:EA:0B:2A:08:FB:30:39:50:E8:CC SHA256: 5F:99:18:AE:47:58:FD:7E:E3:B7:B4:F8:57:4A:5B:68:94:F8:DD:2A:02:DE:F7:58:8B:6A:06:D6:E2:CE:3E:ED Signature algorithm name: 1.3.101.112 Subject Public Key Algorithm: 1.3.101.112 key of unknown size Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_eb5d1996-197c-4913-9b10-201b4f371ff7_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 613554766f456cae0e968ecf8eaedd5fbb0f04c6ff64202c6b51df34cd7b2a20 Valid from: Thu Aug 17 05:21:07 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 50:FF:D2:51:CA:F6:35:31:C8:12:14:13:36:0B:A5:05:F4:08:3F:97 SHA256: 13:13:32:47:2B:5B:E7:20:EC:4B:77:E8:80:78:E0:84:DB:D9:5E:6D:6C:C6:86:5F:B5:6D:18:99:38:02:B0:32 Signature algorithm name: SHA384withECDSA Subject Public Key Algorithm: 384-bit EC (secp384r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_eddc097c-d9bc-4672-a6ec-2740f8ed99c4_enc_ecdh-es+a192kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9755e3a9d7404f86161bdfd47dc0f57021aa598b6f4bde9b3929a1303d66baef Valid from: Thu Aug 17 05:21:18 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 20:1F:EE:29:8F:57:B4:FA:29:E8:3F:D6:DD:60:0C:E7:6C:A6:82:54 SHA256: 6A:69:0F:0F:D0:51:5F:83:29:91:BB:E5:A7:63:48:14:F7:D1:C4:18:EE:4D:F2:28:50:63:18:2D:00:94:C7:F4 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_02674321-5bdc-451e-a8e0-12fbc494ab00_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: b544920f9433a67816ac7e022649057deeecd012b68344683ca92a680496b3dc Valid from: Tue Aug 08 06:57:41 CDT 2023 until: Tue Aug 08 06:57:51 CDT 2073 Certificate fingerprints: SHA1: BC:D6:33:CB:95:28:C1:61:D3:EC:D8:10:79:04:C2:22:B8:AF:93:C3 SHA256: 38:0E:40:94:0F:57:1A:B5:9E:AD:A2:7E:B1:AE:ED:42:4C:60:9F:BE:C3:95:51:2A:8B:39:E8:92:90:1C:57:FD Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_18c82db5-7b1c-4bd4-bbe9-7a4e65045fb4_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 874585304266014b022a0a321c5d4451bb433305b9137a1ddbdff36504e39d45 Valid from: Tue Aug 08 06:57:38 CDT 2023 until: Tue Aug 08 06:57:48 CDT 2073 Certificate fingerprints: SHA1: 56:79:CC:8A:CB:CF:74:40:31:D6:C3:1D:D8:DC:9B:03:EA:2A:80:89 SHA256: 86:12:AF:78:E6:63:68:B7:9E:B7:70:A3:CF:EF:35:35:FF:46:15:18:97:97:A8:1A:17:79:85:F5:99:9E:61:0A Signature algorithm name: SHA384withECDSA Subject Public Key Algorithm: 384-bit EC (secp384r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_45aa4647-b976-44b8-a94d-025ecced0fe9_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4c0fc7cf58866f4beee13c4bf8d12bd084b264f6bedfa484b54034a385d563db Valid from: Tue Aug 08 06:57:45 CDT 2023 until: Tue Aug 08 06:57:55 CDT 2073 Certificate fingerprints: SHA1: 91:48:30:F4:F6:E8:5D:AF:09:79:C2:EC:F9:C6:20:B0:85:3C:02:7E SHA256: 9A:D9:B9:3A:74:AF:99:A9:B2:44:40:1F:8D:E2:C5:72:6E:E3:AA:43:52:A0:8A:1E:61:5A:48:29:57:7E:92:60 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_46f71619-57a9-4c3f-bc15-b91872c828cf_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 1187ed8ad9aa4a985c68ba2e0665665a50c970a06e25697360b0c680bda347a3 Valid from: Tue Aug 08 06:57:37 CDT 2023 until: Tue Aug 08 06:57:47 CDT 2073 Certificate fingerprints: SHA1: 9F:F8:EC:FF:83:8A:35:73:B1:AB:89:FF:39:6C:61:C2:76:24:78:37 SHA256: B5:3C:C6:0B:13:D2:C0:E5:3D:E4:7D:66:B4:DA:AA:B1:6E:23:82:07:57:D9:ED:3B:47:28:91:CE:76:EE:62:64 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_51b7ce59-5b1e-4f24-92d0-57edff831f37_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: e2dd7decf9dd456bddfa2b9800ac47a4e38ac420cf416c0255820851a8041daf Valid from: Tue Aug 08 06:57:39 CDT 2023 until: Tue Aug 08 06:57:49 CDT 2073 Certificate fingerprints: SHA1: A0:F0:F1:30:66:6B:35:DB:31:AB:8D:D3:E5:58:F4:31:F9:0B:60:E8 SHA256: 5F:CF:BB:E8:6E:FE:A9:F3:D0:09:8E:A5:2A:C7:A8:3B:42:CF:2C:A9:59:D9:A2:86:9B:B2:E3:A1:81:D9:BF:2F Signature algorithm name: SHA512withECDSA Subject Public Key Algorithm: 521-bit EC (secp521r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_5b5666f0-8c3c-46db-8e10-190263885d01_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 88d0bbd883c815c46882674a9e0cb82d4c27bc18231177a262aab71b28e1878 Valid from: Tue Aug 08 06:57:37 CDT 2023 until: Tue Aug 08 06:57:47 CDT 2073 Certificate fingerprints: SHA1: E7:6A:0E:37:85:BD:F9:E2:FD:B2:4B:96:A9:3A:97:91:EE:30:91:53 SHA256: 41:AB:78:C1:91:19:BA:03:13:B1:D6:62:27:1D:6E:0B:53:FC:91:AF:DF:E0:6A:17:61:E5:28:D7:AF:26:BA:E1 Signature algorithm name: SHA512withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_64a3d3e3-503c-4574-a544-ea63bab7f637_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 58380f109ee41ec443e0e1655e4009f7c782b4e48203464651b92508e37e8cb1 Valid from: Tue Aug 08 06:57:46 CDT 2023 until: Tue Aug 08 06:57:56 CDT 2073 Certificate fingerprints: SHA1: DF:F5:B0:63:1B:B4:A1:81:28:FF:FB:0E:97:78:49:B1:0F:A7:9F:CA SHA256: 4E:72:58:BB:D6:8E:D1:D1:C8:33:32:2F:58:FA:66:8A:26:1E:10:4F:C3:7F:DD:33:6E:39:38:1F:11:A6:EF:7F Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_9b146bc3-5987-414c-9ed6-7ba735b0ab10_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d62267e39615f334538d64353a48539673b6c8331f3dbb5bdae6b6897541a631 Valid from: Tue Aug 08 06:57:36 CDT 2023 until: Tue Aug 08 06:57:46 CDT 2073 Certificate fingerprints: SHA1: 15:16:97:87:F1:EF:56:12:9E:FB:24:A5:8E:EA:CF:B5:14:9F:81:24 SHA256: 61:C4:F6:D9:8A:54:A9:31:D6:4D:09:B0:D9:0B:36:01:4F:97:53:B8:0D:09:83:01:E3:1B:67:F6:66:F9:05:0B Signature algorithm name: SHA384withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b037a3dc-b4a9-46a6-8b45-66df01da4f0a_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 8decb6c87779103a3915f71963b3c6d6208c7530a6935215b3f7ef6a2832effb Valid from: Tue Aug 08 06:57:39 CDT 2023 until: Tue Aug 08 06:57:49 CDT 2073 Certificate fingerprints: SHA1: 74:9C:1C:D1:D0:15:92:A4:35:38:C7:12:FC:89:D8:19:29:B7:77:EE SHA256: AF:39:10:89:1E:0B:08:2F:AF:C1:D4:F9:13:73:1D:72:C9:6B:27:EF:8A:F0:66:D6:89:BA:27:CB:1A:90:16:EA Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b0b8feac-e048-407c-afc8-44008b4e88cb_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9a20c156e837e5f7d974e6ec9c3da25f30170e775f789c4836d3a00d919fe5e5 Valid from: Tue Aug 08 06:57:36 CDT 2023 until: Tue Aug 08 06:57:46 CDT 2073 Certificate fingerprints: SHA1: 3F:8D:06:04:A6:9F:ED:C1:39:FC:86:40:C4:8C:19:6D:C2:E3:A9:5E SHA256: 3A:1D:39:FC:3C:BD:17:A9:19:A8:45:BB:FD:FE:2A:3A:24:BD:CF:A6:0A:07:17:21:BF:D8:75:84:5E:10:50:16 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b68c6303-e35e-44f0-b300-e9347e3e3305_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9bd61db1532aef6c9efa870ccf8cd39caf227037d82c9c0404ba3c95bff46322 Valid from: Tue Aug 08 06:57:40 CDT 2023 until: Tue Aug 08 06:57:50 CDT 2073 Certificate fingerprints: SHA1: 34:29:CF:02:EF:D0:C9:CF:A3:6C:79:A8:B9:36:D8:6F:CB:6F:4D:02 SHA256: 8B:F9:35:9E:86:1E:0A:1C:BC:2E:7C:BB:C9:50:FD:F3:84:51:F6:E8:92:C6:03:2A:0C:EB:74:0C:7D:93:8C:28 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_cef00de1-5a40-444a-94b4-35d7a290efad_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 845d78edfaf1912519bddcffffa6aaae9253dd1a087c781132686472763314e2 Valid from: Tue Aug 08 06:57:44 CDT 2023 until: Tue Aug 08 06:57:54 CDT 2073 Certificate fingerprints: SHA1: A4:EC:F5:F6:80:A1:51:FE:DD:65:AC:7E:2E:78:C9:0B:FB:82:33:DC SHA256: C9:62:C8:12:CB:C6:6B:96:C6:D4:E4:9B:1D:0A:8A:E8:47:0E:C6:EA:70:E2:CE:DE:06:C8:77:4D:84:3E:32:33 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_cef05e47-6622-43e7-b61d-1209f0dcdf99_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ee31a06bda23b8f5a042295d851018c3502a7a8bcd22e2367226c9b5014699a8 Valid from: Tue Aug 08 06:57:38 CDT 2023 until: Tue Aug 08 06:57:48 CDT 2073 Certificate fingerprints: SHA1: 22:EC:A2:90:AA:1C:73:0C:23:B2:AA:F8:B2:CD:35:C2:A4:10:0E:0E SHA256: F2:B4:3B:93:BA:BF:08:E0:58:30:78:03:8F:C0:60:6A:68:E7:68:7D:00:ED:50:B2:9A:8B:21:C3:9F:71:4A:8A Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256k1) key (disabled) Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* All keys are saved in aliases. Every alias has follow format: KeyOpsType + GUID + Use + Algorithm . Where: - KeyOpsType: values Connect | SSA - Use: sig (signature) | enc (encryption) - Algorithm: if Use == sig follow algorithm values are used: RS256 RS384 RS512 ES256 ES256K ES384 ES512 PS256 PS384 PS512 EdDSA if Use == enc follow algorithm values are used: RSA1_5 RSA-OAEP RSA-OAEP-256 ECDH-ES ECDH-ES+A128KW ECDH-ES+A192KW ECDH-ES+A256KW . This Key Store is used for keys/certificates keeping, which are used by the OpenID provider ( jans-auth-server ). smtp-keys.pkcs12 # Here is the example of the file: /etc/certs/smtp-keys.pkcs12 (list of entries/aliases). keytool -list -v -storetype PKCS12 -keystore /etc/certs/smtp-keys.pkcs12 -storepass 6VkIGu0DhnrD Keystore type: PKCS12 Keystore provider: SUN Your keystore contains 1 entry Alias name: smtp_sig_ec256 Creation date: Aug 8, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=SMTP CA Certificate Issuer: CN=SMTP CA Certificate Serial number: 690675c1 Valid from: Tue Aug 08 06:57:12 CDT 2023 until: Fri Aug 05 06:57:12 CDT 2033 Certificate fingerprints: SHA1: 69:77:F6:3E:44:0C:3A:BE:0D:58:02:71:21:72:39:12:54:DB:D7:88 SHA256: E5:E6:CB:BE:76:62:06:2F:A0:C9:49:0F:DD:0D:B1:D1:5B:D6:A2:2C:11:E1:0B:FE:84:67:B0:9D:EB:9B:3A:ED Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: 94 D2 A8 BC 8C D7 6F E0 EC BF 2D 92 3A 8D E1 CE ......o...-.:... 0010: 3D 71 CB B0 =q.. ] ] ******************************************* ******************************************* This Key Store stores one alias ( smtp_sig_ec256 ) and it is used for keeping of key/certificate, which is used by email sending functionality - signing of emails. Alias smtp_sig_ec256 contains self-signed certificate. User/Admin can update this KeyStore, adding key/certificate signed by trusted certificate authority (CA) (X-509 PKI). BCFKS KeyStore # Janssen also supports BCFKS format of KeyStore. As a rule this format is used on RHEL/DISA-STIG OS. Access to this type of KeyStore is provided by BCFIPS crypto provider. Modules of cryptoprovider can be found (after installing on RHEL/DISA-STIG OS) here: /var/gluu/dist/app/bc-fips-1.0.2.3.jar /var/gluu/dist/app/bcpkix-fips-1.0.6.jar . Here is example of the BCFKS KeyStore /etc/certs/jans-auth-keys.bcfks (list of entries/aliases): keytool -list -v -keystore /etc/certs/jans-auth-keys.bcfks -storetype BCFKS -providerpath /var/gluu/dist/app/bc-fips-1.0.2.3.jar:/var/gluu/dist/app/bcpkix-fips-1.0.6.jar -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -storepass CqE4ApXQxz5y Keystore type: BCFKS Keystore provider: BCFIPS Your keystore contains 30 entries Alias name: connect_01906c9d-fed6-48f1-94b8-85446a692f23_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 3b795840da219a3a7736d0ac0ebc2d632e925dc4b472a02e4b930eb1d5ca278b Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 40:B5:54:85:6B:3B:B1:A9:93:22:6D:91:AA:37:AD:92:A9:B0:5A:A9 SHA256: 06:23:28:01:89:6A:96:EA:A6:3E:EA:27:1D:7C:7A:8A:C7:C9:6D:3F:D0:BF:00:69:35:27:CA:CB:54:75:C6:F1 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_03a3687a-9c3c-4026-abfc-cafef6a76f92_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: df266f1918ae93954aaad44cdceab2ac89be1c20ad16245f1567d751db5d6d1a Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 12:12:0B:15:47:A4:C9:AB:44:4A:00:5E:B3:3A:8E:EE:56:70:6F:A7 SHA256: 11:F8:12:47:17:E6:D1:D4:80:1F:66:72:22:2C:49:93:72:DE:EF:5E:58:40:74:5B:AE:66:C4:96:F5:9C:86:13 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_1b960e55-7b8c-4eeb-9379-b933b8a28fb6_enc_ecdh-es+a128kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ad0cb98a5844cfe6a56c944d269aa3ce6379dc8fea2b0752514753935ae3d821 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 28:8F:83:99:24:8E:97:54:5A:B7:41:BB:28:C5:5E:BE:67:38:AF:F4 SHA256: E5:DE:D0:4A:17:5B:F8:5D:32:E4:8B:E2:E6:24:D6:22:50:D6:2E:E1:D4:ED:AB:9A:AB:74:B8:24:8C:16:97:14 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_4260d824-790d-440e-b2e0-a1a4ab813169_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 28f4866a894a33bb70dcb33138631be67a3b3b2c2b02c31a24913fde2d6d905d Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: CD:2C:FC:D2:81:A7:26:EA:C1:63:66:C4:AF:43:20:F3:E0:10:B7:41 SHA256: F5:3F:81:C5:B4:CD:8B:7D:B1:E4:83:54:DE:B9:88:F5:1B:3E:DA:CD:A5:93:86:D5:21:E5:3B:3D:42:5C:56:E3 Signature algorithm name: SHA512WITHECDSA Subject Public Key Algorithm: 521-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_464cc164-24ec-43c2-9f13-bca1c7faab11_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d4786313f02f3444beabbac0ed6c307db4af29e3f044edd047e976efe48c2337 Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 8A:37:4D:12:F9:24:93:DF:1B:59:90:26:3B:1A:95:5A:F8:46:1E:CB SHA256: B4:28:C6:BC:3D:AA:7C:52:5C:E4:22:FC:E7:E0:94:BF:22:66:91:0F:D6:CF:37:6E:C5:54:ED:0C:30:A8:24:CF Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_53cfa5f1-c227-4843-94d0-e5369cd822b0_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 321e23c27b9ec8a65e7e8fe0e64f68aa7390d713bebfa78b17f8962bb28c1d4f Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 6F:D2:4A:FC:48:1F:F3:B7:CC:13:4B:41:3A:BC:19:C4:85:A9:E9:7C SHA256: 43:80:83:D8:84:75:87:5A:24:D6:6B:AC:EC:0D:45:2E:8F:4A:FC:B4:47:D4:D7:49:E8:06:12:2F:98:7C:91:8F Signature algorithm name: SHA384WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_63e8e482-18ef-410e-bf27-0543a37ac166_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 5fe30fe9ce2b55b6738ec74e0b711c5aa3052ae200fdb9c39bb1392420087d7c Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 1C:27:A5:78:64:EA:01:13:C8:62:D4:4C:93:7A:95:F5:CC:C0:55:BA SHA256: F6:CB:47:52:9D:10:B6:31:FB:C2:1F:CC:30:DD:91:DD:2D:85:C0:44:BB:AB:CA:05:9D:47:05:00:7E:35:73:8B Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_64e35c92-c4f2-4104-81ef-7a366f2dbc38_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6742d9b42e180b7f4a1f58121dddb02896ff1638e8254bd74415a90e47718e91 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 75:AB:EA:2C:D7:C8:87:86:7C:FE:0D:23:33:24:CE:FD:75:3E:E5:E0 SHA256: EA:7D:7F:F1:51:00:5F:D8:80:A5:AF:67:F4:E1:84:A2:E5:D0:0A:8F:A3:98:81:29:36:9B:14:DA:59:02:76:AA Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_71a098e5-0fe0-4946-85f8-adf0d6759413_enc_ecdh-es+a256kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 285d3bcd2569a9a0db6091c184e47bf855edf758251749b739267b7f6f9821d3 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: D6:D7:0C:33:6E:A8:A4:54:2A:1F:2D:59:7D:2C:26:0A:EB:B8:AE:41 SHA256: EC:82:5E:A3:66:99:FB:3E:64:B7:47:27:AA:0D:13:C6:64:E1:42:41:B4:8E:F7:B9:23:20:AA:15:1E:F3:22:F7 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_82a7b334-4756-4201-a432-1b181badf695_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: cce1b501329cff10503a96587042b4f37cc994ac3f98c615bab4c9680a53d769 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 37:1C:A3:F4:A3:04:E4:DC:AA:F3:21:AD:BD:B0:5F:D8:0A:95:7B:29 SHA256: D7:CA:AE:57:A3:43:1E:94:93:ED:C8:34:72:29:DD:CE:02:BD:E5:69:6D:34:D3:7D:26:AE:78:19:4C:E9:BF:CE Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_a3d528cf-fd43-4015-92be-1e644310bbf0_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: de13b1e646dd2456c3512de303b2fb272108bcdb40c180717077820c07e32f65 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: EF:5E:62:AA:89:31:70:83:35:40:CB:9E:30:23:32:21:12:77:DC:83 SHA256: 88:1A:A2:85:DB:27:46:04:EE:E5:DC:8A:5E:A7:77:CC:36:C5:A6:1A:E7:A1:85:44:2E:E4:A0:91:8A:FD:A4:6F Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_ab2f67de-14fb-4312-89fa-56b2cd70f616_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d36755d2a472837ab9fe1dad688b5a1881bff6073d5a494af0275226f236146c Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 8B:FD:A9:75:7C:33:1E:9D:03:47:58:2E:31:D6:49:30:E6:65:6B:A7 SHA256: 5C:E2:28:7B:B0:66:17:A8:14:82:49:14:16:E8:40:B3:B6:C1:5F:90:77:25:A3:C4:A5:25:E6:77:CB:B9:92:91 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_ae7adf42-8f9b-4fe0-bbf1-e9e1016904f5_enc_rsa-oaep-256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 324a9b70a8410e9a02eb596e536cda516f91b250befb22699a909d0b2505e03 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 66:CF:B6:EB:27:10:CC:45:E4:CF:8A:66:71:05:97:22:BA:47:6B:33 SHA256: EF:16:46:1F:C5:0B:41:0B:B4:06:A7:9D:7F:EB:81:76:5F:35:B3:E4:09:67:95:D2:2A:10:D3:2F:59:DA:5D:73 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_b52de13d-33fe-446f-b4fa-6b4ce816c18e_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4d4b22cacdd15cd7bbf339c18ef14fba4ba7b0f13ad37f9452e00404488a880c Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 47:03:76:16:4B:D9:5C:83:AC:C7:40:10:F3:46:72:86:15:21:6C:CD SHA256: A3:3A:22:75:E2:E5:5B:69:31:FB:E8:59:E0:90:20:60:BC:47:30:9C:5C:5A:B6:97:92:37:71:CD:91:BF:93:78 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_c82cc876-6e92-408c-b519-76d153aad42d_enc_ecdh-es+a192kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 586b7dd9cecd3ef8c58b1bac766caec5d4c2ac8097c1cc4a22a20905ce5f9229 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: E6:3E:62:82:3C:6F:FE:CF:85:FD:6D:82:A9:7D:68:03:38:F0:AB:63 SHA256: 0D:D0:1B:50:02:0B:41:C1:35:CD:A9:7A:E5:10:AA:88:F2:AD:F7:8E:88:C2:3F:68:A9:33:E6:1B:EB:28:71:30 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_d1001a39-29a1-45e4-ae0d-2eee86a83ada_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ba44ac71c5a340aec0d8e0078b059c36a2819915774e8403e1b589a330570833 Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 49:59:6A:9D:D6:E6:98:05:18:BD:25:1A:C5:C0:2B:A6:C3:3E:36:52 SHA256: DA:57:65:45:A2:16:76:E0:B7:20:DA:82:BF:77:AF:B9:58:D5:E7:D3:2F:1B:D3:BC:48:51:E2:D1:C2:41:A9:FA Signature algorithm name: SHA512WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_f32a5790-4e43-4629-95bd-37b35d7c2e39_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9f0340f5c5cafc1816d2a31c20846fb24d400b3b5194a629ac5baf6db6d15e60 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 5A:37:CA:6A:27:AB:9F:FC:6B:C3:D3:C6:B4:47:F3:10:F4:C9:F3:B3 SHA256: 11:A4:9C:ED:C0:05:B9:27:89:2B:17:52:11:AA:34:B4:E7:81:08:13:44:7D:93:3A:DE:CA:23:A4:22:F7:05:9F Signature algorithm name: SHA384WITHECDSA Subject Public Key Algorithm: 384-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_0639ba94-902c-4ab6-923a-58137554f667_enc_ecdh-es Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6fac3869f3fc7297470eee65fc4315328edaf475798d5bbc469de652f3088ca3 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: 76:B5:F0:B9:1C:88:54:95:5B:11:2A:6A:AE:2E:C3:02:59:1B:07:2C SHA256: 7B:26:2E:36:4B:27:AA:C0:5B:FE:2C:2E:73:B1:75:64:2D:3E:0B:D2:C4:8D:F6:63:12:E8:2E:4C:46:EB:35:4C Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_0d94f183-878c-445d-9917-28357b15c4ee_sig_rs256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6d76a82ed166e13ecc2fb0742ebc72f619af0b738baf69438d2aba4262cfdbc4 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 14:8E:19:D8:8D:FD:68:14:40:72:35:1F:93:2A:7D:83:81:7E:6C:D8 SHA256: CB:69:E0:7C:55:2C:39:56:F8:17:ED:72:96:47:DB:8C:90:1A:1E:2A:E8:33:CA:79:96:DD:44:9F:F7:63:A2:D4 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_1a5ea0d5-0c70-43d2-ab23-e324620b413b_sig_ps512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 42bd6fbc27749cd6598c54aa0928e93057dc6c6c083c9f73d4e2046c4bac02d0 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: D3:D1:31:59:33:D1:A6:86:8F:A5:F8:7F:D6:15:44:53:15:99:6D:DC SHA256: 88:95:8C:89:F3:E7:28:E8:3D:9F:47:39:E2:F8:F5:FC:FA:63:71:B3:81:F0:9C:98:7E:A4:0A:FD:7E:7E:E9:AD Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_20d8cce9-0994-4fca-9cfa-f5fbe22eb940_sig_es256k Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a192c3ca749b78a153cb3134c50fddcdd5dd401dd399b831199ba383eddf355b Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 4E:94:55:21:15:53:1E:3E:3B:6E:85:B9:BF:A7:4B:46:2A:FB:09:4F SHA256: BA:AB:58:DF:29:7C:5A:D5:31:2F:B9:8B:CE:E9:3F:0B:5B:E5:01:94:CC:A8:9B:41:8B:45:9B:30:D2:63:D6:24 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_33b1591d-1b79-490f-a980-573486ec620b_sig_es384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ba8a0e96843f1a5181a96d2fc1bdae8b6954bb70b2b5c1fad4895438f4079dd0 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: B8:97:F4:EA:85:14:41:24:8C:DC:E0:8F:66:18:FD:31:7E:0B:5D:D5 SHA256: F3:9E:1F:25:E2:03:3C:7B:69:15:12:01:E2:94:EF:1E:95:43:43:A2:CB:8E:88:88:8A:3D:53:5E:82:E9:0E:9C Signature algorithm name: SHA384WITHECDSA Subject Public Key Algorithm: 384-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_34943497-d9fb-43ca-8ee1-1437e1dcf78e_sig_ps384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: b45de18f13366f309b100be313770edc6e80942771b08d656e699f7e081e5a69 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: C4:2D:DB:4D:06:7F:27:89:9A:C0:84:DB:08:BF:0C:75:3B:5B:74:22 SHA256: 77:07:D2:90:7C:AD:7A:F1:D8:EE:C1:84:54:B6:E5:41:7B:BB:C7:8F:64:96:D4:D3:ED:FD:32:F3:6C:10:11:62 Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_475830af-d019-4e04-9fb9-e68f0491284a_sig_es512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 69e6093118ce51ec5f21477e2946dd023f3c5b70bbde2922b26139b653eddd62 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 30:9D:95:9C:AE:60:F9:3F:D8:7A:AD:89:9D:AC:5D:7F:05:52:F9:50 SHA256: CA:90:7B:75:3C:99:CE:F2:42:DE:55:38:83:CB:C2:EA:F8:E7:0D:2B:00:5F:57:CF:75:D5:33:C4:5E:32:7E:A7 Signature algorithm name: SHA512WITHECDSA Subject Public Key Algorithm: 521-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_59bb3fe7-bf2a-4244-85a7-dd18785bcac6_enc_rsa-oaep Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 7f3e4adf1e08994ba83a1a59584c6f402e584baaecf1735ff9e0add33d65a423 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: FC:D7:45:92:F4:60:73:C6:7C:19:DA:AB:EC:54:FF:B4:62:C6:AC:CB SHA256: 66:05:C9:4C:3D:CA:EC:9F:29:06:57:00:A8:90:09:24:17:41:71:DC:1F:8E:7F:E7:5B:39:D8:A1:8B:A3:5A:F2 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_5e0f07d5-1e91-4bd3-bf56-6caa8a137ea6_enc_rsa1_5 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 3449c41d6f7c1b5b7f33c7411a81f41883f6f1fccb64d4e2bc22c130d771a26a Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: 1F:55:2E:62:3D:7E:FE:92:20:13:0D:FC:33:F8:82:B1:B7:BF:9E:7A SHA256: C9:6E:48:AF:F7:8B:04:30:FB:4B:30:47:A2:83:1E:4C:AF:9E:04:E6:07:8A:B1:AE:3B:CD:92:AE:CB:97:D2:EB Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_7d9cec29-697e-4e3e-9991-eba03394b69c_sig_ps256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 15e7eed8194a80919e9bd699212efca7e50ec9aa3834c6a8e32a7eeb9d9e1da9 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: A5:BE:24:97:EB:F5:0F:18:05:56:02:BF:66:24:98:24:59:82:5A:E6 SHA256: 16:EF:DD:45:17:3B:D7:66:36:14:7E:96:03:1F:51:02:6C:86:1E:19:E7:43:C7:DF:E9:A9:D0:86:9C:A6:7C:B8 Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_96ea824f-f915-4da8-8f76-3b4bf8bdf552_sig_rs384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4c79afa5d03e2aaab17c90519d59dec517de004f4c9b62960ebf10276b699105 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: E8:F3:5D:16:D0:2C:47:98:D4:F6:98:A1:5F:46:A0:DB:BD:F8:72:30 SHA256: 15:42:A4:30:FE:DB:D8:C4:61:11:A6:8D:10:51:02:64:70:C7:EA:BF:F3:C8:F3:42:03:D9:F8:00:19:F9:7C:28 Signature algorithm name: SHA384WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_b7ee7e46-0a6b-4040-b6b3-a78e9dedc116_sig_rs512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 82f95026558b89f3ca8c1129d3b79c74ce2ff70bb849991a8305afea974ebe1c Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: D8:45:78:27:94:39:93:57:DF:67:56:3B:06:5C:0C:2A:20:93:F6:0F SHA256: 6D:55:8E:F3:5F:6A:EA:6D:37:71:A9:57:1D:32:98:92:04:5E:8B:4A:C4:FC:E1:ED:B1:7A:D4:11:BF:38:02:80 Signature algorithm name: SHA512WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_b9d65217-ff51-4eab-914f-aeb40eb30bc2_sig_es256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 632a5f6e2bf5c5dbabf7376718c35b3101fe8a8065a6bf54db3dde5a1825dbf4 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 7D:51:C1:44:45:EF:6B:71:3D:EF:BC:20:E0:AE:59:4C:3D:16:10:23 SHA256: CC:1C:60:5E:E4:6A:B4:C4:7F:3F:2D:1B:2F:12:B4:79:27:94:3D:1D:D5:FA:C4:11:0E:53:76:DA:52:34:B0:62 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* .", "title": "Key Storage"}, {"location": "janssen-server/auth-server/crypto/key-storage/#overview", "text": "A Java KeyStore is a file that contains set of aliases. Every alias can contain private key and public key and certificate (additional property info about owner of they key) or only public key and certificate. KeyStore stores the following type of data: - Private Keys; - Public Keys and Certificates; - Secret Keys. KeyStore are used by follow crypto primitives: - asymetric encryption; - digital signature; - symmetric-key algorithm.", "title": "Overview"}, {"location": "janssen-server/auth-server/crypto/key-storage/#janssen-key-storages", "text": "", "title": "Janssen Key Storages"}, {"location": "janssen-server/auth-server/crypto/key-storage/#janssen-key-storages_1", "text": "Janssen KeyStore files contain: - Private Keys; - Public Keys and Certificates.", "title": "Janssen Key Storages"}, {"location": "janssen-server/auth-server/crypto/key-storage/#supported-formats-of-key-storages", "text": "There is some set of standardized KeyStore formats. Janssen applications use follow KeyStore formats: - JKS : Java KeyStore format (proprietary keystore implementation provided by the SUN provider). KeyStore file extensions: .jks , .keystore , .ks ; - PKCS#12 : Personal Information Exchange Syntax, developed by RSA Security. PKCS #12 defines an archive file format for storing many cryptography objects as a single file. KeyStore file extensions: .pkcs12 , .p12 , .pfx ; - BCFKS : Bouncy Castle FIPS Key Store (BCFKS) format supports storage of certificates and private keys using AES-CCM and PBKDF2 algorithms, providing greater security than the standard JKS and PKCS12 implementations. Support for BCFKS format is implemented, using BCFIPS Crypto Provider (https://www.bouncycastle.org/fips_java_roadmap.html). KeyStore file extensions: .bcfks , bcf , bcfips .", "title": "Supported Formats of Key Storages"}, {"location": "janssen-server/auth-server/crypto/key-storage/#installed-keystore-files", "text": "Janssen installs KeyStore files in the directory: /etc/certs . Follow Keystore files are used by Janssen: jans-auth-keys.pkcs12 smtp-keys.pkcs12 .", "title": "Installed KeyStore files"}, {"location": "janssen-server/auth-server/crypto/key-storage/#jans-auth-keyspkcs12", "text": "Here is the example of the file: /etc/certs/jans-auth-keys.pkcs12 (list of entries/aliases). keytool -list -v -storetype PKCS12 -keystore /etc/certs/jans-auth-keys.pkcs12 -storepass gNzpzYj5h8i1 Keystore type: PKCS12 Keystore provider: SUN Your keystore contains 31 entries Alias name: connect_3c83ba3a-7a62-49e7-8478-b6d3e242e549_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a81e8386d6774110b12a292a7185c454359b9b6d67a3f5aef587e9395db04166 Valid from: Thu Aug 17 05:21:05 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 4F:FD:3A:E6:61:D8:8E:0F:61:A4:AA:DE:D7:E4:F4:28:5E:EE:39:20 SHA256: 52:15:67:CE:0B:56:1C:CD:CE:C9:39:4C:11:25:B8:73:13:7F:7F:91:BB:E4:1A:3F:48:8D:B0:DC:01:D0:55:3D Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_45c2ce16-6d5b-47d4-be40-c4da48ba49d3_enc_ecdh-es+a128kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: c6fdff1d75c83e32519a94133f9954de22a2aea4fb20ef669bce2221c08cf21f Valid from: Thu Aug 17 05:21:17 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 02:35:E7:FC:50:47:4A:3A:EA:54:EE:92:CA:75:14:D0:A4:E0:0C:45 SHA256: 19:18:8F:68:68:A2:FE:E2:03:BC:E6:2E:87:24:D4:E9:B0:64:D8:44:7D:32:A1:DE:1C:1B:8E:9A:96:3F:32:5A Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_5365f93a-368d-4643-8708-1f4b31b62d47_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4d561c04da6bbe50ea15720e6c6898d35793e711eabc9eaa02ad7ed9dafa148b Valid from: Thu Aug 17 05:21:14 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: C7:B4:1A:9A:15:59:E6:45:AC:77:C7:1C:E4:7D:F2:01:EC:4B:59:AD SHA256: 75:11:06:F5:74:D7:B4:C4:0A:57:A5:88:AA:91:F9:57:4C:78:BE:D2:68:1F:0E:AF:0B:CA:16:2F:0F:FE:17:EA Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_5b5da374-2ccb-40ca-8544-9338fe7427ff_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 235fc012863b7291c3370978761a2df6a14796cc601b0fec801b84aa7281b116 Valid from: Thu Aug 17 05:21:03 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 17:33:24:FC:C8:F7:0C:10:7B:0A:30:5B:28:6E:30:AC:13:A5:FD:36 SHA256: E5:05:5A:7E:00:93:2E:8B:3E:AE:91:D5:B5:B5:1A:A9:51:37:FE:72:29:02:83:20:F7:6F:BC:BE:D9:FF:23:7E Signature algorithm name: SHA384withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_6218efa5-197e-49f5-919f-769e6d0aaaec_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 304513446352446c48e39017e3044545e0e2a4a71c36899eacfac775606e958d Valid from: Thu Aug 17 05:21:08 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: BE:27:21:18:F4:D4:F6:71:D9:4A:DF:A0:3F:F2:20:76:E1:3E:DD:05 SHA256: 39:FB:09:EC:BD:62:CF:B2:8B:6A:7F:D9:AF:34:64:7C:50:53:E9:E1:14:01:FE:35:B3:B6:03:8D:C6:E3:A3:68 Signature algorithm name: SHA512withECDSA Subject Public Key Algorithm: 521-bit EC (secp521r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_6dbf485d-9d78-49d0-b977-72608ca6b727_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6310f2b2c5fe5e9354d6352140bedf9efe986ed1c44e68d6dda2ccb46038a14c Valid from: Thu Aug 17 05:21:04 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: E1:78:BA:84:C1:9A:9F:6D:FF:32:1B:F4:D9:4E:AE:AE:23:A9:7F:52 SHA256: EF:C9:B8:40:82:E1:16:B2:7B:2C:E9:E4:47:17:5D:C2:AB:D7:AA:16:EE:11:95:19:F7:52:7C:20:E9:3C:82:91 Signature algorithm name: SHA512withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_7325add6-aaa6-4e4c-bfee-968fa7eba793_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ea8c7dfe1d28f4ff9f686f0eccd5b3d06c50d80b4751713cce0052997027c90f Valid from: Thu Aug 17 05:21:10 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 2D:71:05:C2:5C:5A:50:CD:C7:64:42:69:03:8B:BC:66:6F:F7:E3:2A SHA256: C8:DD:E9:2E:49:91:04:25:29:48:6F:CA:01:0B:6F:17:CA:29:01:C5:4D:2B:AF:3F:A3:25:03:16:12:34:5C:48 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_829abf33-03f1-4f35-a42e-bca49f992df4_enc_ecdh-es+a256kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 24c62ce19733ddce99573c073bfa890e29d48fbc4a1b4365748fdc0c420b793a Valid from: Thu Aug 17 05:21:18 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 66:FC:23:8E:08:80:2A:C8:74:08:A5:37:C2:6D:8F:68:AB:23:7E:D3 SHA256: 27:7B:A3:5D:E2:F3:6D:15:52:F8:D0:03:0A:7D:D5:B5:32:B9:4E:93:F1:C3:14:98:CA:98:E9:53:84:45:24:4C Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_87933d28-0523-4bd2-a078-a94e32887b04_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 276ab34dca0e41236756ae0863ebd5e16ea0b209645128f54da0c0dc1c12b64c Valid from: Thu Aug 17 05:21:06 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 53:23:C9:45:4D:D2:29:70:BA:EB:27:EB:83:66:AB:4C:B9:56:9E:83 SHA256: 42:38:33:97:94:ED:58:51:D4:F1:C8:E5:2E:AB:56:05:B0:1D:79:05:33:51:DA:0F:41:E9:E8:59:11:B8:0F:57 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256k1) key (disabled) Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_8d71b86c-5b81-444c-afdf-bb3da4de11e4_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d8344594dfcce15695d56f30178bc2a38bf3d432756bfd15a69242b3348876dd Valid from: Thu Aug 17 05:21:02 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 5D:75:82:47:5F:80:F9:2F:41:48:CF:01:9F:EE:66:0E:71:37:FA:83 SHA256: D1:92:1C:B1:D0:29:B8:23:73:FA:2E:89:11:2D:F1:8F:5E:2E:FE:B0:80:D1:CC:60:1B:B3:46:82:BA:04:9E:4B Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_9574dff8-1f98-421d-91bf-a760a18be2d2_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a92efd444e5ea4ac9cd573aa66746b3b90adf465d20ad1abb25d903619f30d6c Valid from: Thu Aug 17 05:21:11 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 29:CF:94:A6:DF:1E:85:59:A4:C1:62:1F:95:AB:67:31:1B:2D:07:6C SHA256: E5:72:DE:3F:C5:96:63:21:AB:82:B4:64:00:E6:19:9B:2C:B0:6D:7C:C6:8C:3D:5B:21:58:6A:3D:D1:CC:54:0D Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_9f70c848-95b6-48fe-a9e9-79b374848e28_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 46d231ec4e06d52ce1d5a4950f2f91ffc5dd107f5ac7a422225d55fb0004ae26 Valid from: Thu Aug 17 05:21:13 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: A5:82:D0:70:8D:19:A5:5D:DE:4D:CC:52:AE:FB:F4:FF:EF:1A:56:AE SHA256: BB:FA:F0:82:DC:71:84:90:74:C1:33:D9:BC:AE:35:EA:DD:6B:35:95:CE:45:DB:94:E9:9B:E9:39:A4:47:CD:B2 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_a28e886e-090b-42c3-b437-92c91106c0c1_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4f03840af117cdff5a44ae7f12050ead8934d460134a35088ba5cb3782046b9e Valid from: Thu Aug 17 05:21:16 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 24:00:50:A1:B6:FD:F3:EC:19:95:CE:0F:BA:4E:AE:C5:64:57:F7:0C SHA256: BC:02:64:A2:1E:B6:B3:BD:BE:15:8E:E6:8B:CA:1E:00:A0:13:D9:40:72:7E:93:0F:40:DB:58:B5:56:1B:08:54 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_b7920896-d087-4668-9ee5-66fd3cf56694_enc_rsa-oaep-256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 16d9f709786c58f4343b2fce290cafa4130cb706cae25bcc98970742879d6f1d Valid from: Thu Aug 17 05:21:15 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 28:B3:2B:59:0B:BF:DB:F1:05:63:27:C3:9B:CD:35:14:54:A9:A3:16 SHA256: D9:55:37:5E:2E:AE:48:3E:72:DF:39:E2:0B:D8:79:4F:A3:21:33:EF:DA:DF:24:22:8B:42:08:61:E5:7F:F8:9F Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_c50ce977-00c0-4f4a-8594-1a0bc3935f88_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: c1992dccc3c0635dea6f34ac0f03414cc5f2422883dde72e8c07ea3fba66e865 Valid from: Thu Aug 17 05:21:09 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 65:CC:C8:CF:EA:54:C8:2C:27:31:59:34:5E:69:41:CE:09:37:EB:6B SHA256: C0:C8:68:75:BE:C1:CC:9F:4B:19:5E:23:9B:F4:3B:E8:E3:CE:B7:84:35:29:C0:8C:12:63:1E:B4:81:6B:23:99 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_e99b9f12-cbf5-4d5e-9156-12f112d7b4a3_sig_eddsa Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 523b5a9b1edbb4ac08435f1f86c7d810be34535e0bc02b073baeab6d9f35ca75 Valid from: Thu Aug 17 05:21:12 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: EB:D3:5F:54:76:44:D1:01:5F:39:EA:0B:2A:08:FB:30:39:50:E8:CC SHA256: 5F:99:18:AE:47:58:FD:7E:E3:B7:B4:F8:57:4A:5B:68:94:F8:DD:2A:02:DE:F7:58:8B:6A:06:D6:E2:CE:3E:ED Signature algorithm name: 1.3.101.112 Subject Public Key Algorithm: 1.3.101.112 key of unknown size Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_eb5d1996-197c-4913-9b10-201b4f371ff7_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 613554766f456cae0e968ecf8eaedd5fbb0f04c6ff64202c6b51df34cd7b2a20 Valid from: Thu Aug 17 05:21:07 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 50:FF:D2:51:CA:F6:35:31:C8:12:14:13:36:0B:A5:05:F4:08:3F:97 SHA256: 13:13:32:47:2B:5B:E7:20:EC:4B:77:E8:80:78:E0:84:DB:D9:5E:6D:6C:C6:86:5F:B5:6D:18:99:38:02:B0:32 Signature algorithm name: SHA384withECDSA Subject Public Key Algorithm: 384-bit EC (secp384r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_eddc097c-d9bc-4672-a6ec-2740f8ed99c4_enc_ecdh-es+a192kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9755e3a9d7404f86161bdfd47dc0f57021aa598b6f4bde9b3929a1303d66baef Valid from: Thu Aug 17 05:21:18 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 20:1F:EE:29:8F:57:B4:FA:29:E8:3F:D6:DD:60:0C:E7:6C:A6:82:54 SHA256: 6A:69:0F:0F:D0:51:5F:83:29:91:BB:E5:A7:63:48:14:F7:D1:C4:18:EE:4D:F2:28:50:63:18:2D:00:94:C7:F4 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_02674321-5bdc-451e-a8e0-12fbc494ab00_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: b544920f9433a67816ac7e022649057deeecd012b68344683ca92a680496b3dc Valid from: Tue Aug 08 06:57:41 CDT 2023 until: Tue Aug 08 06:57:51 CDT 2073 Certificate fingerprints: SHA1: BC:D6:33:CB:95:28:C1:61:D3:EC:D8:10:79:04:C2:22:B8:AF:93:C3 SHA256: 38:0E:40:94:0F:57:1A:B5:9E:AD:A2:7E:B1:AE:ED:42:4C:60:9F:BE:C3:95:51:2A:8B:39:E8:92:90:1C:57:FD Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_18c82db5-7b1c-4bd4-bbe9-7a4e65045fb4_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 874585304266014b022a0a321c5d4451bb433305b9137a1ddbdff36504e39d45 Valid from: Tue Aug 08 06:57:38 CDT 2023 until: Tue Aug 08 06:57:48 CDT 2073 Certificate fingerprints: SHA1: 56:79:CC:8A:CB:CF:74:40:31:D6:C3:1D:D8:DC:9B:03:EA:2A:80:89 SHA256: 86:12:AF:78:E6:63:68:B7:9E:B7:70:A3:CF:EF:35:35:FF:46:15:18:97:97:A8:1A:17:79:85:F5:99:9E:61:0A Signature algorithm name: SHA384withECDSA Subject Public Key Algorithm: 384-bit EC (secp384r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_45aa4647-b976-44b8-a94d-025ecced0fe9_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4c0fc7cf58866f4beee13c4bf8d12bd084b264f6bedfa484b54034a385d563db Valid from: Tue Aug 08 06:57:45 CDT 2023 until: Tue Aug 08 06:57:55 CDT 2073 Certificate fingerprints: SHA1: 91:48:30:F4:F6:E8:5D:AF:09:79:C2:EC:F9:C6:20:B0:85:3C:02:7E SHA256: 9A:D9:B9:3A:74:AF:99:A9:B2:44:40:1F:8D:E2:C5:72:6E:E3:AA:43:52:A0:8A:1E:61:5A:48:29:57:7E:92:60 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_46f71619-57a9-4c3f-bc15-b91872c828cf_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 1187ed8ad9aa4a985c68ba2e0665665a50c970a06e25697360b0c680bda347a3 Valid from: Tue Aug 08 06:57:37 CDT 2023 until: Tue Aug 08 06:57:47 CDT 2073 Certificate fingerprints: SHA1: 9F:F8:EC:FF:83:8A:35:73:B1:AB:89:FF:39:6C:61:C2:76:24:78:37 SHA256: B5:3C:C6:0B:13:D2:C0:E5:3D:E4:7D:66:B4:DA:AA:B1:6E:23:82:07:57:D9:ED:3B:47:28:91:CE:76:EE:62:64 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_51b7ce59-5b1e-4f24-92d0-57edff831f37_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: e2dd7decf9dd456bddfa2b9800ac47a4e38ac420cf416c0255820851a8041daf Valid from: Tue Aug 08 06:57:39 CDT 2023 until: Tue Aug 08 06:57:49 CDT 2073 Certificate fingerprints: SHA1: A0:F0:F1:30:66:6B:35:DB:31:AB:8D:D3:E5:58:F4:31:F9:0B:60:E8 SHA256: 5F:CF:BB:E8:6E:FE:A9:F3:D0:09:8E:A5:2A:C7:A8:3B:42:CF:2C:A9:59:D9:A2:86:9B:B2:E3:A1:81:D9:BF:2F Signature algorithm name: SHA512withECDSA Subject Public Key Algorithm: 521-bit EC (secp521r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_5b5666f0-8c3c-46db-8e10-190263885d01_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 88d0bbd883c815c46882674a9e0cb82d4c27bc18231177a262aab71b28e1878 Valid from: Tue Aug 08 06:57:37 CDT 2023 until: Tue Aug 08 06:57:47 CDT 2073 Certificate fingerprints: SHA1: E7:6A:0E:37:85:BD:F9:E2:FD:B2:4B:96:A9:3A:97:91:EE:30:91:53 SHA256: 41:AB:78:C1:91:19:BA:03:13:B1:D6:62:27:1D:6E:0B:53:FC:91:AF:DF:E0:6A:17:61:E5:28:D7:AF:26:BA:E1 Signature algorithm name: SHA512withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_64a3d3e3-503c-4574-a544-ea63bab7f637_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 58380f109ee41ec443e0e1655e4009f7c782b4e48203464651b92508e37e8cb1 Valid from: Tue Aug 08 06:57:46 CDT 2023 until: Tue Aug 08 06:57:56 CDT 2073 Certificate fingerprints: SHA1: DF:F5:B0:63:1B:B4:A1:81:28:FF:FB:0E:97:78:49:B1:0F:A7:9F:CA SHA256: 4E:72:58:BB:D6:8E:D1:D1:C8:33:32:2F:58:FA:66:8A:26:1E:10:4F:C3:7F:DD:33:6E:39:38:1F:11:A6:EF:7F Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_9b146bc3-5987-414c-9ed6-7ba735b0ab10_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d62267e39615f334538d64353a48539673b6c8331f3dbb5bdae6b6897541a631 Valid from: Tue Aug 08 06:57:36 CDT 2023 until: Tue Aug 08 06:57:46 CDT 2073 Certificate fingerprints: SHA1: 15:16:97:87:F1:EF:56:12:9E:FB:24:A5:8E:EA:CF:B5:14:9F:81:24 SHA256: 61:C4:F6:D9:8A:54:A9:31:D6:4D:09:B0:D9:0B:36:01:4F:97:53:B8:0D:09:83:01:E3:1B:67:F6:66:F9:05:0B Signature algorithm name: SHA384withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b037a3dc-b4a9-46a6-8b45-66df01da4f0a_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 8decb6c87779103a3915f71963b3c6d6208c7530a6935215b3f7ef6a2832effb Valid from: Tue Aug 08 06:57:39 CDT 2023 until: Tue Aug 08 06:57:49 CDT 2073 Certificate fingerprints: SHA1: 74:9C:1C:D1:D0:15:92:A4:35:38:C7:12:FC:89:D8:19:29:B7:77:EE SHA256: AF:39:10:89:1E:0B:08:2F:AF:C1:D4:F9:13:73:1D:72:C9:6B:27:EF:8A:F0:66:D6:89:BA:27:CB:1A:90:16:EA Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b0b8feac-e048-407c-afc8-44008b4e88cb_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9a20c156e837e5f7d974e6ec9c3da25f30170e775f789c4836d3a00d919fe5e5 Valid from: Tue Aug 08 06:57:36 CDT 2023 until: Tue Aug 08 06:57:46 CDT 2073 Certificate fingerprints: SHA1: 3F:8D:06:04:A6:9F:ED:C1:39:FC:86:40:C4:8C:19:6D:C2:E3:A9:5E SHA256: 3A:1D:39:FC:3C:BD:17:A9:19:A8:45:BB:FD:FE:2A:3A:24:BD:CF:A6:0A:07:17:21:BF:D8:75:84:5E:10:50:16 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b68c6303-e35e-44f0-b300-e9347e3e3305_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9bd61db1532aef6c9efa870ccf8cd39caf227037d82c9c0404ba3c95bff46322 Valid from: Tue Aug 08 06:57:40 CDT 2023 until: Tue Aug 08 06:57:50 CDT 2073 Certificate fingerprints: SHA1: 34:29:CF:02:EF:D0:C9:CF:A3:6C:79:A8:B9:36:D8:6F:CB:6F:4D:02 SHA256: 8B:F9:35:9E:86:1E:0A:1C:BC:2E:7C:BB:C9:50:FD:F3:84:51:F6:E8:92:C6:03:2A:0C:EB:74:0C:7D:93:8C:28 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_cef00de1-5a40-444a-94b4-35d7a290efad_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 845d78edfaf1912519bddcffffa6aaae9253dd1a087c781132686472763314e2 Valid from: Tue Aug 08 06:57:44 CDT 2023 until: Tue Aug 08 06:57:54 CDT 2073 Certificate fingerprints: SHA1: A4:EC:F5:F6:80:A1:51:FE:DD:65:AC:7E:2E:78:C9:0B:FB:82:33:DC SHA256: C9:62:C8:12:CB:C6:6B:96:C6:D4:E4:9B:1D:0A:8A:E8:47:0E:C6:EA:70:E2:CE:DE:06:C8:77:4D:84:3E:32:33 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_cef05e47-6622-43e7-b61d-1209f0dcdf99_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ee31a06bda23b8f5a042295d851018c3502a7a8bcd22e2367226c9b5014699a8 Valid from: Tue Aug 08 06:57:38 CDT 2023 until: Tue Aug 08 06:57:48 CDT 2073 Certificate fingerprints: SHA1: 22:EC:A2:90:AA:1C:73:0C:23:B2:AA:F8:B2:CD:35:C2:A4:10:0E:0E SHA256: F2:B4:3B:93:BA:BF:08:E0:58:30:78:03:8F:C0:60:6A:68:E7:68:7D:00:ED:50:B2:9A:8B:21:C3:9F:71:4A:8A Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256k1) key (disabled) Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* All keys are saved in aliases. Every alias has follow format: KeyOpsType + GUID + Use + Algorithm . Where: - KeyOpsType: values Connect | SSA - Use: sig (signature) | enc (encryption) - Algorithm: if Use == sig follow algorithm values are used: RS256 RS384 RS512 ES256 ES256K ES384 ES512 PS256 PS384 PS512 EdDSA if Use == enc follow algorithm values are used: RSA1_5 RSA-OAEP RSA-OAEP-256 ECDH-ES ECDH-ES+A128KW ECDH-ES+A192KW ECDH-ES+A256KW . This Key Store is used for keys/certificates keeping, which are used by the OpenID provider ( jans-auth-server ).", "title": "jans-auth-keys.pkcs12"}, {"location": "janssen-server/auth-server/crypto/key-storage/#smtp-keyspkcs12", "text": "Here is the example of the file: /etc/certs/smtp-keys.pkcs12 (list of entries/aliases). keytool -list -v -storetype PKCS12 -keystore /etc/certs/smtp-keys.pkcs12 -storepass 6VkIGu0DhnrD Keystore type: PKCS12 Keystore provider: SUN Your keystore contains 1 entry Alias name: smtp_sig_ec256 Creation date: Aug 8, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=SMTP CA Certificate Issuer: CN=SMTP CA Certificate Serial number: 690675c1 Valid from: Tue Aug 08 06:57:12 CDT 2023 until: Fri Aug 05 06:57:12 CDT 2033 Certificate fingerprints: SHA1: 69:77:F6:3E:44:0C:3A:BE:0D:58:02:71:21:72:39:12:54:DB:D7:88 SHA256: E5:E6:CB:BE:76:62:06:2F:A0:C9:49:0F:DD:0D:B1:D1:5B:D6:A2:2C:11:E1:0B:FE:84:67:B0:9D:EB:9B:3A:ED Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: 94 D2 A8 BC 8C D7 6F E0 EC BF 2D 92 3A 8D E1 CE ......o...-.:... 0010: 3D 71 CB B0 =q.. ] ] ******************************************* ******************************************* This Key Store stores one alias ( smtp_sig_ec256 ) and it is used for keeping of key/certificate, which is used by email sending functionality - signing of emails. Alias smtp_sig_ec256 contains self-signed certificate. User/Admin can update this KeyStore, adding key/certificate signed by trusted certificate authority (CA) (X-509 PKI).", "title": "smtp-keys.pkcs12"}, {"location": "janssen-server/auth-server/crypto/key-storage/#bcfks-keystore", "text": "Janssen also supports BCFKS format of KeyStore. As a rule this format is used on RHEL/DISA-STIG OS. Access to this type of KeyStore is provided by BCFIPS crypto provider. Modules of cryptoprovider can be found (after installing on RHEL/DISA-STIG OS) here: /var/gluu/dist/app/bc-fips-1.0.2.3.jar /var/gluu/dist/app/bcpkix-fips-1.0.6.jar . Here is example of the BCFKS KeyStore /etc/certs/jans-auth-keys.bcfks (list of entries/aliases): keytool -list -v -keystore /etc/certs/jans-auth-keys.bcfks -storetype BCFKS -providerpath /var/gluu/dist/app/bc-fips-1.0.2.3.jar:/var/gluu/dist/app/bcpkix-fips-1.0.6.jar -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -storepass CqE4ApXQxz5y Keystore type: BCFKS Keystore provider: BCFIPS Your keystore contains 30 entries Alias name: connect_01906c9d-fed6-48f1-94b8-85446a692f23_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 3b795840da219a3a7736d0ac0ebc2d632e925dc4b472a02e4b930eb1d5ca278b Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 40:B5:54:85:6B:3B:B1:A9:93:22:6D:91:AA:37:AD:92:A9:B0:5A:A9 SHA256: 06:23:28:01:89:6A:96:EA:A6:3E:EA:27:1D:7C:7A:8A:C7:C9:6D:3F:D0:BF:00:69:35:27:CA:CB:54:75:C6:F1 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_03a3687a-9c3c-4026-abfc-cafef6a76f92_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: df266f1918ae93954aaad44cdceab2ac89be1c20ad16245f1567d751db5d6d1a Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 12:12:0B:15:47:A4:C9:AB:44:4A:00:5E:B3:3A:8E:EE:56:70:6F:A7 SHA256: 11:F8:12:47:17:E6:D1:D4:80:1F:66:72:22:2C:49:93:72:DE:EF:5E:58:40:74:5B:AE:66:C4:96:F5:9C:86:13 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_1b960e55-7b8c-4eeb-9379-b933b8a28fb6_enc_ecdh-es+a128kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ad0cb98a5844cfe6a56c944d269aa3ce6379dc8fea2b0752514753935ae3d821 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 28:8F:83:99:24:8E:97:54:5A:B7:41:BB:28:C5:5E:BE:67:38:AF:F4 SHA256: E5:DE:D0:4A:17:5B:F8:5D:32:E4:8B:E2:E6:24:D6:22:50:D6:2E:E1:D4:ED:AB:9A:AB:74:B8:24:8C:16:97:14 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_4260d824-790d-440e-b2e0-a1a4ab813169_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 28f4866a894a33bb70dcb33138631be67a3b3b2c2b02c31a24913fde2d6d905d Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: CD:2C:FC:D2:81:A7:26:EA:C1:63:66:C4:AF:43:20:F3:E0:10:B7:41 SHA256: F5:3F:81:C5:B4:CD:8B:7D:B1:E4:83:54:DE:B9:88:F5:1B:3E:DA:CD:A5:93:86:D5:21:E5:3B:3D:42:5C:56:E3 Signature algorithm name: SHA512WITHECDSA Subject Public Key Algorithm: 521-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_464cc164-24ec-43c2-9f13-bca1c7faab11_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d4786313f02f3444beabbac0ed6c307db4af29e3f044edd047e976efe48c2337 Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 8A:37:4D:12:F9:24:93:DF:1B:59:90:26:3B:1A:95:5A:F8:46:1E:CB SHA256: B4:28:C6:BC:3D:AA:7C:52:5C:E4:22:FC:E7:E0:94:BF:22:66:91:0F:D6:CF:37:6E:C5:54:ED:0C:30:A8:24:CF Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_53cfa5f1-c227-4843-94d0-e5369cd822b0_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 321e23c27b9ec8a65e7e8fe0e64f68aa7390d713bebfa78b17f8962bb28c1d4f Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 6F:D2:4A:FC:48:1F:F3:B7:CC:13:4B:41:3A:BC:19:C4:85:A9:E9:7C SHA256: 43:80:83:D8:84:75:87:5A:24:D6:6B:AC:EC:0D:45:2E:8F:4A:FC:B4:47:D4:D7:49:E8:06:12:2F:98:7C:91:8F Signature algorithm name: SHA384WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_63e8e482-18ef-410e-bf27-0543a37ac166_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 5fe30fe9ce2b55b6738ec74e0b711c5aa3052ae200fdb9c39bb1392420087d7c Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 1C:27:A5:78:64:EA:01:13:C8:62:D4:4C:93:7A:95:F5:CC:C0:55:BA SHA256: F6:CB:47:52:9D:10:B6:31:FB:C2:1F:CC:30:DD:91:DD:2D:85:C0:44:BB:AB:CA:05:9D:47:05:00:7E:35:73:8B Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_64e35c92-c4f2-4104-81ef-7a366f2dbc38_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6742d9b42e180b7f4a1f58121dddb02896ff1638e8254bd74415a90e47718e91 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 75:AB:EA:2C:D7:C8:87:86:7C:FE:0D:23:33:24:CE:FD:75:3E:E5:E0 SHA256: EA:7D:7F:F1:51:00:5F:D8:80:A5:AF:67:F4:E1:84:A2:E5:D0:0A:8F:A3:98:81:29:36:9B:14:DA:59:02:76:AA Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_71a098e5-0fe0-4946-85f8-adf0d6759413_enc_ecdh-es+a256kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 285d3bcd2569a9a0db6091c184e47bf855edf758251749b739267b7f6f9821d3 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: D6:D7:0C:33:6E:A8:A4:54:2A:1F:2D:59:7D:2C:26:0A:EB:B8:AE:41 SHA256: EC:82:5E:A3:66:99:FB:3E:64:B7:47:27:AA:0D:13:C6:64:E1:42:41:B4:8E:F7:B9:23:20:AA:15:1E:F3:22:F7 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_82a7b334-4756-4201-a432-1b181badf695_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: cce1b501329cff10503a96587042b4f37cc994ac3f98c615bab4c9680a53d769 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 37:1C:A3:F4:A3:04:E4:DC:AA:F3:21:AD:BD:B0:5F:D8:0A:95:7B:29 SHA256: D7:CA:AE:57:A3:43:1E:94:93:ED:C8:34:72:29:DD:CE:02:BD:E5:69:6D:34:D3:7D:26:AE:78:19:4C:E9:BF:CE Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_a3d528cf-fd43-4015-92be-1e644310bbf0_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: de13b1e646dd2456c3512de303b2fb272108bcdb40c180717077820c07e32f65 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: EF:5E:62:AA:89:31:70:83:35:40:CB:9E:30:23:32:21:12:77:DC:83 SHA256: 88:1A:A2:85:DB:27:46:04:EE:E5:DC:8A:5E:A7:77:CC:36:C5:A6:1A:E7:A1:85:44:2E:E4:A0:91:8A:FD:A4:6F Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_ab2f67de-14fb-4312-89fa-56b2cd70f616_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d36755d2a472837ab9fe1dad688b5a1881bff6073d5a494af0275226f236146c Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 8B:FD:A9:75:7C:33:1E:9D:03:47:58:2E:31:D6:49:30:E6:65:6B:A7 SHA256: 5C:E2:28:7B:B0:66:17:A8:14:82:49:14:16:E8:40:B3:B6:C1:5F:90:77:25:A3:C4:A5:25:E6:77:CB:B9:92:91 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_ae7adf42-8f9b-4fe0-bbf1-e9e1016904f5_enc_rsa-oaep-256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 324a9b70a8410e9a02eb596e536cda516f91b250befb22699a909d0b2505e03 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 66:CF:B6:EB:27:10:CC:45:E4:CF:8A:66:71:05:97:22:BA:47:6B:33 SHA256: EF:16:46:1F:C5:0B:41:0B:B4:06:A7:9D:7F:EB:81:76:5F:35:B3:E4:09:67:95:D2:2A:10:D3:2F:59:DA:5D:73 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_b52de13d-33fe-446f-b4fa-6b4ce816c18e_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4d4b22cacdd15cd7bbf339c18ef14fba4ba7b0f13ad37f9452e00404488a880c Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 47:03:76:16:4B:D9:5C:83:AC:C7:40:10:F3:46:72:86:15:21:6C:CD SHA256: A3:3A:22:75:E2:E5:5B:69:31:FB:E8:59:E0:90:20:60:BC:47:30:9C:5C:5A:B6:97:92:37:71:CD:91:BF:93:78 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_c82cc876-6e92-408c-b519-76d153aad42d_enc_ecdh-es+a192kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 586b7dd9cecd3ef8c58b1bac766caec5d4c2ac8097c1cc4a22a20905ce5f9229 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: E6:3E:62:82:3C:6F:FE:CF:85:FD:6D:82:A9:7D:68:03:38:F0:AB:63 SHA256: 0D:D0:1B:50:02:0B:41:C1:35:CD:A9:7A:E5:10:AA:88:F2:AD:F7:8E:88:C2:3F:68:A9:33:E6:1B:EB:28:71:30 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_d1001a39-29a1-45e4-ae0d-2eee86a83ada_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ba44ac71c5a340aec0d8e0078b059c36a2819915774e8403e1b589a330570833 Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 49:59:6A:9D:D6:E6:98:05:18:BD:25:1A:C5:C0:2B:A6:C3:3E:36:52 SHA256: DA:57:65:45:A2:16:76:E0:B7:20:DA:82:BF:77:AF:B9:58:D5:E7:D3:2F:1B:D3:BC:48:51:E2:D1:C2:41:A9:FA Signature algorithm name: SHA512WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_f32a5790-4e43-4629-95bd-37b35d7c2e39_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9f0340f5c5cafc1816d2a31c20846fb24d400b3b5194a629ac5baf6db6d15e60 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 5A:37:CA:6A:27:AB:9F:FC:6B:C3:D3:C6:B4:47:F3:10:F4:C9:F3:B3 SHA256: 11:A4:9C:ED:C0:05:B9:27:89:2B:17:52:11:AA:34:B4:E7:81:08:13:44:7D:93:3A:DE:CA:23:A4:22:F7:05:9F Signature algorithm name: SHA384WITHECDSA Subject Public Key Algorithm: 384-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_0639ba94-902c-4ab6-923a-58137554f667_enc_ecdh-es Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6fac3869f3fc7297470eee65fc4315328edaf475798d5bbc469de652f3088ca3 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: 76:B5:F0:B9:1C:88:54:95:5B:11:2A:6A:AE:2E:C3:02:59:1B:07:2C SHA256: 7B:26:2E:36:4B:27:AA:C0:5B:FE:2C:2E:73:B1:75:64:2D:3E:0B:D2:C4:8D:F6:63:12:E8:2E:4C:46:EB:35:4C Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_0d94f183-878c-445d-9917-28357b15c4ee_sig_rs256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6d76a82ed166e13ecc2fb0742ebc72f619af0b738baf69438d2aba4262cfdbc4 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 14:8E:19:D8:8D:FD:68:14:40:72:35:1F:93:2A:7D:83:81:7E:6C:D8 SHA256: CB:69:E0:7C:55:2C:39:56:F8:17:ED:72:96:47:DB:8C:90:1A:1E:2A:E8:33:CA:79:96:DD:44:9F:F7:63:A2:D4 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_1a5ea0d5-0c70-43d2-ab23-e324620b413b_sig_ps512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 42bd6fbc27749cd6598c54aa0928e93057dc6c6c083c9f73d4e2046c4bac02d0 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: D3:D1:31:59:33:D1:A6:86:8F:A5:F8:7F:D6:15:44:53:15:99:6D:DC SHA256: 88:95:8C:89:F3:E7:28:E8:3D:9F:47:39:E2:F8:F5:FC:FA:63:71:B3:81:F0:9C:98:7E:A4:0A:FD:7E:7E:E9:AD Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_20d8cce9-0994-4fca-9cfa-f5fbe22eb940_sig_es256k Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a192c3ca749b78a153cb3134c50fddcdd5dd401dd399b831199ba383eddf355b Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 4E:94:55:21:15:53:1E:3E:3B:6E:85:B9:BF:A7:4B:46:2A:FB:09:4F SHA256: BA:AB:58:DF:29:7C:5A:D5:31:2F:B9:8B:CE:E9:3F:0B:5B:E5:01:94:CC:A8:9B:41:8B:45:9B:30:D2:63:D6:24 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_33b1591d-1b79-490f-a980-573486ec620b_sig_es384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ba8a0e96843f1a5181a96d2fc1bdae8b6954bb70b2b5c1fad4895438f4079dd0 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: B8:97:F4:EA:85:14:41:24:8C:DC:E0:8F:66:18:FD:31:7E:0B:5D:D5 SHA256: F3:9E:1F:25:E2:03:3C:7B:69:15:12:01:E2:94:EF:1E:95:43:43:A2:CB:8E:88:88:8A:3D:53:5E:82:E9:0E:9C Signature algorithm name: SHA384WITHECDSA Subject Public Key Algorithm: 384-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_34943497-d9fb-43ca-8ee1-1437e1dcf78e_sig_ps384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: b45de18f13366f309b100be313770edc6e80942771b08d656e699f7e081e5a69 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: C4:2D:DB:4D:06:7F:27:89:9A:C0:84:DB:08:BF:0C:75:3B:5B:74:22 SHA256: 77:07:D2:90:7C:AD:7A:F1:D8:EE:C1:84:54:B6:E5:41:7B:BB:C7:8F:64:96:D4:D3:ED:FD:32:F3:6C:10:11:62 Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_475830af-d019-4e04-9fb9-e68f0491284a_sig_es512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 69e6093118ce51ec5f21477e2946dd023f3c5b70bbde2922b26139b653eddd62 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 30:9D:95:9C:AE:60:F9:3F:D8:7A:AD:89:9D:AC:5D:7F:05:52:F9:50 SHA256: CA:90:7B:75:3C:99:CE:F2:42:DE:55:38:83:CB:C2:EA:F8:E7:0D:2B:00:5F:57:CF:75:D5:33:C4:5E:32:7E:A7 Signature algorithm name: SHA512WITHECDSA Subject Public Key Algorithm: 521-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_59bb3fe7-bf2a-4244-85a7-dd18785bcac6_enc_rsa-oaep Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 7f3e4adf1e08994ba83a1a59584c6f402e584baaecf1735ff9e0add33d65a423 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: FC:D7:45:92:F4:60:73:C6:7C:19:DA:AB:EC:54:FF:B4:62:C6:AC:CB SHA256: 66:05:C9:4C:3D:CA:EC:9F:29:06:57:00:A8:90:09:24:17:41:71:DC:1F:8E:7F:E7:5B:39:D8:A1:8B:A3:5A:F2 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_5e0f07d5-1e91-4bd3-bf56-6caa8a137ea6_enc_rsa1_5 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 3449c41d6f7c1b5b7f33c7411a81f41883f6f1fccb64d4e2bc22c130d771a26a Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: 1F:55:2E:62:3D:7E:FE:92:20:13:0D:FC:33:F8:82:B1:B7:BF:9E:7A SHA256: C9:6E:48:AF:F7:8B:04:30:FB:4B:30:47:A2:83:1E:4C:AF:9E:04:E6:07:8A:B1:AE:3B:CD:92:AE:CB:97:D2:EB Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_7d9cec29-697e-4e3e-9991-eba03394b69c_sig_ps256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 15e7eed8194a80919e9bd699212efca7e50ec9aa3834c6a8e32a7eeb9d9e1da9 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: A5:BE:24:97:EB:F5:0F:18:05:56:02:BF:66:24:98:24:59:82:5A:E6 SHA256: 16:EF:DD:45:17:3B:D7:66:36:14:7E:96:03:1F:51:02:6C:86:1E:19:E7:43:C7:DF:E9:A9:D0:86:9C:A6:7C:B8 Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_96ea824f-f915-4da8-8f76-3b4bf8bdf552_sig_rs384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4c79afa5d03e2aaab17c90519d59dec517de004f4c9b62960ebf10276b699105 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: E8:F3:5D:16:D0:2C:47:98:D4:F6:98:A1:5F:46:A0:DB:BD:F8:72:30 SHA256: 15:42:A4:30:FE:DB:D8:C4:61:11:A6:8D:10:51:02:64:70:C7:EA:BF:F3:C8:F3:42:03:D9:F8:00:19:F9:7C:28 Signature algorithm name: SHA384WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_b7ee7e46-0a6b-4040-b6b3-a78e9dedc116_sig_rs512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 82f95026558b89f3ca8c1129d3b79c74ce2ff70bb849991a8305afea974ebe1c Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: D8:45:78:27:94:39:93:57:DF:67:56:3B:06:5C:0C:2A:20:93:F6:0F SHA256: 6D:55:8E:F3:5F:6A:EA:6D:37:71:A9:57:1D:32:98:92:04:5E:8B:4A:C4:FC:E1:ED:B1:7A:D4:11:BF:38:02:80 Signature algorithm name: SHA512WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_b9d65217-ff51-4eab-914f-aeb40eb30bc2_sig_es256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 632a5f6e2bf5c5dbabf7376718c35b3101fe8a8065a6bf54db3dde5a1825dbf4 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 7D:51:C1:44:45:EF:6B:71:3D:EF:BC:20:E0:AE:59:4C:3D:16:10:23 SHA256: CC:1C:60:5E:E4:6A:B4:C4:7F:3F:2D:1B:2F:12:B4:79:27:94:3D:1D:D5:FA:C4:11:0E:53:76:DA:52:34:B0:62 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* .", "title": "BCFKS KeyStore"}, {"location": "janssen-server/auth-server/crypto/keys/", "tags": ["administration", "auth-server", "cryptography", "keys"], "text": "Overview # Janssen uses keys for signing and encryption, primarily concerning JSON documents. Janssen supports several signing and encryption algorithms in salted and unsalted, to fit a variety of business needs. If other algorithms are necessary, Janssen supports them via interception scripts. Keys # A key is a piece of information, usually a string of numbers or letters that are stored in a file, which, when processed through a cryptographic algorithm, can encode or decode cryptographic data. In Janssen we use keys for creating token like id_token , access_token . access_token : Access tokens are what the OAuth client uses to make requests to an API. The access token is meant to be read and validated by the API. id_token : An ID token is an artifact that proves that the user has been authenticated. It was introduced by OpenID Connect (OIDC) , an open standard for authentication used by Janssen. It contains information about what happened when a user authenticated, and is intended to be read by the OAuth client. The ID token may also contain information about the user such as their name or email address, although that is not a requirement of an ID token. Jans server JSON objects of public key # Gets list of JSON Web Key (JWK) used by server. JWK is a JSON data structure that represents a set of public keys as a JSON object. Browse below endpoint to know more about public keys used by server. https://<your_server>/jans-auth/restv1/jwks Let's see some example of JWT public keys used in janssen. When jwk is expired, it is archived and can be access by following url: https://<your_server>/jans-auth/restv1/jwks/archived/{kid} More info about archived jwks can be found here Example-1 # The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for \"sig\" (Signature) on data. The \"alg\" (Algorithm) intended with this key is \"RS256\". { \"name\" : \"Connect RS256 Sign Key\" \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\", ... } Example-2 # The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for \"sig\" (Signature) on data. The \"alg\" (Algorithm) intended with this key is \"RS384\". { \"name\" : \"Connect RS384 Sign Key\", \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-384\", ... } Example-3 # The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"RS512\". { \"name\" : \"Connect RS512 Sign Key\", \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-512\", ... } Example-4 # The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256\". { \"name\" : \"Connect ES256 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-256 (secp256r1) and SHA-256\", ... } Example-5 # The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256K\". { \"name\" : \"Connect ES256 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-256 (secp256r1) and SHA-256\", ... } Example-6 # The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256K\". { \"name\" : \"Connect ES384 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-384 (secp384r1) and SHA-384\", ... } Example-7 # The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES512\". { \"name\" : \"Connect ES512 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-521 (secp521r1) and SHA-512\", ... } Example-8 # The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS256\". { \"name\" : \"Connect PS256 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-256 and MGF1 with SHA-256\", ... } Example-9 # The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS384\". { \"name\" : \"Connect PS384 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-384 and MGF1 with SHA-384\", ... } Example-10 # The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS512\". { \"name\" : \"Connect PS512 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-512 and MGF1 with SHA-512\", ... } Example-11 # The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for \"enc\" (encryption) on data. The \"alg\" (Algorithm) intended with this key is \"RSA1_5\". ``commandLine { \"name\" : \"Connect RSA1_5 Encryption Key\", \"descr\" : \"Encryption Key: RSAES-PKCS1-v1_5\", ... } ### Example-12 The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for \"enc\" (encryption) on data. The \"alg\" (Algorithm) intended with this key is \"RSA-OAEP\". ```commandLine { \"name\" : \"Connect RSA-OAEP Encryption Key\", \"descr\" : \"Encryption Key: RSAES OAEP using default parameters\", ... } Crypto Supported # Depending on the transport through which the messages are sent, the integrity of the message might not be guaranteed and the originator of the message might not be authenticated. To mitigate these risks, ID Token, UserInfo Response, Request Object, and Client Authentication JWT values can utilize JSON Web Signature (JWS) [JWS] to sign their contents. To achieve message confidentiality, these values can also use JSON Web Encryption (JWE) [JWE] to encrypt their contents. Signing algorithms # Signing or Signature algorithm is a cryptographic mechanism used to verify the authenticity and integrity of digital data. We may consider it as a digital version of the ordinary handwritten signatures, but with higher levels of complexity and security. Let's see some signing key algorithms Name Kty Use Alg RS256 Sign Key RSA sig RS256 RS384 Sign Key RSA sig RS384 RS512 Sign Key RSA sig RS512 ES256 Sign Key EC sig ES256 ES256 Sign Key EC sig ES256K ES384 Sign Key EC sig ES384 ES512 Sign Key EC sig ES384 PS256 Sign Key RSA sig PS256 PS384 sign Key RSA sig PS384 PS512 sign Key RSA sig PS512 Encryption algorithms # In cryptography, encryption is the process of encoding information. This process converts the original representation of the information, known as plaintext, into an alternative form known as ciphertext. Ideally, only authorized parties can decipher a ciphertext back to plaintext and access the original information. Let's see some encryption keys. Name Kty Use Alg RSA1_5 Encryption key RSA enc RSA1_5 RSA-OAEP Encryption Key RSA enc RSA-OAEP ECDH-ES Encryption Key CE enc ECDH-ES RSA Key Formats # PKCS#8 encrypted private key \"EncryptedPrivateKeyInfo\" (default for private keys) PKCS#1 \"RSAPublicKey\" (default for public keys) PKCS#8 unencrypted \"PrivateKeyInfo\" PKCS#1 unencrypted \"RSAPrivateKey\" (OpenSSL private key file format) X.509 \"SubjectPublicKeyInfo\" (OpenSSL public key file format) The above key values can be passed as (a) a binary DER-encoded ASN.1 file, (b) a text file in PEM format, (c) a string containing the key in PEM format . Also supported are RSA private and public keys represented in XML format to XKMS 2.0 [XKMS] and JSON Web Key (JWK) format [JWK] . For more details, see Key Storage Format . To know more about RSA keyformat browse here Janssen Keystore Formats # In Janssen we use keystore formats PKCS12 . Which is Encrypted private key formats. In Janssen currently using an extension of p12 . We also have pkcs12 , pfx . We can store private keys, secret keys and certificates on this type. You can find jans-auth-keys.p12 in /etc/certs/ To see the private key you can use bellow command keytool -list -v -keystore /etc/certs/jans-auth-keys.p12 -storetype pkcs12 -storepass <password>", "title": "Keys"}, {"location": "janssen-server/auth-server/crypto/keys/#overview", "text": "Janssen uses keys for signing and encryption, primarily concerning JSON documents. Janssen supports several signing and encryption algorithms in salted and unsalted, to fit a variety of business needs. If other algorithms are necessary, Janssen supports them via interception scripts.", "title": "Overview"}, {"location": "janssen-server/auth-server/crypto/keys/#keys", "text": "A key is a piece of information, usually a string of numbers or letters that are stored in a file, which, when processed through a cryptographic algorithm, can encode or decode cryptographic data. In Janssen we use keys for creating token like id_token , access_token . access_token : Access tokens are what the OAuth client uses to make requests to an API. The access token is meant to be read and validated by the API. id_token : An ID token is an artifact that proves that the user has been authenticated. It was introduced by OpenID Connect (OIDC) , an open standard for authentication used by Janssen. It contains information about what happened when a user authenticated, and is intended to be read by the OAuth client. The ID token may also contain information about the user such as their name or email address, although that is not a requirement of an ID token.", "title": "Keys"}, {"location": "janssen-server/auth-server/crypto/keys/#jans-server-json-objects-of-public-key", "text": "Gets list of JSON Web Key (JWK) used by server. JWK is a JSON data structure that represents a set of public keys as a JSON object. Browse below endpoint to know more about public keys used by server. https://<your_server>/jans-auth/restv1/jwks Let's see some example of JWT public keys used in janssen. When jwk is expired, it is archived and can be access by following url: https://<your_server>/jans-auth/restv1/jwks/archived/{kid} More info about archived jwks can be found here", "title": "Jans server JSON objects of public key"}, {"location": "janssen-server/auth-server/crypto/keys/#example-1", "text": "The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for \"sig\" (Signature) on data. The \"alg\" (Algorithm) intended with this key is \"RS256\". { \"name\" : \"Connect RS256 Sign Key\" \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\", ... }", "title": "Example-1"}, {"location": "janssen-server/auth-server/crypto/keys/#example-2", "text": "The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for \"sig\" (Signature) on data. The \"alg\" (Algorithm) intended with this key is \"RS384\". { \"name\" : \"Connect RS384 Sign Key\", \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-384\", ... }", "title": "Example-2"}, {"location": "janssen-server/auth-server/crypto/keys/#example-3", "text": "The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"RS512\". { \"name\" : \"Connect RS512 Sign Key\", \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-512\", ... }", "title": "Example-3"}, {"location": "janssen-server/auth-server/crypto/keys/#example-4", "text": "The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256\". { \"name\" : \"Connect ES256 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-256 (secp256r1) and SHA-256\", ... }", "title": "Example-4"}, {"location": "janssen-server/auth-server/crypto/keys/#example-5", "text": "The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256K\". { \"name\" : \"Connect ES256 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-256 (secp256r1) and SHA-256\", ... }", "title": "Example-5"}, {"location": "janssen-server/auth-server/crypto/keys/#example-6", "text": "The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256K\". { \"name\" : \"Connect ES384 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-384 (secp384r1) and SHA-384\", ... }", "title": "Example-6"}, {"location": "janssen-server/auth-server/crypto/keys/#example-7", "text": "The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES512\". { \"name\" : \"Connect ES512 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-521 (secp521r1) and SHA-512\", ... }", "title": "Example-7"}, {"location": "janssen-server/auth-server/crypto/keys/#example-8", "text": "The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS256\". { \"name\" : \"Connect PS256 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-256 and MGF1 with SHA-256\", ... }", "title": "Example-8"}, {"location": "janssen-server/auth-server/crypto/keys/#example-9", "text": "The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS384\". { \"name\" : \"Connect PS384 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-384 and MGF1 with SHA-384\", ... }", "title": "Example-9"}, {"location": "janssen-server/auth-server/crypto/keys/#example-10", "text": "The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS512\". { \"name\" : \"Connect PS512 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-512 and MGF1 with SHA-512\", ... }", "title": "Example-10"}, {"location": "janssen-server/auth-server/crypto/keys/#example-11", "text": "The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for \"enc\" (encryption) on data. The \"alg\" (Algorithm) intended with this key is \"RSA1_5\". ``commandLine { \"name\" : \"Connect RSA1_5 Encryption Key\", \"descr\" : \"Encryption Key: RSAES-PKCS1-v1_5\", ... } ### Example-12 The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for \"enc\" (encryption) on data. The \"alg\" (Algorithm) intended with this key is \"RSA-OAEP\". ```commandLine { \"name\" : \"Connect RSA-OAEP Encryption Key\", \"descr\" : \"Encryption Key: RSAES OAEP using default parameters\", ... }", "title": "Example-11"}, {"location": "janssen-server/auth-server/crypto/keys/#crypto-supported", "text": "Depending on the transport through which the messages are sent, the integrity of the message might not be guaranteed and the originator of the message might not be authenticated. To mitigate these risks, ID Token, UserInfo Response, Request Object, and Client Authentication JWT values can utilize JSON Web Signature (JWS) [JWS] to sign their contents. To achieve message confidentiality, these values can also use JSON Web Encryption (JWE) [JWE] to encrypt their contents.", "title": "Crypto Supported"}, {"location": "janssen-server/auth-server/crypto/keys/#signing-algorithms", "text": "Signing or Signature algorithm is a cryptographic mechanism used to verify the authenticity and integrity of digital data. We may consider it as a digital version of the ordinary handwritten signatures, but with higher levels of complexity and security. Let's see some signing key algorithms Name Kty Use Alg RS256 Sign Key RSA sig RS256 RS384 Sign Key RSA sig RS384 RS512 Sign Key RSA sig RS512 ES256 Sign Key EC sig ES256 ES256 Sign Key EC sig ES256K ES384 Sign Key EC sig ES384 ES512 Sign Key EC sig ES384 PS256 Sign Key RSA sig PS256 PS384 sign Key RSA sig PS384 PS512 sign Key RSA sig PS512", "title": "Signing algorithms"}, {"location": "janssen-server/auth-server/crypto/keys/#encryption-algorithms", "text": "In cryptography, encryption is the process of encoding information. This process converts the original representation of the information, known as plaintext, into an alternative form known as ciphertext. Ideally, only authorized parties can decipher a ciphertext back to plaintext and access the original information. Let's see some encryption keys. Name Kty Use Alg RSA1_5 Encryption key RSA enc RSA1_5 RSA-OAEP Encryption Key RSA enc RSA-OAEP ECDH-ES Encryption Key CE enc ECDH-ES", "title": "Encryption algorithms"}, {"location": "janssen-server/auth-server/crypto/keys/#rsa-key-formats", "text": "PKCS#8 encrypted private key \"EncryptedPrivateKeyInfo\" (default for private keys) PKCS#1 \"RSAPublicKey\" (default for public keys) PKCS#8 unencrypted \"PrivateKeyInfo\" PKCS#1 unencrypted \"RSAPrivateKey\" (OpenSSL private key file format) X.509 \"SubjectPublicKeyInfo\" (OpenSSL public key file format) The above key values can be passed as (a) a binary DER-encoded ASN.1 file, (b) a text file in PEM format, (c) a string containing the key in PEM format . Also supported are RSA private and public keys represented in XML format to XKMS 2.0 [XKMS] and JSON Web Key (JWK) format [JWK] . For more details, see Key Storage Format . To know more about RSA keyformat browse here", "title": "RSA Key Formats"}, {"location": "janssen-server/auth-server/crypto/keys/#janssen-keystore-formats", "text": "In Janssen we use keystore formats PKCS12 . Which is Encrypted private key formats. In Janssen currently using an extension of p12 . We also have pkcs12 , pfx . We can store private keys, secret keys and certificates on this type. You can find jans-auth-keys.p12 in /etc/certs/ To see the private key you can use bellow command keytool -list -v -keystore /etc/certs/jans-auth-keys.p12 -storetype pkcs12 -storepass <password>", "title": "Janssen Keystore Formats"}, {"location": "janssen-server/auth-server/endpoints/access-evaluation/", "tags": ["administration", "auth-server", "access-evaluation", "endpoint"], "text": "Overview # The Jans-Auth server implements OpenID AuthZEN Authorization API 1.0 \u2013 draft 01 . The AuthZEN Authorization API 1.0 specification defines a standardized interface for communication between Policy Enforcement Points (PEPs) and Policy Decision Points (PDPs) to facilitate consistent authorization decisions across diverse systems. It introduces an Access Evaluation API that allows PEPs to query PDPs about specific access requests, enhancing interoperability and scalability in authorization processes. The specification is transport-agnostic, with an initial focus on HTTPS bindings, and emphasizes secure, fine-grained, and dynamic authorization mechanisms. The Access Evaluation Endpoint in the AuthZEN specification serves as a mechanism for Policy Enforcement Points (PEPs) to request access decisions from a Policy Decision Point (PDP) for specific resources and actions. Upon receiving a request, the endpoint evaluates the subject, resource, and action against defined policies to determine if access should be granted, denied, or if additional information is needed. The endpoint's responses are typically concise, aiming to provide a rapid decision that PEPs can enforce in real-time. The goal is to provide a scalable, secure interface for dynamic and fine-grained access control across applications. URL to access access evaluation endpoint on Janssen Server is listed in both: - the response of Janssen Server's well-known configuration endpoint given below. - the response of Janssen Server's /.well-known/authzen-configuration endpoint. OpenID Discovery https://janssen.server.host/jans-auth/.well-known/openid-configuration AuthZEN Discovery https://janssen.server.host/jans-auth/.well-known/authzen-configuration /.well-known/authzen-configuration allows to publish data specific to AuthZEN only. Response of AuthZEN discovery endpoint can be changed via AccessEvaluationDiscoveryType custom script. Snippet of AccessEvaluationDiscoveryType @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { scriptLogger . info ( \"write to script logger\" ); JSONObject response = ( JSONObject ) responseAsJsonObject ; response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); return true ; } access_evaluation_v1_endpoint claim in the response specifies the URL for access evaluation endpoint. By default, access evaluation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/access/v1/evaluation In order to call Access Evaluation Endpoint client must have access_evaluation scope. If scope is not present AS rejects call with 401 (unauthorized) http status code. Authorization header must contain valid access_token with access_evaluation scope granted to it. Otherwise it's possible to use Basic token with encoded client credentials if set accessEvaluationAllowBasicClientAuthorization AS configuration property to true . Bearer token : Authorization: Bearer <access_token> Basic authorization : Authorization: Basic <encoded client credentials> More information about request and response of the Access Evaluation Endpoint can be found in the OpenAPI specification of jans-auth-server module . Sample request POST /jans-auth/restv1/access/v1/evaluation HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Authorization: Basic M2NjOTdhYWItMDE0Zi00ZWM5LWI4M2EtNTE3MTRlODE3MDMwOmFlYmMwZWFhLWY5N2YtNDU5NS04ZWExLWFlNmU1NDFmNDZjNg== { \"subject\": { \"id\": \"alice@acmecorp.com\", \"type\": \"super_admin\", \"properties\": null }, \"resource\": { \"id\": \"123\", \"type\": \"account\", \"properties\": null }, \"action\": { \"name\": \"can_read\", \"properties\": { \"method\": \"GET\" } }, \"context\": { \"properties\": null } } Sample successful response with authorization_code . HTTP/1.1 200 Content-Type: application/json { \"decision\":true, \"context\": { \"id\":\"9e04dd22-e980-4e54-bc04-d64a0c2e1afe\", \"reason_admin\":{\"reason\":\"super_admin\"}, \"reason_user\":null } } Sample error response HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"invalid_token\" } Configuration Properties # Access Evaluation Endpoint AS configuration: accessEvaluationScriptName - Access evaluation custom script name. If not set AS falls back to first valid script found in database. accessEvaluationAllowBasicClientAuthorization - Allow basic client authorization for access evaluation endpoint. Custom script # AS provides AccessEvaluationType custom script which must be used to control Access Evaluation Endpoint behaviour. Use accessEvaluationScriptName configuration property to specify custom script. If not set AS falls back to first valid script found in database. Main evaluate method returns response which grants or denies access. Please see following snippet below: @Override public AccessEvaluationResponse evaluate ( AccessEvaluationRequest request , Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. access http request via context.getHttpRequest() // 2. access all access evaluation specific data directly with 'request', e.g. request.getSubject() // 3. perform custom validation if needed validateResource ( request . getResource ()); // typically some internal validation must be performed here // request data alone must not be trusted, it's just sample to demo script with endpoint if ( \"super_admin\" . equalsIgnoreCase ( request . getSubject (). getType ())) { final ObjectNode reasonAdmin = objectMapper . createObjectNode (); reasonAdmin . put ( \"reason\" , \"super_admin\" ); final AccessEvaluationResponseContext responseContext = new AccessEvaluationResponseContext (); responseContext . setId ( UUID . randomUUID (). toString ()); responseContext . setReasonAdmin ( reasonAdmin ); return new AccessEvaluationResponse ( true , responseContext ); } return AccessEvaluationResponse . FALSE ; } More details in Access Evaluation Custom Script Page . Full sample script can be found here Full successful Access Evaluation Flow sample # ####################################################### TEST: OpenID Connect Discovery ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/webfinger HTTP/1.1?resource=acct%3Aadmin%40happy-example.gluu.info&rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer HTTP/1.1 Host: happy-example.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 207 Content-Type: application/jrd+json;charset=iso-8859-1 Date: Fri, 08 Nov 2024 17:15:19 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=f8a91ca8-3ebb-48fb-852e-31e40b398b6d; Secure; HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"subject\": \"acct:admin@happy-example.gluu.info\", \"links\": [{ \"rel\": \"http://openid.net/specs/connect/1.0/issuer\", \"href\": \"https://happy-example.gluu.info\" }] } OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: happy-example.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 7715 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:19 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=474307e2-ed02-404e-bf35-a2bc60bf3421; Secure; HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/par\", \"introspection_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"introspection_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"status_list_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/status_list\", \"issuer\" : \"https://happy-example.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"introspection_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"fragment\", \"query.jwt\", \"query\", \"fragment.jwt\", \"jwt\", \"form_post.jwt\", \"form_post\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code token\", \"code\", \"code id_token\", \"code token id_token\", \"token id_token\", \"token\", \"id_token\" ], \"tx_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:device_code\", \"refresh_token\", \"implicit\", \"password\", \"authorization_code\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:token-exchange\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"prompt_values_supported\" : [ \"none\", \"login\", \"consent\", \"select_account\", \"create\" ], \"userinfo_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/userinfo\", \"access_evaluation_v1_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/access/v1/evaluation\", \"authorization_challenge_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/authorization_challenge\", \"op_tos_uri\" : \"https://happy-example.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"global_token_revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/global-token-revocation\", \"introspection_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"tx_token_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"session_revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://happy-example.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"role\", \"access_evaluation\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"clientinfo\", \"user_name\", \"profile\", \"uma_protection\", \"revoke_any_token\", \"global_token_revocation\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"device_sso\", \"https://jans.io/scim/users.read\", \"phone\", \"mobile_phone\", \"offline_access\", \"authorization_challenge\", \"https://jans.io/oauth/lock/audit.write\", \"email\", \"https://jans.io/oauth/lock/audit.readonly\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"archived_jwks_uri\" : \"https://happy-example.gluu.info/jans-auth/restv1/jwks/archived\", \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"tx_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://happy-example.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: accessEvaluation_whenSubjectTypeIsAcceptedByScript_shouldGrantAccess ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"access_evaluation openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://happy-example.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"access_evaluation test\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1664 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:20 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=d7035723-e472-4cac-84c5-ef19f14fcc09; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://happy-example.gluu.info/jans-auth/restv1/register?client_id=3cc97aab-014f-4ec9-b83a-51714e817030\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"bcf42a29-d534-4ed4-a4aa-eceb4e50f472\", \"client_id\": \"3cc97aab-014f-4ec9-b83a-51714e817030\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid access_evaluation\", \"client_secret\": \"aebc0eaa-f97f-4595-8ea1-ae6e541f46c6\", \"client_id_issued_at\": 1731086120, \"backchannel_logout_session_required\": false, \"client_name\": \"access_evaluation test\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"refresh_token\", \"authorization_code\" ], \"subject_type\": \"public\", \"authorization_details_types\": [], \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://happy-example.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 0, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/access/v1/evaluation HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Authorization: Basic M2NjOTdhYWItMDE0Zi00ZWM5LWI4M2EtNTE3MTRlODE3MDMwOmFlYmMwZWFhLWY5N2YtNDU5NS04ZWExLWFlNmU1NDFmNDZjNg== {\"subject\":{\"id\":\"alice@acmecorp.com\",\"type\":\"super_admin\",\"properties\":null},\"resource\":{\"id\":\"123\",\"type\":\"account\",\"properties\":null},\"action\":{\"name\":\"can_read\",\"properties\":{\"method\":\"GET\"}},\"context\":{\"properties\":null}} ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 132 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:21 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=d4f99d9f-5b94-4863-a020-73f6fb62c5e8; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"decision\":true,\"context\":{\"id\":\"9e04dd22-e980-4e54-bc04-d64a0c2e1afe\",\"reason_admin\":{\"reason\":\"super_admin\"},\"reason_user\":null}}", "title": "Access Evaluation"}, {"location": "janssen-server/auth-server/endpoints/access-evaluation/#overview", "text": "The Jans-Auth server implements OpenID AuthZEN Authorization API 1.0 \u2013 draft 01 . The AuthZEN Authorization API 1.0 specification defines a standardized interface for communication between Policy Enforcement Points (PEPs) and Policy Decision Points (PDPs) to facilitate consistent authorization decisions across diverse systems. It introduces an Access Evaluation API that allows PEPs to query PDPs about specific access requests, enhancing interoperability and scalability in authorization processes. The specification is transport-agnostic, with an initial focus on HTTPS bindings, and emphasizes secure, fine-grained, and dynamic authorization mechanisms. The Access Evaluation Endpoint in the AuthZEN specification serves as a mechanism for Policy Enforcement Points (PEPs) to request access decisions from a Policy Decision Point (PDP) for specific resources and actions. Upon receiving a request, the endpoint evaluates the subject, resource, and action against defined policies to determine if access should be granted, denied, or if additional information is needed. The endpoint's responses are typically concise, aiming to provide a rapid decision that PEPs can enforce in real-time. The goal is to provide a scalable, secure interface for dynamic and fine-grained access control across applications. URL to access access evaluation endpoint on Janssen Server is listed in both: - the response of Janssen Server's well-known configuration endpoint given below. - the response of Janssen Server's /.well-known/authzen-configuration endpoint. OpenID Discovery https://janssen.server.host/jans-auth/.well-known/openid-configuration AuthZEN Discovery https://janssen.server.host/jans-auth/.well-known/authzen-configuration /.well-known/authzen-configuration allows to publish data specific to AuthZEN only. Response of AuthZEN discovery endpoint can be changed via AccessEvaluationDiscoveryType custom script. Snippet of AccessEvaluationDiscoveryType @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { scriptLogger . info ( \"write to script logger\" ); JSONObject response = ( JSONObject ) responseAsJsonObject ; response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); return true ; } access_evaluation_v1_endpoint claim in the response specifies the URL for access evaluation endpoint. By default, access evaluation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/access/v1/evaluation In order to call Access Evaluation Endpoint client must have access_evaluation scope. If scope is not present AS rejects call with 401 (unauthorized) http status code. Authorization header must contain valid access_token with access_evaluation scope granted to it. Otherwise it's possible to use Basic token with encoded client credentials if set accessEvaluationAllowBasicClientAuthorization AS configuration property to true . Bearer token : Authorization: Bearer <access_token> Basic authorization : Authorization: Basic <encoded client credentials> More information about request and response of the Access Evaluation Endpoint can be found in the OpenAPI specification of jans-auth-server module . Sample request POST /jans-auth/restv1/access/v1/evaluation HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Authorization: Basic M2NjOTdhYWItMDE0Zi00ZWM5LWI4M2EtNTE3MTRlODE3MDMwOmFlYmMwZWFhLWY5N2YtNDU5NS04ZWExLWFlNmU1NDFmNDZjNg== { \"subject\": { \"id\": \"alice@acmecorp.com\", \"type\": \"super_admin\", \"properties\": null }, \"resource\": { \"id\": \"123\", \"type\": \"account\", \"properties\": null }, \"action\": { \"name\": \"can_read\", \"properties\": { \"method\": \"GET\" } }, \"context\": { \"properties\": null } } Sample successful response with authorization_code . HTTP/1.1 200 Content-Type: application/json { \"decision\":true, \"context\": { \"id\":\"9e04dd22-e980-4e54-bc04-d64a0c2e1afe\", \"reason_admin\":{\"reason\":\"super_admin\"}, \"reason_user\":null } } Sample error response HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"invalid_token\" }", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/access-evaluation/#configuration-properties", "text": "Access Evaluation Endpoint AS configuration: accessEvaluationScriptName - Access evaluation custom script name. If not set AS falls back to first valid script found in database. accessEvaluationAllowBasicClientAuthorization - Allow basic client authorization for access evaluation endpoint.", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/access-evaluation/#custom-script", "text": "AS provides AccessEvaluationType custom script which must be used to control Access Evaluation Endpoint behaviour. Use accessEvaluationScriptName configuration property to specify custom script. If not set AS falls back to first valid script found in database. Main evaluate method returns response which grants or denies access. Please see following snippet below: @Override public AccessEvaluationResponse evaluate ( AccessEvaluationRequest request , Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. access http request via context.getHttpRequest() // 2. access all access evaluation specific data directly with 'request', e.g. request.getSubject() // 3. perform custom validation if needed validateResource ( request . getResource ()); // typically some internal validation must be performed here // request data alone must not be trusted, it's just sample to demo script with endpoint if ( \"super_admin\" . equalsIgnoreCase ( request . getSubject (). getType ())) { final ObjectNode reasonAdmin = objectMapper . createObjectNode (); reasonAdmin . put ( \"reason\" , \"super_admin\" ); final AccessEvaluationResponseContext responseContext = new AccessEvaluationResponseContext (); responseContext . setId ( UUID . randomUUID (). toString ()); responseContext . setReasonAdmin ( reasonAdmin ); return new AccessEvaluationResponse ( true , responseContext ); } return AccessEvaluationResponse . FALSE ; } More details in Access Evaluation Custom Script Page . Full sample script can be found here", "title": "Custom script"}, {"location": "janssen-server/auth-server/endpoints/access-evaluation/#full-successful-access-evaluation-flow-sample", "text": "####################################################### TEST: OpenID Connect Discovery ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/webfinger HTTP/1.1?resource=acct%3Aadmin%40happy-example.gluu.info&rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer HTTP/1.1 Host: happy-example.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 207 Content-Type: application/jrd+json;charset=iso-8859-1 Date: Fri, 08 Nov 2024 17:15:19 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=f8a91ca8-3ebb-48fb-852e-31e40b398b6d; Secure; HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"subject\": \"acct:admin@happy-example.gluu.info\", \"links\": [{ \"rel\": \"http://openid.net/specs/connect/1.0/issuer\", \"href\": \"https://happy-example.gluu.info\" }] } OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: happy-example.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 7715 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:19 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=474307e2-ed02-404e-bf35-a2bc60bf3421; Secure; HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/par\", \"introspection_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"introspection_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"status_list_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/status_list\", \"issuer\" : \"https://happy-example.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"introspection_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"fragment\", \"query.jwt\", \"query\", \"fragment.jwt\", \"jwt\", \"form_post.jwt\", \"form_post\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code token\", \"code\", \"code id_token\", \"code token id_token\", \"token id_token\", \"token\", \"id_token\" ], \"tx_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:device_code\", \"refresh_token\", \"implicit\", \"password\", \"authorization_code\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:token-exchange\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"prompt_values_supported\" : [ \"none\", \"login\", \"consent\", \"select_account\", \"create\" ], \"userinfo_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/userinfo\", \"access_evaluation_v1_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/access/v1/evaluation\", \"authorization_challenge_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/authorization_challenge\", \"op_tos_uri\" : \"https://happy-example.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"global_token_revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/global-token-revocation\", \"introspection_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"tx_token_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"session_revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://happy-example.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"role\", \"access_evaluation\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"clientinfo\", \"user_name\", \"profile\", \"uma_protection\", \"revoke_any_token\", \"global_token_revocation\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"device_sso\", \"https://jans.io/scim/users.read\", \"phone\", \"mobile_phone\", \"offline_access\", \"authorization_challenge\", \"https://jans.io/oauth/lock/audit.write\", \"email\", \"https://jans.io/oauth/lock/audit.readonly\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"archived_jwks_uri\" : \"https://happy-example.gluu.info/jans-auth/restv1/jwks/archived\", \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"tx_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://happy-example.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: accessEvaluation_whenSubjectTypeIsAcceptedByScript_shouldGrantAccess ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"access_evaluation openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://happy-example.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"access_evaluation test\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1664 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:20 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=d7035723-e472-4cac-84c5-ef19f14fcc09; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://happy-example.gluu.info/jans-auth/restv1/register?client_id=3cc97aab-014f-4ec9-b83a-51714e817030\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"bcf42a29-d534-4ed4-a4aa-eceb4e50f472\", \"client_id\": \"3cc97aab-014f-4ec9-b83a-51714e817030\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid access_evaluation\", \"client_secret\": \"aebc0eaa-f97f-4595-8ea1-ae6e541f46c6\", \"client_id_issued_at\": 1731086120, \"backchannel_logout_session_required\": false, \"client_name\": \"access_evaluation test\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"refresh_token\", \"authorization_code\" ], \"subject_type\": \"public\", \"authorization_details_types\": [], \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://happy-example.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 0, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/access/v1/evaluation HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Authorization: Basic M2NjOTdhYWItMDE0Zi00ZWM5LWI4M2EtNTE3MTRlODE3MDMwOmFlYmMwZWFhLWY5N2YtNDU5NS04ZWExLWFlNmU1NDFmNDZjNg== {\"subject\":{\"id\":\"alice@acmecorp.com\",\"type\":\"super_admin\",\"properties\":null},\"resource\":{\"id\":\"123\",\"type\":\"account\",\"properties\":null},\"action\":{\"name\":\"can_read\",\"properties\":{\"method\":\"GET\"}},\"context\":{\"properties\":null}} ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 132 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:21 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=d4f99d9f-5b94-4863-a020-73f6fb62c5e8; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"decision\":true,\"context\":{\"id\":\"9e04dd22-e980-4e54-bc04-d64a0c2e1afe\",\"reason_admin\":{\"reason\":\"super_admin\"},\"reason_user\":null}}", "title": "Full successful Access Evaluation Flow sample"}, {"location": "janssen-server/auth-server/endpoints/archived-jwks-uri/", "tags": ["administration", "auth-server", "jwks", "json-web-key-set", "endpoint"], "text": "Overview # Janssen Server supports /jwks/archived/{kid} metadata endpoint and publishes its Archived JSON Web Keys (JWKs) at this endpoint. This endpoint publishes expired signing keys as well as expired encryption keys used by Janssen Server. RP can use these keys to validate signatures from Janssen Server, and also to perform encryption and decryption if keys are no longer present in /jwks endpoint. Like other metadata endpoints, this is not a secure endpoint. URL to access archived jwks endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration archived_jwks_uri claim in the response specifies the URL for archived jwks endpoint. By default, the archived jwks endpoint looks like below: https://janssen.server.host/jans-auth/restv1/jwks/archived/{kid} This endpoint is always enabled and can not be disabled using feature flags. Configuration Properties # Archived JWKs endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . archivedJwksUri archivedJwkLifetimeInSeconds If archivedJwkLifetimeInSeconds is not set then AS falls back to one year expiration. After archived jwk lifetime is passed, jwk is removed from archive. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Archived JWKS URI"}, {"location": "janssen-server/auth-server/endpoints/archived-jwks-uri/#overview", "text": "Janssen Server supports /jwks/archived/{kid} metadata endpoint and publishes its Archived JSON Web Keys (JWKs) at this endpoint. This endpoint publishes expired signing keys as well as expired encryption keys used by Janssen Server. RP can use these keys to validate signatures from Janssen Server, and also to perform encryption and decryption if keys are no longer present in /jwks endpoint. Like other metadata endpoints, this is not a secure endpoint. URL to access archived jwks endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration archived_jwks_uri claim in the response specifies the URL for archived jwks endpoint. By default, the archived jwks endpoint looks like below: https://janssen.server.host/jans-auth/restv1/jwks/archived/{kid} This endpoint is always enabled and can not be disabled using feature flags.", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/archived-jwks-uri/#configuration-properties", "text": "Archived JWKs endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . archivedJwksUri archivedJwkLifetimeInSeconds If archivedJwkLifetimeInSeconds is not set then AS falls back to one year expiration. After archived jwk lifetime is passed, jwk is removed from archive.", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/archived-jwks-uri/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/", "tags": ["administration", "auth-server", "authorization-challenge", "endpoint"], "text": "Overview # Authorization Challenge Endpoint allows first-party native client obtain authorization code which later can be exchanged on access token. This can provide an entirely browserless OAuth 2.0 experience suited for native applications. This endpoint conforms to OAuth 2.0 for First-Party Applications specifications. URL to access authorization challenge endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration authorization_challenge_endpoint claim in the response specifies the URL for authorization challenge endpoint. By default, authorization challenge endpoint looks like below: https://janssen.server.host/jans-auth/restv1/authorize-challenge In order to call Authorization Challenge Endpoint client must have authorization_challenge scope. If scope is not present AS rejects call with 401 (unauthorized) http status code. Authorization Challenge Endpoint supports Proof Key for Code Exchange (PKCE). More information about request and response of the authorization challenge endpoint can be found in the OpenAPI specification of jans-auth-server module . Sample request POST /authorize HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded login_hint=%2B1-310-123-4567&scope=profile &client_id=bb16c14c73415 Sample successful response with authorization_code . HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store { \"authorization_code\": \"uY29tL2F1dGhlbnRpY\" } Sample error response HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"username_required\" } Configuration Properties # Authorization Challenge Endpoint AS configuration: authorizationChallengeEndpoint - The authorization challenge endpoint URL authorizationChallengeDefaultAcr - Authorization Challenge Endpoint Default ACR if no value is specified in acr_values request parameter. Default value is default_challenge . authorizationChallengeShouldGenerateSession - Boolean value specifying whether to generate session_id (AS object and cookie) during authorization at Authorization Challenge Endpoint. Default value is false . mtlsAuthorizationChallengeEndpoint - URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Authorization Challenge Endpoint. Custom script # AS provides AuthorizationChallengeType custom script which must be used to control Authorization Challenge Endpoint behaviour. If request does not have acr_values specified and script name falls back to default_challenge which is available and enabled during installation. Default script name can be changed via authorizationChallengeDefaultAcr configuration property. Main method return true/false which indicates to server whether to issue authorization_code in response or not. If parameters is not present then error has to be created and false returned. If all is good script has to return true and it's strongly recommended to set user context.getExecutionContext().setUser(user); so AS can keep tracking what exactly user is authenticated. Please see following snippet below: public boolean authorize ( Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. validate all required parameters are present final String username = getParameterOrCreateError ( context , USERNAME_PARAMETER ); if ( StringUtils . isBlank ( username )) { return false ; } final String password = getParameterOrCreateError ( context , PASSWORD_PARAMETER ); if ( StringUtils . isBlank ( password )) { return false ; } scriptLogger . trace ( \"All required parameters are present\" ); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil . bean ( UserService . class ); PersistenceEntryManager entryManager = CdiUtil . bean ( PersistenceEntryManager . class ); final User user = userService . getUser ( username ); if ( user == null ) { scriptLogger . trace ( \"User is not found by username {}\" , username ); createError ( context , \"username_invalid\" ); return false ; } final boolean ok = entryManager . authenticate ( user . getDn (), User . class , password ); if ( ok ) { context . getExecutionContext (). setUser ( user ); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger . trace ( \"User {} is authenticated successfully.\" , username ); return true ; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger . trace ( \"Failed to authenticate user {}. Please check username and password.\" , username ); createError ( context , \"username_or_password_invalid\" ); return false ; } More details in Authorization Challenge Custom Script Page . Full sample script can be found here Auth session # Auth session is optional. AS does not return it by default. It's possible to pass in request use_auth_session=true which makes AS return it in error response. If it is desired to use auth_session and don't pass client_id (or other parameters) in next request, it should be put in attributes of auth_session object. auth_session object lifetime is set by authorizationChallengeSessionLifetimeInSeconds AS configuration property. If authorizationChallengeSessionLifetimeInSeconds is not set then value falls back to 86400 seconds. Example String clientId = context . getHttpRequest (). getParameter ( \"client_id\" ); authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"client_id\" , clientId ); AS automatically validates DPoP if it is set during auth session creation. Thus it's recommended to set jkt of the auth session if DPoP is used. final String dpop = context . getHttpRequest (). getHeader ( DpopService . DPOP ); if ( StringUtils . isNotBlank ( dpop )) { authorizationChallengeSessionObject . getAttributes (). setJkt ( getDpopJkt ( dpop )); } Full sample script can be found here Web session # Authorization challenge script is first-party flow and thus web session is not created by default. However there can be cases when such session has to be created. Please set authorizationChallengeShouldGenerateSession configuration property to true to force session creation. In case it is needed to prepare session with specific data, it is possible to create session in script and set it into context. Example: SessionIdService sessionIdService = CdiUtil . bean ( SessionIdService . class ); Identity identityService = CdiUtil . bean ( Identity . class ); Map < String , String > sessionStore = new HashMap < String , String > (); sessionStore . put ( \"login_id_token\" , login_id_token ); sessionStore . put ( \"login_access_token\" , login_access_token ); sessionStore . put ( \"transaction_status\" , \"PENDING\" ); SessionId sessionId = sessionIdService . generateAuthenticatedSessionId ( context . getHttpRequest (), user . getDn (), sessionStore ); context . getExecutionContext (). setAuthorizationChallengeSessionId ( sessionId ); scriptLogger . trace ( \"Created Authorization challenge session successfully\" ); Multi-step example # Sometimes it's required to send data sequentially. Step by step. Calls to Authorization Challenge Endpoint must have use_auth_session=true parameter to force tracking data between request. Lets consider example when RP first sends username and then in next request OTP . POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded username=alice &scope=photos &client_id=bb16c14c73415 AS accepts username and returns back error with auth_session . HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"otp_required\", \"auth_session\": \"ce6772f5e07bc8361572f\" } In next call RP can send OTP and auth_session (AS matches user from auth_session ) POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded otp=ccnnju667d&auth_session=ce6772f5e07bc8361572f In custom script it's easy to code what data has to be kept in auth_session . private void createError(ExternalScriptContext context, String errorCode) { String deviceSessionPart = prepareDeviceSessionSubJson(context); final String entity = String.format(\"{\\\"error\\\": \\\"%s\\\"%s}\", errorCode, deviceSessionPart); context.createWebApplicationException(401, entity); } private String prepareDeviceSessionSubJson(ExternalScriptContext context) { DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { prepareDeviceSession(context, authorizationChallengeSessionObject); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } else if (context.getAuthzRequest().isUseDeviceSession()) { authorizationChallengeSessionObject = prepareDeviceSession(context, null); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } return \"\"; } private DeviceSession prepareDeviceSession(ExternalScriptContext context, DeviceSession authorizationChallengeSessionObject) { DeviceSessionService deviceSessionService = CdiUtil.bean(DeviceSessionService.class); boolean newSave = authorizationChallengeSessionObject == null; if (newSave) { authorizationChallengeSessionObject = deviceSessionService.newDeviceSession(); } String username = context.getHttpRequest().getParameter(USERNAME_PARAMETER); if (StringUtils.isNotBlank(username)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(USERNAME_PARAMETER, username); } String otp = context.getHttpRequest().getParameter(OTP_PARAMETER); if (StringUtils.isNotBlank(otp)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(OTP_PARAMETER, otp); } String clientId = context.getHttpRequest().getParameter(\"client_id\"); if (StringUtils.isNotBlank(clientId)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"client_id\", clientId); } String acrValues = context.getHttpRequest().getParameter(\"acr_values\"); if (StringUtils.isNotBlank(acrValues)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"acr_values\", acrValues); } if (newSave) { deviceSessionService.persist(authorizationChallengeSessionObject); } else { deviceSessionService.merge(authorizationChallengeSessionObject); } return authorizationChallengeSessionObject; } More details in Authorization Challenge Custom Script Page . Full multi-step sample script can be found here Full successful Authorization Challenge Flow sample # OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 6244 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:04 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=fa097a44-5568-48aa-9390-1880616e5a69; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://yuriyz-fond-skink.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"phone_number_verified\", \"room_number\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"query\", \"jwt\", \"query.jwt\", \"form_post.jwt\", \"form_post\", \"fragment\", \"fragment.jwt\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code\", \"code id_token token\", \"id_token\", \"code id_token\", \"token\", \"id_token token\", \"code token\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:device_code\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"implicit\", \"authorization_code\", \"password\", \"refresh_token\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/userinfo\", \"authorization_challenge_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize-challenge\", \"op_tos_uri\" : \"https://yuriyz-fond-skink.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"key_from_java\" : \"value_from_script_on_java\", \"session_revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"user_name\", \"clientinfo\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"https://jans.io/scim/users.read\", \"device_sso\", \"phone\", \"mobile_phone\", \"offline_access\", \"email\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: authorizationChallengeFlow ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"jans test app\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1633 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:05 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=81dc6c45-7831-4738-b169-b087ee9a6bd6; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register?client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"28a50db3-b6d1-4054-a259-ef7168afa760\", \"client_id\": \"999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid\", \"client_secret\": \"f6364c5c-295d-4e6e-bb40-6ad3a47b2119\", \"client_id_issued_at\": 1691668385, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"jans test app\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"authorization_code\", \"refresh_token\" ], \"subject_type\": \"public\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1691704385, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea&scope=openid+profile+address+email+phone+user_name&state=b4a41b29-51c8-4354-9c8c-fda38b4dbd43&nonce=3a56f8d0-f78e-4b15-857c-3e792801be68&prompt=&ui_locales=&claims_locales=&acr_values=&request_session_id=false&password=secret&username=admin ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-transform, no-store Connection: Keep-Alive Content-Length: 61 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:06 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=3aa95eb7-73e2-40ae-9303-34adf30a1a05; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"authorization_code\":\"9e3dc65b-937a-49c2-bdff-41fbc1a352d0\"} Successfully obtained authorization code 9e3dc65b-937a-49c2-bdff-41fbc1a352d0 at Authorization Challenge Endpoint ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/x-www-form-urlencoded Authorization: Basic OTk5ZTEzYjgtZjRhMi00ZmVkLWFkM2MtNmM4OGJkMmM5MmVhOmY2MzY0YzVjLTI5NWQtNGU2ZS1iYjQwLTZhZDNhNDdiMjExOQ== grant_type=authorization_code&code=9e3dc65b-937a-49c2-bdff-41fbc1a352d0&redirect_uri=https%3A%2F%2Fyuriyz-fond-skink.gluu.info%2Fjans-auth-rp%2Fhome.htm ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1250 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:06 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=3eb3c205-6206-4a70-98fb-75bf81757976; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"access_token\":\"d87aa8d2-fefb-4d16-a775-9b9d27f73bfc\",\"refresh_token\":\"505314a7-05f5-4c9f-8900-ccb0685dea17\",\"id_token\":\"eyJraWQiOiJjb25uZWN0XzI1OGZmMmFiLWE4ODQtNDIxNy1iNmQ4LTJhMGI2NDhmOTcxZF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiUC04RktlejhlNHROTURTbVlGeHV5dyIsInN1YiI6IjI1Nzg0ZDQ5LTg0ZjMtNGIyNi1hZWUyLTEwNDkzMzM5MjMyZCIsImFtciI6W10sImlzcyI6Imh0dHBzOi8veXVyaXl6LWZvbmQtc2tpbmsuZ2x1dS5pbmZvIiwibm9uY2UiOiIzYTU2ZjhkMC1mNzhlLTRiMTUtODU3Yy0zZTc5MjgwMWJlNjgiLCJqYW5zT3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCIsImF1ZCI6Ijk5OWUxM2I4LWY0YTItNGZlZC1hZDNjLTZjODhiZDJjOTJlYSIsInJhbmRvbSI6ImJmYmI5OTBmLWNkYTEtNGM3OC1hNjM4LWFhN2NiMjc5MjU3MiIsImFjciI6ImRlZmF1bHRfY2hhbGxlbmdlIiwiY19oYXNoIjoiTnFoSGFIenZZYjYxeDFackQwUEZVdyIsImF1dGhfdGltZSI6MTY5MTY2ODM4NiwiZXhwIjoxNjkxNjcxOTg2LCJncmFudCI6ImF1dGhvcml6YXRpb25fY29kZSIsImlhdCI6MTY5MTY2ODM4Nn0.QTUmzJaHtbPGjrV4E0MUn_fU1On44B6-_7pT0Dz_cY29s_KajGLfin3G_WsYmZA--ysyRLAmdK_X5C3W-wpkpDJ8906vuZST5547lSJGOZ45_VFv7XnTmBip3zRQOmrlxdU6OQ5Vmj3xMON_NQ-ckEUSNr65xWTAPmOQoncGYp8s-TO7ethyx6UyDTnW8d1YiXWCUYfQDQ8d5wCPHnfoYAsZCs_f0xaBUmaiwvUL3ckiXgMr2yHjWKWQuezlbjJk7ODu2cgoAzs3IWMonaixIJeeJJcOvFB4SPTnbToJe7ISvvsZTEwrLWW_E_LgTUEDqHbeWyeQI8WqDa9EOwMEFw\",\"token_type\":\"Bearer\",\"expires_in\":299} ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/x-www-form-urlencoded Authorization: Basic OTk5ZTEzYjgtZjRhMi00ZmVkLWFkM2MtNmM4OGJkMmM5MmVhOmY2MzY0YzVjLTI5NWQtNGU2ZS1iYjQwLTZhZDNhNDdiMjExOQ== grant_type=refresh_token&refresh_token=505314a7-05f5-4c9f-8900-ccb0685dea17 ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store Connection: Keep-Alive Content-Length: 166 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:08 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=88a6b7a5-3230-4f0f-b859-09df77a5c67a; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"access_token\":\"572f6422-caf9-496a-a6be-4ab39c872816\",\"refresh_token\":\"e93b6576-5297-4d9d-a92b-3276d90a75e4\",\"scope\":\"openid\",\"token_type\":\"Bearer\",\"expires_in\":299} ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /jans-auth/restv1/userinfo HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Authorization: Bearer 572f6422-caf9-496a-a6be-4ab39c872816 ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store, private Connection: Keep-Alive Content-Length: 46 Content-Type: application/json;charset=utf-8 Date: Thu, 10 Aug 2023 11:53:08 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=390c7a63-fe06-48a5-b3bf-2549267ba9b0; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"sub\":\"25784d49-84f3-4b26-aee2-10493339232d\"} Authorization Challenge Flow sample with invalid user # OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 6244 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:01 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=79c5fed3-d69a-4fdf-af88-fce550cd1819; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://yuriyz-fond-skink.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"phone_number_verified\", \"room_number\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"query\", \"jwt\", \"query.jwt\", \"form_post.jwt\", \"form_post\", \"fragment\", \"fragment.jwt\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code\", \"code id_token token\", \"id_token\", \"code id_token\", \"token\", \"id_token token\", \"code token\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:device_code\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"implicit\", \"authorization_code\", \"password\", \"refresh_token\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/userinfo\", \"authorization_challenge_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize-challenge\", \"op_tos_uri\" : \"https://yuriyz-fond-skink.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"key_from_java\" : \"value_from_script_on_java\", \"session_revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"user_name\", \"clientinfo\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"https://jans.io/scim/users.read\", \"device_sso\", \"phone\", \"mobile_phone\", \"offline_access\", \"email\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: authorizationChallengeFlow ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"jans test app\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1633 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:02 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=7045173c-9a96-418a-86ed-47a09749b004; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register?client_id=d93a5129-1546-4b9b-bf8c-ea19e36ea2c8\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"67aa99de-e977-4562-955d-6292f2c95df4\", \"client_id\": \"d93a5129-1546-4b9b-bf8c-ea19e36ea2c8\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid\", \"client_secret\": \"f921c89c-57f0-4a91-baaa-036a4a22737b\", \"client_id_issued_at\": 1691668622, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"jans test app\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"authorization_code\", \"refresh_token\" ], \"subject_type\": \"public\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1691704622, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=d93a5129-1546-4b9b-bf8c-ea19e36ea2c8&scope=openid+profile+address+email+phone+user_name&state=4f925a8d-287a-4cba-a174-04d2e56109df&nonce=84c9b6dd-635c-4ca4-bba1-35c53c51a339&prompt=&ui_locales=&claims_locales=&acr_values=&request_session_id=false&password=secret&username=invalidUser ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 401 Cache-Control: no-transform, no-store Connection: Keep-Alive Content-Length: 29 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:02 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=4c89e007-6c77-43da-a67f-b7ee1ff0e60a; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"error\": \"username_invalid\"}", "title": "Authorization Challenge"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#overview", "text": "Authorization Challenge Endpoint allows first-party native client obtain authorization code which later can be exchanged on access token. This can provide an entirely browserless OAuth 2.0 experience suited for native applications. This endpoint conforms to OAuth 2.0 for First-Party Applications specifications. URL to access authorization challenge endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration authorization_challenge_endpoint claim in the response specifies the URL for authorization challenge endpoint. By default, authorization challenge endpoint looks like below: https://janssen.server.host/jans-auth/restv1/authorize-challenge In order to call Authorization Challenge Endpoint client must have authorization_challenge scope. If scope is not present AS rejects call with 401 (unauthorized) http status code. Authorization Challenge Endpoint supports Proof Key for Code Exchange (PKCE). More information about request and response of the authorization challenge endpoint can be found in the OpenAPI specification of jans-auth-server module . Sample request POST /authorize HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded login_hint=%2B1-310-123-4567&scope=profile &client_id=bb16c14c73415 Sample successful response with authorization_code . HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store { \"authorization_code\": \"uY29tL2F1dGhlbnRpY\" } Sample error response HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"username_required\" }", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#configuration-properties", "text": "Authorization Challenge Endpoint AS configuration: authorizationChallengeEndpoint - The authorization challenge endpoint URL authorizationChallengeDefaultAcr - Authorization Challenge Endpoint Default ACR if no value is specified in acr_values request parameter. Default value is default_challenge . authorizationChallengeShouldGenerateSession - Boolean value specifying whether to generate session_id (AS object and cookie) during authorization at Authorization Challenge Endpoint. Default value is false . mtlsAuthorizationChallengeEndpoint - URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Authorization Challenge Endpoint.", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#custom-script", "text": "AS provides AuthorizationChallengeType custom script which must be used to control Authorization Challenge Endpoint behaviour. If request does not have acr_values specified and script name falls back to default_challenge which is available and enabled during installation. Default script name can be changed via authorizationChallengeDefaultAcr configuration property. Main method return true/false which indicates to server whether to issue authorization_code in response or not. If parameters is not present then error has to be created and false returned. If all is good script has to return true and it's strongly recommended to set user context.getExecutionContext().setUser(user); so AS can keep tracking what exactly user is authenticated. Please see following snippet below: public boolean authorize ( Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. validate all required parameters are present final String username = getParameterOrCreateError ( context , USERNAME_PARAMETER ); if ( StringUtils . isBlank ( username )) { return false ; } final String password = getParameterOrCreateError ( context , PASSWORD_PARAMETER ); if ( StringUtils . isBlank ( password )) { return false ; } scriptLogger . trace ( \"All required parameters are present\" ); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil . bean ( UserService . class ); PersistenceEntryManager entryManager = CdiUtil . bean ( PersistenceEntryManager . class ); final User user = userService . getUser ( username ); if ( user == null ) { scriptLogger . trace ( \"User is not found by username {}\" , username ); createError ( context , \"username_invalid\" ); return false ; } final boolean ok = entryManager . authenticate ( user . getDn (), User . class , password ); if ( ok ) { context . getExecutionContext (). setUser ( user ); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger . trace ( \"User {} is authenticated successfully.\" , username ); return true ; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger . trace ( \"Failed to authenticate user {}. Please check username and password.\" , username ); createError ( context , \"username_or_password_invalid\" ); return false ; } More details in Authorization Challenge Custom Script Page . Full sample script can be found here", "title": "Custom script"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#auth-session", "text": "Auth session is optional. AS does not return it by default. It's possible to pass in request use_auth_session=true which makes AS return it in error response. If it is desired to use auth_session and don't pass client_id (or other parameters) in next request, it should be put in attributes of auth_session object. auth_session object lifetime is set by authorizationChallengeSessionLifetimeInSeconds AS configuration property. If authorizationChallengeSessionLifetimeInSeconds is not set then value falls back to 86400 seconds. Example String clientId = context . getHttpRequest (). getParameter ( \"client_id\" ); authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"client_id\" , clientId ); AS automatically validates DPoP if it is set during auth session creation. Thus it's recommended to set jkt of the auth session if DPoP is used. final String dpop = context . getHttpRequest (). getHeader ( DpopService . DPOP ); if ( StringUtils . isNotBlank ( dpop )) { authorizationChallengeSessionObject . getAttributes (). setJkt ( getDpopJkt ( dpop )); } Full sample script can be found here", "title": "Auth session"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#web-session", "text": "Authorization challenge script is first-party flow and thus web session is not created by default. However there can be cases when such session has to be created. Please set authorizationChallengeShouldGenerateSession configuration property to true to force session creation. In case it is needed to prepare session with specific data, it is possible to create session in script and set it into context. Example: SessionIdService sessionIdService = CdiUtil . bean ( SessionIdService . class ); Identity identityService = CdiUtil . bean ( Identity . class ); Map < String , String > sessionStore = new HashMap < String , String > (); sessionStore . put ( \"login_id_token\" , login_id_token ); sessionStore . put ( \"login_access_token\" , login_access_token ); sessionStore . put ( \"transaction_status\" , \"PENDING\" ); SessionId sessionId = sessionIdService . generateAuthenticatedSessionId ( context . getHttpRequest (), user . getDn (), sessionStore ); context . getExecutionContext (). setAuthorizationChallengeSessionId ( sessionId ); scriptLogger . trace ( \"Created Authorization challenge session successfully\" );", "title": "Web session"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#multi-step-example", "text": "Sometimes it's required to send data sequentially. Step by step. Calls to Authorization Challenge Endpoint must have use_auth_session=true parameter to force tracking data between request. Lets consider example when RP first sends username and then in next request OTP . POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded username=alice &scope=photos &client_id=bb16c14c73415 AS accepts username and returns back error with auth_session . HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"otp_required\", \"auth_session\": \"ce6772f5e07bc8361572f\" } In next call RP can send OTP and auth_session (AS matches user from auth_session ) POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded otp=ccnnju667d&auth_session=ce6772f5e07bc8361572f In custom script it's easy to code what data has to be kept in auth_session . private void createError(ExternalScriptContext context, String errorCode) { String deviceSessionPart = prepareDeviceSessionSubJson(context); final String entity = String.format(\"{\\\"error\\\": \\\"%s\\\"%s}\", errorCode, deviceSessionPart); context.createWebApplicationException(401, entity); } private String prepareDeviceSessionSubJson(ExternalScriptContext context) { DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { prepareDeviceSession(context, authorizationChallengeSessionObject); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } else if (context.getAuthzRequest().isUseDeviceSession()) { authorizationChallengeSessionObject = prepareDeviceSession(context, null); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } return \"\"; } private DeviceSession prepareDeviceSession(ExternalScriptContext context, DeviceSession authorizationChallengeSessionObject) { DeviceSessionService deviceSessionService = CdiUtil.bean(DeviceSessionService.class); boolean newSave = authorizationChallengeSessionObject == null; if (newSave) { authorizationChallengeSessionObject = deviceSessionService.newDeviceSession(); } String username = context.getHttpRequest().getParameter(USERNAME_PARAMETER); if (StringUtils.isNotBlank(username)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(USERNAME_PARAMETER, username); } String otp = context.getHttpRequest().getParameter(OTP_PARAMETER); if (StringUtils.isNotBlank(otp)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(OTP_PARAMETER, otp); } String clientId = context.getHttpRequest().getParameter(\"client_id\"); if (StringUtils.isNotBlank(clientId)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"client_id\", clientId); } String acrValues = context.getHttpRequest().getParameter(\"acr_values\"); if (StringUtils.isNotBlank(acrValues)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"acr_values\", acrValues); } if (newSave) { deviceSessionService.persist(authorizationChallengeSessionObject); } else { deviceSessionService.merge(authorizationChallengeSessionObject); } return authorizationChallengeSessionObject; } More details in Authorization Challenge Custom Script Page . Full multi-step sample script can be found here", "title": "Multi-step example"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#full-successful-authorization-challenge-flow-sample", "text": "OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 6244 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:04 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=fa097a44-5568-48aa-9390-1880616e5a69; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://yuriyz-fond-skink.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"phone_number_verified\", \"room_number\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"query\", \"jwt\", \"query.jwt\", \"form_post.jwt\", \"form_post\", \"fragment\", \"fragment.jwt\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code\", \"code id_token token\", \"id_token\", \"code id_token\", \"token\", \"id_token token\", \"code token\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:device_code\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"implicit\", \"authorization_code\", \"password\", \"refresh_token\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/userinfo\", \"authorization_challenge_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize-challenge\", \"op_tos_uri\" : \"https://yuriyz-fond-skink.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"key_from_java\" : \"value_from_script_on_java\", \"session_revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"user_name\", \"clientinfo\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"https://jans.io/scim/users.read\", \"device_sso\", \"phone\", \"mobile_phone\", \"offline_access\", \"email\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: authorizationChallengeFlow ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"jans test app\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1633 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:05 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=81dc6c45-7831-4738-b169-b087ee9a6bd6; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register?client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"28a50db3-b6d1-4054-a259-ef7168afa760\", \"client_id\": \"999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid\", \"client_secret\": \"f6364c5c-295d-4e6e-bb40-6ad3a47b2119\", \"client_id_issued_at\": 1691668385, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"jans test app\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"authorization_code\", \"refresh_token\" ], \"subject_type\": \"public\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1691704385, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea&scope=openid+profile+address+email+phone+user_name&state=b4a41b29-51c8-4354-9c8c-fda38b4dbd43&nonce=3a56f8d0-f78e-4b15-857c-3e792801be68&prompt=&ui_locales=&claims_locales=&acr_values=&request_session_id=false&password=secret&username=admin ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-transform, no-store Connection: Keep-Alive Content-Length: 61 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:06 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=3aa95eb7-73e2-40ae-9303-34adf30a1a05; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"authorization_code\":\"9e3dc65b-937a-49c2-bdff-41fbc1a352d0\"} Successfully obtained authorization code 9e3dc65b-937a-49c2-bdff-41fbc1a352d0 at Authorization Challenge Endpoint ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/x-www-form-urlencoded Authorization: Basic OTk5ZTEzYjgtZjRhMi00ZmVkLWFkM2MtNmM4OGJkMmM5MmVhOmY2MzY0YzVjLTI5NWQtNGU2ZS1iYjQwLTZhZDNhNDdiMjExOQ== grant_type=authorization_code&code=9e3dc65b-937a-49c2-bdff-41fbc1a352d0&redirect_uri=https%3A%2F%2Fyuriyz-fond-skink.gluu.info%2Fjans-auth-rp%2Fhome.htm ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1250 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:06 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=3eb3c205-6206-4a70-98fb-75bf81757976; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"access_token\":\"d87aa8d2-fefb-4d16-a775-9b9d27f73bfc\",\"refresh_token\":\"505314a7-05f5-4c9f-8900-ccb0685dea17\",\"id_token\":\"eyJraWQiOiJjb25uZWN0XzI1OGZmMmFiLWE4ODQtNDIxNy1iNmQ4LTJhMGI2NDhmOTcxZF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiUC04RktlejhlNHROTURTbVlGeHV5dyIsInN1YiI6IjI1Nzg0ZDQ5LTg0ZjMtNGIyNi1hZWUyLTEwNDkzMzM5MjMyZCIsImFtciI6W10sImlzcyI6Imh0dHBzOi8veXVyaXl6LWZvbmQtc2tpbmsuZ2x1dS5pbmZvIiwibm9uY2UiOiIzYTU2ZjhkMC1mNzhlLTRiMTUtODU3Yy0zZTc5MjgwMWJlNjgiLCJqYW5zT3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCIsImF1ZCI6Ijk5OWUxM2I4LWY0YTItNGZlZC1hZDNjLTZjODhiZDJjOTJlYSIsInJhbmRvbSI6ImJmYmI5OTBmLWNkYTEtNGM3OC1hNjM4LWFhN2NiMjc5MjU3MiIsImFjciI6ImRlZmF1bHRfY2hhbGxlbmdlIiwiY19oYXNoIjoiTnFoSGFIenZZYjYxeDFackQwUEZVdyIsImF1dGhfdGltZSI6MTY5MTY2ODM4NiwiZXhwIjoxNjkxNjcxOTg2LCJncmFudCI6ImF1dGhvcml6YXRpb25fY29kZSIsImlhdCI6MTY5MTY2ODM4Nn0.QTUmzJaHtbPGjrV4E0MUn_fU1On44B6-_7pT0Dz_cY29s_KajGLfin3G_WsYmZA--ysyRLAmdK_X5C3W-wpkpDJ8906vuZST5547lSJGOZ45_VFv7XnTmBip3zRQOmrlxdU6OQ5Vmj3xMON_NQ-ckEUSNr65xWTAPmOQoncGYp8s-TO7ethyx6UyDTnW8d1YiXWCUYfQDQ8d5wCPHnfoYAsZCs_f0xaBUmaiwvUL3ckiXgMr2yHjWKWQuezlbjJk7ODu2cgoAzs3IWMonaixIJeeJJcOvFB4SPTnbToJe7ISvvsZTEwrLWW_E_LgTUEDqHbeWyeQI8WqDa9EOwMEFw\",\"token_type\":\"Bearer\",\"expires_in\":299} ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/x-www-form-urlencoded Authorization: Basic OTk5ZTEzYjgtZjRhMi00ZmVkLWFkM2MtNmM4OGJkMmM5MmVhOmY2MzY0YzVjLTI5NWQtNGU2ZS1iYjQwLTZhZDNhNDdiMjExOQ== grant_type=refresh_token&refresh_token=505314a7-05f5-4c9f-8900-ccb0685dea17 ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store Connection: Keep-Alive Content-Length: 166 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:08 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=88a6b7a5-3230-4f0f-b859-09df77a5c67a; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"access_token\":\"572f6422-caf9-496a-a6be-4ab39c872816\",\"refresh_token\":\"e93b6576-5297-4d9d-a92b-3276d90a75e4\",\"scope\":\"openid\",\"token_type\":\"Bearer\",\"expires_in\":299} ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /jans-auth/restv1/userinfo HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Authorization: Bearer 572f6422-caf9-496a-a6be-4ab39c872816 ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store, private Connection: Keep-Alive Content-Length: 46 Content-Type: application/json;charset=utf-8 Date: Thu, 10 Aug 2023 11:53:08 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=390c7a63-fe06-48a5-b3bf-2549267ba9b0; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"sub\":\"25784d49-84f3-4b26-aee2-10493339232d\"}", "title": "Full successful Authorization Challenge Flow sample"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#authorization-challenge-flow-sample-with-invalid-user", "text": "OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 6244 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:01 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=79c5fed3-d69a-4fdf-af88-fce550cd1819; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://yuriyz-fond-skink.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"phone_number_verified\", \"room_number\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"query\", \"jwt\", \"query.jwt\", \"form_post.jwt\", \"form_post\", \"fragment\", \"fragment.jwt\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code\", \"code id_token token\", \"id_token\", \"code id_token\", \"token\", \"id_token token\", \"code token\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:device_code\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"implicit\", \"authorization_code\", \"password\", \"refresh_token\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/userinfo\", \"authorization_challenge_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize-challenge\", \"op_tos_uri\" : \"https://yuriyz-fond-skink.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"key_from_java\" : \"value_from_script_on_java\", \"session_revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"user_name\", \"clientinfo\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"https://jans.io/scim/users.read\", \"device_sso\", \"phone\", \"mobile_phone\", \"offline_access\", \"email\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: authorizationChallengeFlow ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"jans test app\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1633 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:02 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=7045173c-9a96-418a-86ed-47a09749b004; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register?client_id=d93a5129-1546-4b9b-bf8c-ea19e36ea2c8\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"67aa99de-e977-4562-955d-6292f2c95df4\", \"client_id\": \"d93a5129-1546-4b9b-bf8c-ea19e36ea2c8\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid\", \"client_secret\": \"f921c89c-57f0-4a91-baaa-036a4a22737b\", \"client_id_issued_at\": 1691668622, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"jans test app\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"authorization_code\", \"refresh_token\" ], \"subject_type\": \"public\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1691704622, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=d93a5129-1546-4b9b-bf8c-ea19e36ea2c8&scope=openid+profile+address+email+phone+user_name&state=4f925a8d-287a-4cba-a174-04d2e56109df&nonce=84c9b6dd-635c-4ca4-bba1-35c53c51a339&prompt=&ui_locales=&claims_locales=&acr_values=&request_session_id=false&password=secret&username=invalidUser ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 401 Cache-Control: no-transform, no-store Connection: Keep-Alive Content-Length: 29 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:02 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=4c89e007-6c77-43da-a67f-b7ee1ff0e60a; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"error\": \"username_invalid\"}", "title": "Authorization Challenge Flow sample with invalid user"}, {"location": "janssen-server/auth-server/endpoints/authorization/", "tags": ["administration", "auth-server", "authorization", "endpoint"], "text": "Overview # Janssen Server exposes authorization endpoint compliant with OAuth2 framework . A client uses authorization endpoint to obtain an authorization grant. Based on response type requested by the client, the authorization endpoint issues an authorization code or an access token. Authorization endpoint is a protected endpoint which will require end-user authentication before issuing authorization code or access token. URL to access authorization endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration authorization_endpoint claim in the response specifies the URL for authorization endpoint. By default, authorization endpoint looks like below: https://janssen.server.host/jans-auth/restv1/authorize More information about request and response of the authorization endpoint can be found in the OpenAPI specification of jans-auth-server module . Configuration Properties # Authorization endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . issuer requirePkce fapiCompatibility forceSignedRequestObject authorizationCodeLifetime returnDeviceSecretFromAuthzEndpoint requestUriBlockList requireRequestObjectEncryption staticDecryptionKid requestUriHashVerificationEnabled legacyIdTokenClaims customHeadersWithAuthorizationResponse includeSidInResponse sessionIdRequestParameterEnabled returnDeviceSecretFromAuthzEndpoint requirePar cibaMaxExpirationTimeAllowedSec Required Client Configuration # Clients must be registered with Janssen Server as using code and/or implicit grant types in order to use authorization endpoint. Using Janssen Text-based UI(TUI) , client can be registered for appropriate grant type by navigating to Auth-Server -> Clients -> Add Client Using PKCE # Janssen Server supports PKCE , which recommended and more secure method for using code grant. PKCE can be enabled/disable by setting requirePkce property. Janssen server supports plain as well as s256 code challenge methods. Using PAR # As a separate endpoint, Janssen Server supports PAR (Pushed Authorization Requests) to enable authorization using more complex authorization requests and making it more secure at the same time. Use Janssen Server configuration property requirePar to accept only PAR requests. Using JARM # Authorization endpoint supports JWT Secured Authorization Response Mode, or JARM . Using JARM makes authorization responses more secure and compliant to be used in FAPI deployments. Janssen Server supports all response modes as defined in JARM specification Using Prompt Parameter # prompt request parameter is an ASCII string value that specifies whether the Authorization Server prompts the End-User for re-authentication and consent. Janssen Server supports none , login , consent , create and select_account values for prompt parameter. Multiple values can be specified by separating them with single space. Based on value/s of this request parameter Authorization Server prompts the End-User for re-authentication ( login ), consent or user registration details ( create ). Check Prompt page for more details. none # none value will instruct Janssen Server NOT to display any authentication or consent user interface pages. An error is returned if the End-User is not already authenticated or the Client does not have pre-configured consent for the requested scopes. This can be used as a method to check for existing authentication and/or consent. login # login value will instruct Janssen Server to prompt the End-User for re-authentication. consent # consent value will instruct Janssen Server to prompt the End-User for consent before returning information to the Client. select_account # select_account value will instruct Janssen Server to prompt the End-User to select a user account. This allows a user who has multiple accounts at the Authorization Server to select amongst the multiple accounts that they may have current sessions for. Configuring Authentication Methods # acr_values request parameter is used to specify authentication methods to be used by Janssen Server to authenticate the end user. Multiple acr values can be specified by separating them with a space. In order to use a particular acr value, the client needs to be authorized to use all the acr values in the list. If no the request doesn't specify any acr value then the default acr value configured for respective client is used by Janssen server for end user authentication. Customizing using Interception Scripts # Interception scripts allows flexibility to configure and customize multiple aspects in Janssen Server. For example, see this documentation to learn how person authentication and consent gathering can be customized using interception scripts. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Authorization"}, {"location": "janssen-server/auth-server/endpoints/authorization/#overview", "text": "Janssen Server exposes authorization endpoint compliant with OAuth2 framework . A client uses authorization endpoint to obtain an authorization grant. Based on response type requested by the client, the authorization endpoint issues an authorization code or an access token. Authorization endpoint is a protected endpoint which will require end-user authentication before issuing authorization code or access token. URL to access authorization endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration authorization_endpoint claim in the response specifies the URL for authorization endpoint. By default, authorization endpoint looks like below: https://janssen.server.host/jans-auth/restv1/authorize More information about request and response of the authorization endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/authorization/#configuration-properties", "text": "Authorization endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . issuer requirePkce fapiCompatibility forceSignedRequestObject authorizationCodeLifetime returnDeviceSecretFromAuthzEndpoint requestUriBlockList requireRequestObjectEncryption staticDecryptionKid requestUriHashVerificationEnabled legacyIdTokenClaims customHeadersWithAuthorizationResponse includeSidInResponse sessionIdRequestParameterEnabled returnDeviceSecretFromAuthzEndpoint requirePar cibaMaxExpirationTimeAllowedSec", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/authorization/#required-client-configuration", "text": "Clients must be registered with Janssen Server as using code and/or implicit grant types in order to use authorization endpoint. Using Janssen Text-based UI(TUI) , client can be registered for appropriate grant type by navigating to Auth-Server -> Clients -> Add Client", "title": "Required Client Configuration"}, {"location": "janssen-server/auth-server/endpoints/authorization/#using-pkce", "text": "Janssen Server supports PKCE , which recommended and more secure method for using code grant. PKCE can be enabled/disable by setting requirePkce property. Janssen server supports plain as well as s256 code challenge methods.", "title": "Using PKCE"}, {"location": "janssen-server/auth-server/endpoints/authorization/#using-par", "text": "As a separate endpoint, Janssen Server supports PAR (Pushed Authorization Requests) to enable authorization using more complex authorization requests and making it more secure at the same time. Use Janssen Server configuration property requirePar to accept only PAR requests.", "title": "Using PAR"}, {"location": "janssen-server/auth-server/endpoints/authorization/#using-jarm", "text": "Authorization endpoint supports JWT Secured Authorization Response Mode, or JARM . Using JARM makes authorization responses more secure and compliant to be used in FAPI deployments. Janssen Server supports all response modes as defined in JARM specification", "title": "Using JARM"}, {"location": "janssen-server/auth-server/endpoints/authorization/#using-prompt-parameter", "text": "prompt request parameter is an ASCII string value that specifies whether the Authorization Server prompts the End-User for re-authentication and consent. Janssen Server supports none , login , consent , create and select_account values for prompt parameter. Multiple values can be specified by separating them with single space. Based on value/s of this request parameter Authorization Server prompts the End-User for re-authentication ( login ), consent or user registration details ( create ). Check Prompt page for more details.", "title": "Using Prompt Parameter"}, {"location": "janssen-server/auth-server/endpoints/authorization/#none", "text": "none value will instruct Janssen Server NOT to display any authentication or consent user interface pages. An error is returned if the End-User is not already authenticated or the Client does not have pre-configured consent for the requested scopes. This can be used as a method to check for existing authentication and/or consent.", "title": "none"}, {"location": "janssen-server/auth-server/endpoints/authorization/#login", "text": "login value will instruct Janssen Server to prompt the End-User for re-authentication.", "title": "login"}, {"location": "janssen-server/auth-server/endpoints/authorization/#consent", "text": "consent value will instruct Janssen Server to prompt the End-User for consent before returning information to the Client.", "title": "consent"}, {"location": "janssen-server/auth-server/endpoints/authorization/#select_account", "text": "select_account value will instruct Janssen Server to prompt the End-User to select a user account. This allows a user who has multiple accounts at the Authorization Server to select amongst the multiple accounts that they may have current sessions for.", "title": "select_account"}, {"location": "janssen-server/auth-server/endpoints/authorization/#configuring-authentication-methods", "text": "acr_values request parameter is used to specify authentication methods to be used by Janssen Server to authenticate the end user. Multiple acr values can be specified by separating them with a space. In order to use a particular acr value, the client needs to be authorized to use all the acr values in the list. If no the request doesn't specify any acr value then the default acr value configured for respective client is used by Janssen server for end user authentication.", "title": "Configuring Authentication Methods"}, {"location": "janssen-server/auth-server/endpoints/authorization/#customizing-using-interception-scripts", "text": "Interception scripts allows flexibility to configure and customize multiple aspects in Janssen Server. For example, see this documentation to learn how person authentication and consent gathering can be customized using interception scripts.", "title": "Customizing using Interception Scripts"}, {"location": "janssen-server/auth-server/endpoints/authorization/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/", "tags": ["administration", "auth-server", "endpoint"], "text": "Backchannel authentication scripts # Janssen server enables domains to render the username/pw login form, avoiding the redirect to the IDP-hosted login page. Many SSO solutions offer a proprietary endpoint to accomplish this. However, in Janssen server, this is accomplished with the OAuth/OpenID framework by using a combination of calling the /token endpoint using the OAuth password flow, and then redirecting to browser to the /authorization endpoint, but auto-submitting the form. This article describes how to process login via backchannel and when browser is processing authorization, AS will recognize automatically the authenticated user, write cookies and then establish the session. Design # Source-code for sequence diagram Title password Grant with State Person->Browser: Navigate to website Browser->Website: Website->Browser:Display login page Person->Browser: Enter Username / PW Browser->Website: (creds) Website->IDP: /token?uid=_&pw=&browser_ip=_ IDP->Website: {\"redirect\": \"/authz/state=1F2D41A\", ...} Website->Browser: Browser->IDP: /authz?state=1F2D41A IDP->IDP: check IP address is\\n same as state IDP->Browser: write cookie / send redirect_uri Browser->Website: redirect_uri Solution # In order to process the whole authorization, idea is to use resource owner password credentials grant type in the first stage, over there process the authentication as we do today, but also write in cache a short-lived token to recognize such authenticated user, then return to the client such short-lived token. During authorization, browser should send that token as part of the custom params and in the AS we should verify if that user is already authenticated using the short-lived param in the cache, then AS will write cookies, create the session and return to the client information required for this. Jans App Configurations # Above the jans-auth record of the jansAppConf table, enable a new attribute on the jansConfDyn field Example: \"authorizationRequestCustomAllowedParameters\": [ { \"paramName\": \"bcAuthnToken\", \"returnInResponse\": true } ] Sample CURL 1. Obtain access token curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/jans-auth-server/config/properties.write\" 2. Apply patch curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"authorizationRequestCustomAllowedParameters\", \"value\": [ { \"paramName\": \"bcAuthnToken\", \"returnInResponse\": true } ] } ]' Custom Script Registration # In the table jansCustomScr enable 2 new scripts: 1. Script type resource_owner_password_credentials displayName ropc-backchannel [ropc-backchannel-script.py] See script below. 2. Script type person_autentication displayName backchannel-authentication [backchannel-authentication-script.py] See script below. Client Configuration # Associate script person_authentication on table jansClnt . Modify the jansAttrs field which contains a json and the ropcScripts field and add the dn from the ropc script record in the previous step Example: \"ropcScripts\": [ \"inum={SCRIPT_ID},ou=scripts,o=jans\", ], Flow # BcAuthToken request: # Firstly, the /token service is called to generate the bcAuthnToken (get it from the response header with the key Bc-Authn-Token ) In this request example, the client's basic credential is being used in order to authenticate the client, however you could use your preferred authn mode. Request curl --location --request POST 'https://jans.localhost/jans-auth/restv1/token' \\ --header 'Authorization: Basic MzE3MGNiYzUtMDAxOC00OWVmLThiYTYtMjY4MGI2NjhiZjBjOmFmNzk1ZjI1LWQ1MjktNDVlYi1iMTJlLWNjM2ExNTY5OTU1Ng==' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=password' \\ --data-urlencode 'username=test_user' \\ --data-urlencode 'password=test_user_password' \\ --data-urlencode 'custom1=your custom param 1' \\ --data-urlencode 'custom2=your custom param 2' \\ --data-urlencode 'scope=openid' Response HTTP/1.1 200 OK Date: Wed, 29 Jun 2022 14:03:25 GMT Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Bc-Authn-Token: dacfe4fc-d0ce-4673-9370-e66f652c4b7f Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1109 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive {\"access_token\":\"7a024a59-e132-4c05-9126-f4f36b3d3677\",\"refresh_token\":\"184c2b60-b5c7-4250-9850-97b0f531743c\",\"scope\":\"openid\",\"id_token\":\"eyJraWQiOiJmZGJhY2Q2Yi05YTY0LTQ2MWQtOWJlYy1jOTAyMjc5ZGI2ODZfc2lnX3JzMjU2IiwidHlwIjoiand0IiwiYWxnIjoiUlMyNTYifQ.eyJhdWQiOiIzMTcwY2JjNS0wMDE4LTQ5ZWYtOGJhNi0yNjgwYjY2OGJmMGMiLCJhY3IiOiJzaW1wbGVfcGFzc3dvcmRfYXV0aCIsInN1YiI6Il9Fa3p5aXlRdVBzUm1mYjh3WHlmTTB4U0xDckxwTDJGNnA3RWhEeWRBUHciLCJjb2RlIjoiNDY4MzQ2NjktOGQ1Yy00NmQxLTkwNWEtNmMzNDg3YzZlMDg3IiwiYW1yIjpbXSwiaXNzIjoiaHR0cHM6Ly9qYW5zLmxvY2FsaG9zdCIsImV4cCI6MTY1NjUxNTAwNiwiZ3JhbnQiOiJwYXNzd29yZCIsImlhdCI6MTY1NjUxMTQwNiwic2lkIjoiMTg0ZTllOTktNjFmNi00ZWNhLWE0ZmUtMTMwZmFmZDk1MjE1Iiwib3hPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIn0.hW0vReGYLzC2RyBHztSFbDYoaYHcCYxatX1lpzWqyW5U2S9eNp58mKKmvdZmMc229Sz5VxqfYflpWuI_6aXsLFR_KT9FY3exSRIRtPiD_fUETdhsVuKWavumVnjvwdAM6ytu5ORJx06DCxEgaG1uXmRiE9GoT8F1uqeo4NxURhVNXmMd2fiiUmgm1lt3-kNhlSg6vMDJS1Aq1idm-XhiSVy895BY-JdpLEGJEycPKr1lpsBTcmasbFNBJv6_orKWlvvgFCVxo7XmbH7Xnmqi6UUo30L6sULqmCsTLa6DaWYfGokHz_0xRflw_Ihv9wlVq8gSdOZGoMaVGzDdKlddZw\",\"token_type\":\"Bearer\",\"expires_in\":299} Authorize request: # Once you have gotten the bcAuthnToken from the previous /token call, you must call authorize attaching the bcAuthnToken as a parameter and in the acr_values param send the name of the backchannel-authentication registered in previous steps. This script will generate cookies and session associated with the browser if the BcAuthToken is valid. Example: https://jans.localhost/jans-auth/restv1/authorize?response_type=code&client_id=3170cbc5-0018-49ef-8ba6-2680b668bf0c&scope=openid+profile+address+email&redirect_uri=https://jans.localhost/jans-auth-rp/home.htm&state=2f78eaf1-d73e-49f2-8f50-e5faef80808a&nonce=92c3a631-db54-4ae9-bd53-caf92a4adbcf&prompt=&ui_locales=&claims_locales=&acr_values=backchannel-authentication&request_session_id=false&bcAuthnToken={your bcAuthnToken} This call will redirect to the redirect_uri that you sent as a parameter in the call and will receive a code as well, after that the process is more or less the same than the regular flow. Request /token: # With the code obtained previously, you must call /token again, adding the parameter code Request: curl --location --request POST 'https://jans.localhost/jans-auth/restv1/token' \\ --header 'Authorization: Basic MzlhNjlmYzAtNzNmYy00MWJhLWFiMGYtNDJhNWFmYWI2MjllOmJmMDRlZTM4LTM0MTktNGEzNS05YTI5LTcyODlmY2JkNzc2Zg==' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=authorization_code' \\ --data-urlencode 'code=d449a7b9-10f6-4320-b257-05fee91d3c16' \\ --data-urlencode 'redirect_uri=https://jans.localhost/jans-auth-rp/home.htm' Response: HTTP/1.1 200 OK Date: Wed, 29 Jun 2022 15:20:50 GMT Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1291 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive {\"access_token\":\"896b04a2-fcbe-4466-89b9-184930b8675b\",\"refresh_token\":\"843995ef-cd0e-4b2c-9b91-7c68081325ab\",\"id_token\":\"eyJraWQiOiJmZGJhY2Q2Yi05YTY0LTQ2MWQtOWJlYy1jOTAyMjc5ZGI2ODZfc2lnX3JzMjU2IiwidHlwIjoiand0IiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoiMmx5OXh5emthMmc2T09HcVRPTmhqdyIsInN1YiI6Il9Fa3p5aXlRdVBzUm1mYjh3WHlmTTB4U0xDckxwTDJGNnA3RWhEeWRBUHciLCJjb2RlIjoiMjdiNjM0NTItMTE1My00ZDk5LTlkYzQtYzMyNGRmNjIwYWE0IiwiYW1yIjpbIjEwIl0sImlzcyI6Imh0dHBzOi8vamFucy5sb2NhbGhvc3QiLCJub25jZSI6IjkyYzNhNjMxLWRiNTQtNGFlOS1iZDUzLWNhZjkyYTRhZGJjZiIsInNpZCI6ImQzZDFlOWY2LWE1NTMtNDI2ZC04MWQ1LTE0YTFiZjg0MDJhNCIsIm94T3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCIsImF1ZCI6IjMxNzBjYmM1LTAwMTgtNDllZi04YmE2LTI2ODBiNjY4YmYwYyIsImFjciI6InJvcGMtYmFja2NoYW5uZWwiLCJjX2hhc2giOiJzZVkxTldwNmN6ZGppUEdTWktqQlZRIiwiYXV0aF90aW1lIjoxNjU2NTE2MDM4LCJleHAiOjE2NTY1MTk2NTAsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNjU2NTE2MDUwfQ.giFYGuN-VUNSVMMT4bBkoGsZ-rKlByqe6qv24jzp7pk2eCY4FawiaLHJqH9MzBN7uEauRXYNR2pa_0oGoYnNNg4zbFiSARSKVsajcrPeDUgNs71MjMOYCH5dukXB7X5SEP3Drz5njxuXswI_EjM2Cd0OtJMoHQ0_IP_C3rzwmaQQsgWk81yAXl-eM4zABYV1e9OObGFqPtVjoHmpbFbg-teoRTr_LxYgKPwB1XnRqD4G9No7oV-9q1Bv1ED9AU6zxLWf9aGE2gQIC-jgkr7LZ5pB4zYgU_DwgmpaAuW_AT8ApfnQPqgNy7YouIPWZ8pyoncLjF0SdStVPEoreRx7GA\",\"token_type\":\"Bearer\",\"expires_in\":299} With info, you could do whatever you want using browser session. NOTE: I added some custom params in case you need to validate something else, for instance browser IP. Script templates # These scripts are examples of how it worked, but you could customize them based on your needs, for instance browser validations. Backchannel authentication script # from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper from io.jans.as.server.util import ServerUtil from io.jans.service.cache import CacheProvider from io.jans.as.server.service import SessionIdService from io.jans.as.server.service import CookieService from io.jans.as.server.security import Identity from io.jans.service.cache import CacheProvider import java class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"Backchannel Authentication. Initialization\" print \"Backchannel Authentication. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Backchannel Authentication. Destroy\" print \"Backchannel Authentication. Destroyed successfully\" return True def getAuthenticationMethodClaims(self, requestParameters): return None def getApiVersion(self): return 11 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): print \"Backchannel Authentication. Authenticate\" # Get bcAuthnToken from params bcAuthnToken = ServerUtil.getFirstValue(requestParameters, \"bcAuthnToken\") print \"Backchannel Authentication. Get bcAuthnToken from params: '%s'\" % (bcAuthnToken) if (bcAuthnToken == None): return False # Get sessionDn from cacheProvider cacheProvider = CdiUtil.bean(CacheProvider) sessionCacheDn = cacheProvider.get(bcAuthnToken) print \"Backchannel Authentication. Get sessionCacheDn from cacheProvider: '%s'\" % (sessionCacheDn) if (sessionCacheDn == None): return False # Get sessionId by sessionDn sessionId = CdiUtil.bean(SessionIdService).getSessionByDn(sessionCacheDn) print \"Backchannel Authentication. Get sessionId from sessionIdService: '%s'\" % ('None' if sessionId == None else sessionId.getId()) if (sessionId == None): return False # Write sessionId in cookies CdiUtil.bean(CookieService).createSessionIdCookie(sessionId, False) print \"Backchannel Authentication. Set session in Cookie\" # Set sessionId in Identity identity = CdiUtil.bean(Identity) identity.setSessionId(sessionId) print \"Backchannel Authentication. Set session in Identity\" # Remove bcAuthnToken from cacheProvider cacheProvider.remove(bcAuthnToken) print \"Backchannel Authentication. Removed cacheProvider bcAuthnToken: '%s'\" % bcAuthnToken return True def prepareForStep(self, configurationAttributes, requestParameters, step): if (step == 1): return True else: return False def getExtraParametersForStep(self, configurationAttributes, step): return None def getCountAuthenticationSteps(self, configurationAttributes): return 1 def getPageForStep(self, configurationAttributes, step): return \"postlogin.xhtml\" def getNextStep(self, configurationAttributes, requestParameters, step): return -1 def getLogoutExternalUrl(self, configurationAttributes, requestParameters): return None def logout(self, configurationAttributes, requestParameters): return True ROPC backchannel script # from io.jans.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType from io.jans.as.server.service import AuthenticationService, SessionIdService from io.jans.as.server.security import Identity from io.jans.service.cdi.util import CdiUtil from io.jans.as.model.authorize import AuthorizeRequestParam from io.jans.as.server.model.config import Constants from io.jans.util import StringHelper from java.lang import String from java.util import Date, HashMap from io.jans.service.cache import CacheProvider import uuid class ResourceOwnerPasswordCredentials(ResourceOwnerPasswordCredentialsType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"ROPC Backchannel. Initializing ...\" print \"ROPC Backchannel. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"ROPC Backchannel. Destroying ...\" print \"ROPC Backchannel. Destroyed successfully\" return True def getApiVersion(self): return 11 def authenticate(self, context): print \"ROPC Backchannel. Authenticate\" # Do generic authentication authenticationService = CdiUtil.bean(AuthenticationService) username = context.getHttpRequest().getParameter(\"username\") password = context.getHttpRequest().getParameter(\"password\") # Add credential validation result = authenticationService.authenticate(username, password) if not result: print \"ROPC Backchannel. Authenticate. Could not authenticate user '%s' \" % username return False context.setUser(authenticationService.getAuthenticatedUser()) print \"ROPC Backchannel. Authenticate. User '%s' authenticated successfully\" % username # Get custom parameters from request customParam1Value = context.getHttpRequest().getParameter(\"custom1\") customParam2Value = context.getHttpRequest().getParameter(\"custom2\") customParameters = {} customParameters[\"custom1\"] = customParam1Value customParameters[\"custom2\"] = customParam2Value print \"ROPC Backchannel. Authenticate. User '%s'. Creating authenticated session with custom attributes: '%s'\" % (username, customParameters) session = self.createNewAuthenticatedSession(context, customParameters) # This is needed to allow store in token entry sessionId authenticationService.configureEventUser(session) print \"ROPC Backchannel. Authenticate. User '%s'. Created authenticated session: '%s'\" % (username, customParameters) return True def createNewAuthenticatedSession(self, context, customParameters={}): sessionIdService = CdiUtil.bean(SessionIdService) user = context.getUser() client = CdiUtil.bean(Identity).getSessionClient().getClient() # Add mandatory session parameters sessionAttributes = HashMap() sessionAttributes.put(Constants.AUTHENTICATED_USER, user.getUserId()) sessionAttributes.put(AuthorizeRequestParam.CLIENT_ID, client.getClientId()) # Add custom session parameters for key, value in customParameters.iteritems(): if StringHelper.isNotEmpty(value): sessionAttributes.put(key, value) # Generate authenticated session sessionId = sessionIdService.generateAuthenticatedSessionId(context.getHttpRequest(), user.getDn(), sessionAttributes) print \"ROPC Backchannel. Generated session id. DN: '%s'\" % sessionId.getDn() # Add state uuid in cache manager and response header bcAuthnToken = str(uuid.uuid4()) cacheProvider = CdiUtil.bean(CacheProvider) cacheProvider.put(300, bcAuthnToken, sessionId.getDn()) print \"ROPC Backchannel. Added cacheProvider id: '%s'\" % bcAuthnToken # Add response header Bc-Authn-Token context.getHttpResponse().setHeader(\"Bc-Authn-Token\", bcAuthnToken) print \"ROPC Backchannel. Added header Bc-Authn-Token\" return sessionId", "title": "Backchannel Authentication"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#backchannel-authentication-scripts", "text": "Janssen server enables domains to render the username/pw login form, avoiding the redirect to the IDP-hosted login page. Many SSO solutions offer a proprietary endpoint to accomplish this. However, in Janssen server, this is accomplished with the OAuth/OpenID framework by using a combination of calling the /token endpoint using the OAuth password flow, and then redirecting to browser to the /authorization endpoint, but auto-submitting the form. This article describes how to process login via backchannel and when browser is processing authorization, AS will recognize automatically the authenticated user, write cookies and then establish the session.", "title": "Backchannel authentication scripts"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#design", "text": "Source-code for sequence diagram Title password Grant with State Person->Browser: Navigate to website Browser->Website: Website->Browser:Display login page Person->Browser: Enter Username / PW Browser->Website: (creds) Website->IDP: /token?uid=_&pw=&browser_ip=_ IDP->Website: {\"redirect\": \"/authz/state=1F2D41A\", ...} Website->Browser: Browser->IDP: /authz?state=1F2D41A IDP->IDP: check IP address is\\n same as state IDP->Browser: write cookie / send redirect_uri Browser->Website: redirect_uri", "title": "Design"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#solution", "text": "In order to process the whole authorization, idea is to use resource owner password credentials grant type in the first stage, over there process the authentication as we do today, but also write in cache a short-lived token to recognize such authenticated user, then return to the client such short-lived token. During authorization, browser should send that token as part of the custom params and in the AS we should verify if that user is already authenticated using the short-lived param in the cache, then AS will write cookies, create the session and return to the client information required for this.", "title": "Solution"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#jans-app-configurations", "text": "Above the jans-auth record of the jansAppConf table, enable a new attribute on the jansConfDyn field Example: \"authorizationRequestCustomAllowedParameters\": [ { \"paramName\": \"bcAuthnToken\", \"returnInResponse\": true } ] Sample CURL 1. Obtain access token curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/jans-auth-server/config/properties.write\" 2. Apply patch curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"authorizationRequestCustomAllowedParameters\", \"value\": [ { \"paramName\": \"bcAuthnToken\", \"returnInResponse\": true } ] } ]'", "title": "Jans App Configurations"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#custom-script-registration", "text": "In the table jansCustomScr enable 2 new scripts: 1. Script type resource_owner_password_credentials displayName ropc-backchannel [ropc-backchannel-script.py] See script below. 2. Script type person_autentication displayName backchannel-authentication [backchannel-authentication-script.py] See script below.", "title": "Custom Script Registration"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#client-configuration", "text": "Associate script person_authentication on table jansClnt . Modify the jansAttrs field which contains a json and the ropcScripts field and add the dn from the ropc script record in the previous step Example: \"ropcScripts\": [ \"inum={SCRIPT_ID},ou=scripts,o=jans\", ],", "title": "Client Configuration"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#flow", "text": "", "title": "Flow"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#bcauthtoken-request", "text": "Firstly, the /token service is called to generate the bcAuthnToken (get it from the response header with the key Bc-Authn-Token ) In this request example, the client's basic credential is being used in order to authenticate the client, however you could use your preferred authn mode. Request curl --location --request POST 'https://jans.localhost/jans-auth/restv1/token' \\ --header 'Authorization: Basic MzE3MGNiYzUtMDAxOC00OWVmLThiYTYtMjY4MGI2NjhiZjBjOmFmNzk1ZjI1LWQ1MjktNDVlYi1iMTJlLWNjM2ExNTY5OTU1Ng==' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=password' \\ --data-urlencode 'username=test_user' \\ --data-urlencode 'password=test_user_password' \\ --data-urlencode 'custom1=your custom param 1' \\ --data-urlencode 'custom2=your custom param 2' \\ --data-urlencode 'scope=openid' Response HTTP/1.1 200 OK Date: Wed, 29 Jun 2022 14:03:25 GMT Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Bc-Authn-Token: dacfe4fc-d0ce-4673-9370-e66f652c4b7f Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1109 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive {\"access_token\":\"7a024a59-e132-4c05-9126-f4f36b3d3677\",\"refresh_token\":\"184c2b60-b5c7-4250-9850-97b0f531743c\",\"scope\":\"openid\",\"id_token\":\"eyJraWQiOiJmZGJhY2Q2Yi05YTY0LTQ2MWQtOWJlYy1jOTAyMjc5ZGI2ODZfc2lnX3JzMjU2IiwidHlwIjoiand0IiwiYWxnIjoiUlMyNTYifQ.eyJhdWQiOiIzMTcwY2JjNS0wMDE4LTQ5ZWYtOGJhNi0yNjgwYjY2OGJmMGMiLCJhY3IiOiJzaW1wbGVfcGFzc3dvcmRfYXV0aCIsInN1YiI6Il9Fa3p5aXlRdVBzUm1mYjh3WHlmTTB4U0xDckxwTDJGNnA3RWhEeWRBUHciLCJjb2RlIjoiNDY4MzQ2NjktOGQ1Yy00NmQxLTkwNWEtNmMzNDg3YzZlMDg3IiwiYW1yIjpbXSwiaXNzIjoiaHR0cHM6Ly9qYW5zLmxvY2FsaG9zdCIsImV4cCI6MTY1NjUxNTAwNiwiZ3JhbnQiOiJwYXNzd29yZCIsImlhdCI6MTY1NjUxMTQwNiwic2lkIjoiMTg0ZTllOTktNjFmNi00ZWNhLWE0ZmUtMTMwZmFmZDk1MjE1Iiwib3hPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIn0.hW0vReGYLzC2RyBHztSFbDYoaYHcCYxatX1lpzWqyW5U2S9eNp58mKKmvdZmMc229Sz5VxqfYflpWuI_6aXsLFR_KT9FY3exSRIRtPiD_fUETdhsVuKWavumVnjvwdAM6ytu5ORJx06DCxEgaG1uXmRiE9GoT8F1uqeo4NxURhVNXmMd2fiiUmgm1lt3-kNhlSg6vMDJS1Aq1idm-XhiSVy895BY-JdpLEGJEycPKr1lpsBTcmasbFNBJv6_orKWlvvgFCVxo7XmbH7Xnmqi6UUo30L6sULqmCsTLa6DaWYfGokHz_0xRflw_Ihv9wlVq8gSdOZGoMaVGzDdKlddZw\",\"token_type\":\"Bearer\",\"expires_in\":299}", "title": "BcAuthToken request:"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#authorize-request", "text": "Once you have gotten the bcAuthnToken from the previous /token call, you must call authorize attaching the bcAuthnToken as a parameter and in the acr_values param send the name of the backchannel-authentication registered in previous steps. This script will generate cookies and session associated with the browser if the BcAuthToken is valid. Example: https://jans.localhost/jans-auth/restv1/authorize?response_type=code&client_id=3170cbc5-0018-49ef-8ba6-2680b668bf0c&scope=openid+profile+address+email&redirect_uri=https://jans.localhost/jans-auth-rp/home.htm&state=2f78eaf1-d73e-49f2-8f50-e5faef80808a&nonce=92c3a631-db54-4ae9-bd53-caf92a4adbcf&prompt=&ui_locales=&claims_locales=&acr_values=backchannel-authentication&request_session_id=false&bcAuthnToken={your bcAuthnToken} This call will redirect to the redirect_uri that you sent as a parameter in the call and will receive a code as well, after that the process is more or less the same than the regular flow.", "title": "Authorize request:"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#request-token", "text": "With the code obtained previously, you must call /token again, adding the parameter code Request: curl --location --request POST 'https://jans.localhost/jans-auth/restv1/token' \\ --header 'Authorization: Basic MzlhNjlmYzAtNzNmYy00MWJhLWFiMGYtNDJhNWFmYWI2MjllOmJmMDRlZTM4LTM0MTktNGEzNS05YTI5LTcyODlmY2JkNzc2Zg==' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=authorization_code' \\ --data-urlencode 'code=d449a7b9-10f6-4320-b257-05fee91d3c16' \\ --data-urlencode 'redirect_uri=https://jans.localhost/jans-auth-rp/home.htm' Response: HTTP/1.1 200 OK Date: Wed, 29 Jun 2022 15:20:50 GMT Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1291 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive {\"access_token\":\"896b04a2-fcbe-4466-89b9-184930b8675b\",\"refresh_token\":\"843995ef-cd0e-4b2c-9b91-7c68081325ab\",\"id_token\":\"eyJraWQiOiJmZGJhY2Q2Yi05YTY0LTQ2MWQtOWJlYy1jOTAyMjc5ZGI2ODZfc2lnX3JzMjU2IiwidHlwIjoiand0IiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoiMmx5OXh5emthMmc2T09HcVRPTmhqdyIsInN1YiI6Il9Fa3p5aXlRdVBzUm1mYjh3WHlmTTB4U0xDckxwTDJGNnA3RWhEeWRBUHciLCJjb2RlIjoiMjdiNjM0NTItMTE1My00ZDk5LTlkYzQtYzMyNGRmNjIwYWE0IiwiYW1yIjpbIjEwIl0sImlzcyI6Imh0dHBzOi8vamFucy5sb2NhbGhvc3QiLCJub25jZSI6IjkyYzNhNjMxLWRiNTQtNGFlOS1iZDUzLWNhZjkyYTRhZGJjZiIsInNpZCI6ImQzZDFlOWY2LWE1NTMtNDI2ZC04MWQ1LTE0YTFiZjg0MDJhNCIsIm94T3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCIsImF1ZCI6IjMxNzBjYmM1LTAwMTgtNDllZi04YmE2LTI2ODBiNjY4YmYwYyIsImFjciI6InJvcGMtYmFja2NoYW5uZWwiLCJjX2hhc2giOiJzZVkxTldwNmN6ZGppUEdTWktqQlZRIiwiYXV0aF90aW1lIjoxNjU2NTE2MDM4LCJleHAiOjE2NTY1MTk2NTAsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNjU2NTE2MDUwfQ.giFYGuN-VUNSVMMT4bBkoGsZ-rKlByqe6qv24jzp7pk2eCY4FawiaLHJqH9MzBN7uEauRXYNR2pa_0oGoYnNNg4zbFiSARSKVsajcrPeDUgNs71MjMOYCH5dukXB7X5SEP3Drz5njxuXswI_EjM2Cd0OtJMoHQ0_IP_C3rzwmaQQsgWk81yAXl-eM4zABYV1e9OObGFqPtVjoHmpbFbg-teoRTr_LxYgKPwB1XnRqD4G9No7oV-9q1Bv1ED9AU6zxLWf9aGE2gQIC-jgkr7LZ5pB4zYgU_DwgmpaAuW_AT8ApfnQPqgNy7YouIPWZ8pyoncLjF0SdStVPEoreRx7GA\",\"token_type\":\"Bearer\",\"expires_in\":299} With info, you could do whatever you want using browser session. NOTE: I added some custom params in case you need to validate something else, for instance browser IP.", "title": "Request /token:"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#script-templates", "text": "These scripts are examples of how it worked, but you could customize them based on your needs, for instance browser validations.", "title": "Script templates"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#backchannel-authentication-script", "text": "from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper from io.jans.as.server.util import ServerUtil from io.jans.service.cache import CacheProvider from io.jans.as.server.service import SessionIdService from io.jans.as.server.service import CookieService from io.jans.as.server.security import Identity from io.jans.service.cache import CacheProvider import java class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"Backchannel Authentication. Initialization\" print \"Backchannel Authentication. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Backchannel Authentication. Destroy\" print \"Backchannel Authentication. Destroyed successfully\" return True def getAuthenticationMethodClaims(self, requestParameters): return None def getApiVersion(self): return 11 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): print \"Backchannel Authentication. Authenticate\" # Get bcAuthnToken from params bcAuthnToken = ServerUtil.getFirstValue(requestParameters, \"bcAuthnToken\") print \"Backchannel Authentication. Get bcAuthnToken from params: '%s'\" % (bcAuthnToken) if (bcAuthnToken == None): return False # Get sessionDn from cacheProvider cacheProvider = CdiUtil.bean(CacheProvider) sessionCacheDn = cacheProvider.get(bcAuthnToken) print \"Backchannel Authentication. Get sessionCacheDn from cacheProvider: '%s'\" % (sessionCacheDn) if (sessionCacheDn == None): return False # Get sessionId by sessionDn sessionId = CdiUtil.bean(SessionIdService).getSessionByDn(sessionCacheDn) print \"Backchannel Authentication. Get sessionId from sessionIdService: '%s'\" % ('None' if sessionId == None else sessionId.getId()) if (sessionId == None): return False # Write sessionId in cookies CdiUtil.bean(CookieService).createSessionIdCookie(sessionId, False) print \"Backchannel Authentication. Set session in Cookie\" # Set sessionId in Identity identity = CdiUtil.bean(Identity) identity.setSessionId(sessionId) print \"Backchannel Authentication. Set session in Identity\" # Remove bcAuthnToken from cacheProvider cacheProvider.remove(bcAuthnToken) print \"Backchannel Authentication. Removed cacheProvider bcAuthnToken: '%s'\" % bcAuthnToken return True def prepareForStep(self, configurationAttributes, requestParameters, step): if (step == 1): return True else: return False def getExtraParametersForStep(self, configurationAttributes, step): return None def getCountAuthenticationSteps(self, configurationAttributes): return 1 def getPageForStep(self, configurationAttributes, step): return \"postlogin.xhtml\" def getNextStep(self, configurationAttributes, requestParameters, step): return -1 def getLogoutExternalUrl(self, configurationAttributes, requestParameters): return None def logout(self, configurationAttributes, requestParameters): return True", "title": "Backchannel authentication script"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#ropc-backchannel-script", "text": "from io.jans.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType from io.jans.as.server.service import AuthenticationService, SessionIdService from io.jans.as.server.security import Identity from io.jans.service.cdi.util import CdiUtil from io.jans.as.model.authorize import AuthorizeRequestParam from io.jans.as.server.model.config import Constants from io.jans.util import StringHelper from java.lang import String from java.util import Date, HashMap from io.jans.service.cache import CacheProvider import uuid class ResourceOwnerPasswordCredentials(ResourceOwnerPasswordCredentialsType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"ROPC Backchannel. Initializing ...\" print \"ROPC Backchannel. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"ROPC Backchannel. Destroying ...\" print \"ROPC Backchannel. Destroyed successfully\" return True def getApiVersion(self): return 11 def authenticate(self, context): print \"ROPC Backchannel. Authenticate\" # Do generic authentication authenticationService = CdiUtil.bean(AuthenticationService) username = context.getHttpRequest().getParameter(\"username\") password = context.getHttpRequest().getParameter(\"password\") # Add credential validation result = authenticationService.authenticate(username, password) if not result: print \"ROPC Backchannel. Authenticate. Could not authenticate user '%s' \" % username return False context.setUser(authenticationService.getAuthenticatedUser()) print \"ROPC Backchannel. Authenticate. User '%s' authenticated successfully\" % username # Get custom parameters from request customParam1Value = context.getHttpRequest().getParameter(\"custom1\") customParam2Value = context.getHttpRequest().getParameter(\"custom2\") customParameters = {} customParameters[\"custom1\"] = customParam1Value customParameters[\"custom2\"] = customParam2Value print \"ROPC Backchannel. Authenticate. User '%s'. Creating authenticated session with custom attributes: '%s'\" % (username, customParameters) session = self.createNewAuthenticatedSession(context, customParameters) # This is needed to allow store in token entry sessionId authenticationService.configureEventUser(session) print \"ROPC Backchannel. Authenticate. User '%s'. Created authenticated session: '%s'\" % (username, customParameters) return True def createNewAuthenticatedSession(self, context, customParameters={}): sessionIdService = CdiUtil.bean(SessionIdService) user = context.getUser() client = CdiUtil.bean(Identity).getSessionClient().getClient() # Add mandatory session parameters sessionAttributes = HashMap() sessionAttributes.put(Constants.AUTHENTICATED_USER, user.getUserId()) sessionAttributes.put(AuthorizeRequestParam.CLIENT_ID, client.getClientId()) # Add custom session parameters for key, value in customParameters.iteritems(): if StringHelper.isNotEmpty(value): sessionAttributes.put(key, value) # Generate authenticated session sessionId = sessionIdService.generateAuthenticatedSessionId(context.getHttpRequest(), user.getDn(), sessionAttributes) print \"ROPC Backchannel. Generated session id. DN: '%s'\" % sessionId.getDn() # Add state uuid in cache manager and response header bcAuthnToken = str(uuid.uuid4()) cacheProvider = CdiUtil.bean(CacheProvider) cacheProvider.put(300, bcAuthnToken, sessionId.getDn()) print \"ROPC Backchannel. Added cacheProvider id: '%s'\" % bcAuthnToken # Add response header Bc-Authn-Token context.getHttpResponse().setHeader(\"Bc-Authn-Token\", bcAuthnToken) print \"ROPC Backchannel. Added header Bc-Authn-Token\" return sessionId", "title": "ROPC backchannel script"}, {"location": "janssen-server/auth-server/endpoints/client-registration/", "tags": ["administration", "auth-server", "endpoint", "DCR", "dynamic client registration"], "text": "Dynamic Client Registration (DCR) # Dynamic client registration refers to the process by which a client submits a registration request to the Authorization server and how that request is served by the Authorization server. It is explained in the following specifications: For OpenID Connect relying parties For OAuth 2.0 client (without OpenID Connect features) Client management (CRUD) operations OpenBanking OpenID Dynamic Client Registration Client Registration endpoint # The URI to dynamically register a client to a Janssen Auth Server can be found by checking the registration_endpoint claim of the OpenID Connect configuration reponse, typically deployed at https://<my.jans.server>/.well-known/openid-configuration Configuring Janssen AS to allow clients to dynamically register # The Janssen Authorization server will serve a DCR request if the following configuration parameters are set: dynamicRegistrationEnabled : true or false dynamicRegistrationExpirationTime : Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire dcrForbidExpirationTimeInRequest : Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration.. Default value is false . Client expiration Client expiration is set based on dynamicRegistrationExpirationTime AS configuration property or otherwise if dcrForbidExpirationTimeInRequest is false then it can be requested in Dynamic Client Registration Request via lifetime parameter which expected value in seconds. Configure the Janssen AS using steps explained in the link Client registration Requests # Client registration request primarily does two things: Communicate client metadata to the authorization server, and optionally authenticate. There are different ways in which the client metadata is communicated to the authorization server using dynamic client registration requests. Using request body Using signed request object (JWT) Using software statement Using request body # A minimal DCR request with only mandatory parameters, looks like the one below. curl -X POST -k -H 'Content-Type: application/json' -i 'https://my.jans.server/jans-auth/restv1/register' \\ --data '{\"redirect_uris\": [\"https://my.jans.client/page\"]}' If the registration is successful, Janssen Server will respond with http response code 201 with JSON body as shown in example below: { \"allow_spontaneous_scopes\" : false , \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://my.jans.server/jans-auth/restv1/register?client_id=85192707-a38c-496c-806c-ef01a6a3ae4a\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"eaee20de-54ce-4217-b960-6b72b55e6cab\" , \"client_id\" : \"85192707-a38c-496c-806c-ef01a6a3ae4a\" , \"token_endpoint_auth_method\" : \"client_secret_basic\" , \"scope\" : \"profile work_phone phone user_name device_sso openid permission uma_protection address email clientinfo org_name offline_access https://jans.io/auth/ssa.portal test https://jans.io/auth/ssa.admin https://jans.io/auth/ssa.developer\" , \"client_secret\" : \"4148f812-92d6-4245-80e0-243524b3b6a4\" , \"client_id_issued_at\" : 1678700818 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"client_name\" : \"my.jans.client\" , \"par_lifetime\" : 600 , \"lifetime\" : 3600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : false , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" ], \"subject_type\" : \"pairwise\" , \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris\" : [ \"https://my.jans.client/page\" ], \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1678787218 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" ] } In a typical DCR request the client or developer calls the client registration endpoint with a set of client metadata as specified in RFC7591 curl -X POST -k -i 'https://my.jans.server/jans-auth/restv1/register' \\ --data '{ \\ \"redirect_uris\": [\"https://client.example.org/cb\"] \\ \"client_id\": \"c3BhdRkqfX\", \\ \"client_secret\": \"bd136123eeffeef234235805d\", \\ \"grant_types\": [\"authorization_code\", \"refresh_token\"], \\ \"token_endpoint_auth_method\": \"client_secret_basic\", \\ \"jwks_uri\": \"https://client.example.org/my_public_keys.jwks\", \\ \"client_name\": \"My Example\", \\ \"client_name#fr\": \"Mon Exemple\" \\ }' Using signed request object (JWT) # In some use-cases like FAPI implementation, DCR request payload is a JWT. Example: curl -X POST -k -H 'Content-Type: application/jwt' \\ -H 'Accept: application/json' \\ -i 'https://my-jans-server/jans-auth/restv1/register' \\ --data 'eyJraWQiOiJrWTIyZXBUT......ueOg2HkjpggwAEP84jq9Q' When such will be the nature of client registration requests, the following configuration properties should be set in the authorization server: dcrSignatureValidationEnabled - enables DCR signature validation dcrSignatureValidationJwksUri - specifies JWKS URI for all DCR's validations. dcrSignatureValidationJwks - specifies JWKS for all DCR's validations. Configure the Janssen AS using steps explained in the link Using software statement # A signed assertion from a trusted party, a Software statement or Software Statement Assertion (SSA), is used to dynamically register clients to an Authorization server. Example: curl -X POST https://my.jans.server/jans-auth/restv1/register \\ -H \"Content-Type: application/json\" \\ --data-binary @- <<DATA \\ { \"redirect_uris\": [ \"https://client.example.org/cab1\" ], \\ \"software_statement\":\"eyJ0eXAi........j3ouyeYOv8\", \\ \"jwks_uri\":\"https://my.portal/portal/jwks\" \\ } DATA To enable client registrations using Software statements, the AS should be configured using the following configuration parameters: softwareStatementValidationType - The value of this variable is one of the following: NONE - validation is skipped for software statement SCRIPT - (default), invokes getSoftwareStatementJwks of dynamic registration script which has to return jwks. JWKS - claim name within software statement that has inlined JWKS JWKS_URI - claim name within software statement that points to JWKS URI that should lead to keys. dcrSignatureValidationSoftwareStatementJwksURIClaim - specifies claim name inside software statement that should point to JWKS URI. dcrSignatureValidationSoftwareStatementJwksClaim - specifies claim name inside software statement. Value of claim should point to inlined JWKS. trustedSsaIssuers - map of trusted SSA issuers with configuration (e.g. automatically granted scopes). When empty - no issuers validation is performed. When not empty - AS forces validation and each SSA must match at least one entry from list. automaticallyGrantedScopes - automatically granted scopes for trusted issuer { \"https://trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"a\" , \"b\" ] }, \"https://another-trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"d\" ] } } Configure the AS using steps explained in the link Special mention about FAPI: # In case of a typical client registration request in FAPI implementation , the request object which is a signed JWT (as seen in point 3) is also called an SSA (Software statement Assertion) or DCR payload. This SSA can contain the software_statement inside it which is also a signed JWT. Each of the JWTs, the outer JWT called the SSA and the inner JWT called the software_statement are signed by different entities - the TPP and OBIE respectively. Security Pointers # If dynamicRegistrationEnabled is enabled in the Authorization Server, assess the following points to minimize potential exposure of sensitive personal data: trustedClientEnabled and dynamicRegistrationPersistClientAuthorizations properties determine whether clients are trusted and if consent should be sought from the user before releasing their personal data to the RP dynamicRegistrationScopesParamEnabled controls whether default scopes are globally enabled. If dynamicRegistrationScopesParamEnabled is true then scopes defined as default will be automatically added to any dynamically registered client entry without consent of OP's administrator. Therefore, make an informed decision before setting this field to true . CURL commands to configure Jans-auth server # Jans-auth server is configured using Jans Config Api : Obtain the access token # curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/jans-auth-server/config/properties.write\" Patch jans-auth server configurations # Patch jans-auth server configurations to reflect anExampleConfigField with the value anExampleConfigField_value curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://<your.jans.server>/jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"anExampleConfigField\", \"value\": \"anExampleConfigField_value\" } ]' For example, to patch the jans-auth server configurations to reflect dynamicRegistrationEnabled with value as true curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://<your.jans.server>/jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"dynamicRegistrationEnabled\", \"value\": \"true\" } ]' Client metadata # Command to obtain metadata schema jans cli --schema /components/schemas/Client Output: { \"dn\" : \"string\" , \"inum\" : \"string\" , \"displayName\" : \"string\" , \"clientSecret\" : \"string\" , \"frontChannelLogoutUri\" : \"string\" , \"frontChannelLogoutSessionRequired\" : true , \"registrationAccessToken\" : \"string\" , \"clientIdIssuedAt\" : \"2022-08-31T10:39:31.385Z\" , \"clientSecretExpiresAt\" : \"2022-08-31T10:39:31.385Z\" , \"redirectUris\" : [ \"https://client.example.org/cb\" ], \"claimRedirectUris\" : [ \"string\" ], \"responseTypes\" : [ \"code\" ], \"grantTypes\" : [ \"authorization_code\" ], \"applicationType\" : \"web\" , \"contacts\" : [ \"string\" ], \"idTokenTokenBindingCnf\" : \"string\" , \"logoUri\" : \"string\" , \"clientUri\" : \"string\" , \"policyUri\" : \"string\" , \"tosUri\" : \"string\" , \"jwksUri\" : \"string\" , \"jwks\" : \"{ \\\"keys\\\" : [ { \\\"e\\\" : \\\"AQAB\\\", \\\"n\\\" : \\\"gmlDX_mgMcHX..\\\" ] }\" , \"sectorIdentifierUri\" : \"string\" , \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"HS256\" , \"idTokenEncryptedResponseAlg\" : \"RSA1_5\" , \"idTokenEncryptedResponseEnc\" : \"A128CBC+HS256\" , \"userInfoSignedResponseAlg\" : \"HS256\" , \"userInfoEncryptedResponseAlg\" : \"RSA1_5\" , \"userInfoEncryptedResponseEnc\" : \"A128CBC+HS256\" , \"requestObjectSigningAlg\" : \"HS256\" , \"requestObjectEncryptionAlg\" : \"RSA1_5\" , \"requestObjectEncryptionEnc\" : \"A128CBC+HS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"tokenEndpointAuthSigningAlg\" : \"HS256\" , \"defaultMaxAge\" : 1000000 , \"requireAuthTime\" : true , \"defaultAcrValues\" : [ \"string\" ], \"initiateLoginUri\" : \"string\" , \"postLogoutRedirectUris\" : [ \"https://client.example.org/logout/page1\" , \"https://client.example.org/logout/page2\" , \"https://client.example.org/logout/page3\" ], \"requestUris\" : [ \"string\" ], \"scopes\" : [ \"read write dolphin\" ], \"claims\" : [ \"string\" ], \"trustedClient\" : false , \"lastAccessTime\" : \"2022-08-31T10:39:31.385Z\" , \"lastLogonTime\" : \"2022-08-31T10:39:31.385Z\" , \"persistClientAuthorizations\" : true , \"includeClaimsInIdToken\" : false , \"refreshTokenLifetime\" : 100000000 , \"accessTokenLifetime\" : 100000000 , \"customAttributes\" : [ { \"name\" : \"name, displayName, birthdate, email\" , \"multiValued\" : true , \"values\" : [ \"string\" ] } ], \"customObjectClasses\" : [ \"string\" ], \"rptAsJwt\" : true , \"accessTokenAsJwt\" : true , \"accessTokenSigningAlg\" : \"HS256\" , \"disabled\" : false , \"authorizedOrigins\" : [ \"string\" ], \"softwareId\" : \"4NRB1-0XZABZI9E6-5SM3R\" , \"softwareVersion\" : \"2.1\" , \"softwareStatement\" : \"string\" , \"attributes\" : { \"tlsClientAuthSubjectDn\" : \"string\" , \"runIntrospectionScriptBeforeAccessTokenAsJwtCreationAndIncludeClaims\" : true , \"keepClientAuthorizationAfterExpiration\" : true , \"allowSpontaneousScopes\" : true , \"spontaneousScopes\" : [ \"string\" ], \"spontaneousScopeScriptDns\" : [ \"string\" ], \"updateTokenScriptDns\" : [ \"string\" ], \"backchannelLogoutUri\" : [ \"string\" ], \"backchannelLogoutSessionRequired\" : true , \"additionalAudience\" : [ \"string\" ], \"postAuthnScripts\" : [ \"string\" ], \"consentGatheringScripts\" : [ \"string\" ], \"introspectionScripts\" : [ \"string\" ], \"rptClaimsScripts\" : [ \"string\" ], \"ropcScripts\" : [ \"string\" ], \"parLifetime\" : 0 , \"requirePar\" : true , \"jansAuthSignedRespAlg\" : \"string\" , \"jansAuthEncRespAlg\" : \"string\" , \"jansAuthEncRespEnc\" : \"string\" , \"jansSubAttr\" : \"string\" , \"redirectUrisRegex\" : \"string\" , \"jansAuthorizedAcr\" : [ \"string\" ], \"jansDefaultPromptLogin\" : true }, \"backchannelTokenDeliveryMode\" : \"poll\" , \"backchannelClientNotificationEndpoint\" : \"string\" , \"backchannelAuthenticationRequestSigningAlg\" : \"RS256\" , \"backchannelUserCodeParameter\" : true , \"expirationDate\" : \"2022-08-31T10:39:31.385Z\" , \"deletable\" : false , \"jansId\" : \"string\" , \"description\" : \"string\" } Signed DCR and SSA validation # In OpenBanking case DCR (Dynamic Client Request) is signed and must contain SSA (Software Statement Assertion) inside it. Non-Normative Example: POST /register HTTP/1.1 Content-Type: application/jwt Accept: application/json Host: auth.bankone.com eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJJREFtYX... Decoded DCR Example: { \"typ\" : \"JWT\" , \"alg\" : \"ES256\" , \"kid\" : \"ABCD1234\" } { \"iss\" : \"Amazon TPPID\" , \"iat\" : 1492760444 , \"exp\" : 1524296444 , \"aud\" : \"https://authn.gluu.org\" , \"scope\" : \"openid makepayment\" , \"token_endpoint_auth_method\" : \"private_key_jwt\" , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"response_types\" : [ \"code\" ], \"id_token_signed_response_alg\" : \"ES256\" , \"request_object_signing_alg\" : \"ES256\" , \"software_id\" : \"65d1f27c-4aea-4549-9c21-60e495a7a86f\" , \"software_statement\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJlbXB0eSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJhZG1pbiI6dHJ1ZSwic2NvcGUiOiJzY29wZTEgc2NvcGUyIiwiY2xhaW1zIjoiY2xhaW0xIGNsYWltMiIsImlhdCI6MTY2OTgwNjc2MywiZXhwIjoxNjY5ODEwMzYzfQ.db0WQh2lmHkNYCWT8tSW684hqWTPJDTElppy42XM_lc\" } { Sig nature } AS has dcrSsaValidationConfigs configuration value which holds json array. It can be used to validated both DCR and SSA. Single item of this array has following properties: id - REQUIRED primary key for the entity type - REQUIRED either ssa or dcr displayName - Human friendly name in case we build an admin GUI for this description - Human friendly details scope - For SSA only -- list of allowed scopes the issuer can enable the client to request automatically. If not present, all scopes are allowed. allowed_claims - Any claims not listed in this list will be dropped. If not present, all claims are allowed. jwks - Public key jwks_uri - URI of public key issuers - For MTLS, list of issuers trusted configuration_endpoint - points to discovery page, e.g. https://examle.com/.well-known/openid-configuration configuration_endpoint_claim - e.g. ssa_jwks_endpoint shared_secret - for MTLS HMAC One of jwks , jwks_uri or issuers or configuration_endpoint is required. Non-normative example of dcrSsaValidationConfigs [ { \"id\" : \"735ee1c0-895d-4398-9c1b-9ad852257cc0\" , \"type\" : \"DCR\" , \"scopes\" : [ \"read\" , \"write\" ], \"allowedClaims\" : [ \"exp\" , \"iat\" ], \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"Acme\" ], \"sharedSecret\" : \"secret\" }, { \"id\" : \"7907cd0b-0f9f-4b4f-aaa2-0d0614546246\" , \"type\" : \"SSA\" , \"scopes\" : [ \"my_read\" , \"my_write\" ], \"allowedClaims\" : [ \"test_exp\" , \"test_iat\" ], \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"jans-auth\" ], \"sharedSecret\" : \"secret\" }, { \"id\" : \"1e95c9b1-04d0-4440-9362-88f4e1e62d76\" , \"type\" : \"SSA\" , \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"empty\" ], \"sharedSecret\" : \"secret\" } ] Signed DCR validation # DCR can be validated with two approaches. Via dcrSsaValidationConfigs configuration property - RECOMMENDED When create entry in dcrSsaValidationConfigs configuration property : - type MUST be equal to DCR value - issuers MUST have value which equals to iss claim in DCR. Via other configuration properties trustedSsaIssuers - map of trusted SSA issuers with configuration (e.g. automatically granted scopes). When empty - no issuers validation is performed. When not empty - AS forces validation and each SSA must match at least one entry from list. automaticallyGrantedScopes - automatically granted scopes for trusted issuer { \"https://trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"a\" , \"b\" ] }, \"https://another-trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"d\" ] } } dcrSignatureValidationJwks - specifies JWKS for DCR's validations dcrSignatureValidationJwksUri - specifies JWKS URI for DCR's validations dcrSignatureValidationSharedSecret - if HMAC is used, this is the shared secret dcrSignatureValidationEnabled - boolean value enables DCR signature validation. Default is false dcrSignatureValidationSoftwareStatementJwksURIClaim - specifies claim name inside software statement. Value of claim should point to JWKS URI dcrSignatureValidationSoftwareStatementJwksClaim - specifies claim name inside software statement. Value of claim should point to inlined JWKS dcrAuthorizationWithClientCredentials - boolean value indicating if DCR authorization to be performed using client credentials SSA Validation # SSA is validated based on softwareStatementValidationType which is enum. softwareStatementValidationType = builtin - validation is performed against dcrSsaValidationConfigs configuration property, where type MUST be equal to SSA value issuers MUST have value which equals to iss claim in DCR. softwareStatementValidationType = script - jwks and hmac secret are returned by dynamic client registration script softwareStatementValidationType = jwks_uri , allows to specify jwks_uri claim name from software_statement. Claim name specified by softwareStatementValidationClaimName configuration property. softwareStatementValidationType = jwks , allows to specify jwks claim name from software_statement. Claim name specified by softwareStatementValidationClaimName configuration property. softwareStatementValidationType = none , no validation. Customizing the behavior of the AS using Interception script # Janssen's allows developers to register a client with the Authorization Server (AS) without any intervention by the administrator. By default, all clients are given the same default scopes and attributes. Through the use of an interception script, this behavior can be modified. These scripts can be used to analyze the registration request and apply customizations to the registered client. For example, a client can be given specific scopes by analyzing the Software Statement that is sent with the registration request. Further reading here The Use of Attestation in Dynamic Client Registration # AS supports \"The Use of Attestation in OAuth 2.0 Dynamic Client Registration\" specification draft . Specification draft does not define exact attestation request/response formats. Thus AS supports Attestation calls to Verifier via ClientRegistrationType custom script type. Use createClient method of ClientRegistrationType to prevent client creation if attestation result does not satisfy expectation. def createClient ( self , context ): print \"Client registration. CreateClient method\" registerRequest = context . getRegisterRequest () configurationAttributes = context . getConfigurationAttibutes () client = context . getClient () # getting evidence as string or as JWT evidenceAsString = registerRequest . getEvidence () evidenceAsJwt = context . getEvidence () # following code depends on attestation client used to make calls to Verifier attestationResult = attestationClient . attestation ( evidence ) if attestationResult . isFail : print \"Attestation result forbids client creation\" return False print \"Attestation result is OK\" return True Configuration options - dcrAttestationEvidenceRequired - Boolean value indicating if DCR attestation evidence is required. Default value is false . If evidence request parameter is not present and dcrAttestationEvidenceRequired is true AS returns stale_evidence error: HTTP/1.1 400 Bad Request Content-Type: application/json Cache-Control: no-store Pragma: no-cache { \"error\": \"stale_evidence\", \"error_description\": \"The provided evidence is not current.\", \"nonce\": \"lBjvTtuPbpzIaqyiAOOkrIol3WmflPUUepzUXNDFuUgMKUL\" } It is common to get nonce value from Attestation Server. In this case set dcrAttestationEvidenceRequired=false and throw error from custom script. def createClient ( self , context ): evidenceAsString = registerRequest . getEvidence () if StringHelper . isEmpty ( evidenceAsString ) nonceFromVerifier = attestationClient . requestNonce () context . createStaleEvidenceWebApplicationException ( nonceFromVerifier ) return False ... print \"Attestation result is OK\" return True context.createStaleEvidenceWebApplicationException(nonceFromVerifier) leads to stale_evidence error creation, see example above ( nonceFromVerifier must be string value). In case goal is to create own custom error, please use standard context.createWebApplicationException methods and return False from script to prevent client creation. Example entity = < construct error message > context . createWebApplicationException ( 400 , entity ) Dynamic registration custom attributes # CRUD Operations # Janssen Server allows client management through client configuration endpoint (RFC 7592) . JSON response to client registration request contains registration_client_uri and registration_access_token data elements. The URI mentioned using registration_client_uri provides functionality to read, update and delete the client. This endpoint is a protected endpoint where request has to be authenticated using access token registration_access_token . Read client metadata # A read request to the same client that got created in earlier section should be as shown in the example below. HTTP method GET is used to send the request which signifies that it is a request to read client metadata. curl -k -H 'Authorization: Bearer eaee20de-54ce-4217-b960-6b72b55e6cab' \\ -i 'https://my.jans.server/jans-auth/restv1/register?client_id=85192707-a38c-496c-806c-ef01a6a3ae4a' JSON response from Janssen Server will contain the current state of client metadata. Update client metadata # Client metadata can be updated by sending request with PUT HTTP method to registration_client_uri . Janssen Server replaces current metadata with the one sent with update request as outlined in the specification Delete Client # Client can be deleted by sending a request using DELETE method to registration_client_uri . A successful delete action will invalidate the \"client_id\", \"client_secret\", and \"registration_access_token\" for this client, thereby preventing the \"client_id\" from being used at either the authorization endpoint or token endpoint of the authorization server. Internationalization for Client metadata #", "title": "Client Registration"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#dynamic-client-registration-dcr", "text": "Dynamic client registration refers to the process by which a client submits a registration request to the Authorization server and how that request is served by the Authorization server. It is explained in the following specifications: For OpenID Connect relying parties For OAuth 2.0 client (without OpenID Connect features) Client management (CRUD) operations OpenBanking OpenID Dynamic Client Registration", "title": "Dynamic Client Registration (DCR)"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#client-registration-endpoint", "text": "The URI to dynamically register a client to a Janssen Auth Server can be found by checking the registration_endpoint claim of the OpenID Connect configuration reponse, typically deployed at https://<my.jans.server>/.well-known/openid-configuration", "title": "Client Registration endpoint"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#configuring-janssen-as-to-allow-clients-to-dynamically-register", "text": "The Janssen Authorization server will serve a DCR request if the following configuration parameters are set: dynamicRegistrationEnabled : true or false dynamicRegistrationExpirationTime : Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire dcrForbidExpirationTimeInRequest : Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration.. Default value is false . Client expiration Client expiration is set based on dynamicRegistrationExpirationTime AS configuration property or otherwise if dcrForbidExpirationTimeInRequest is false then it can be requested in Dynamic Client Registration Request via lifetime parameter which expected value in seconds. Configure the Janssen AS using steps explained in the link", "title": "Configuring Janssen AS to allow clients to dynamically register"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#client-registration-requests", "text": "Client registration request primarily does two things: Communicate client metadata to the authorization server, and optionally authenticate. There are different ways in which the client metadata is communicated to the authorization server using dynamic client registration requests. Using request body Using signed request object (JWT) Using software statement", "title": "Client registration Requests"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#using-request-body", "text": "A minimal DCR request with only mandatory parameters, looks like the one below. curl -X POST -k -H 'Content-Type: application/json' -i 'https://my.jans.server/jans-auth/restv1/register' \\ --data '{\"redirect_uris\": [\"https://my.jans.client/page\"]}' If the registration is successful, Janssen Server will respond with http response code 201 with JSON body as shown in example below: { \"allow_spontaneous_scopes\" : false , \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://my.jans.server/jans-auth/restv1/register?client_id=85192707-a38c-496c-806c-ef01a6a3ae4a\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"eaee20de-54ce-4217-b960-6b72b55e6cab\" , \"client_id\" : \"85192707-a38c-496c-806c-ef01a6a3ae4a\" , \"token_endpoint_auth_method\" : \"client_secret_basic\" , \"scope\" : \"profile work_phone phone user_name device_sso openid permission uma_protection address email clientinfo org_name offline_access https://jans.io/auth/ssa.portal test https://jans.io/auth/ssa.admin https://jans.io/auth/ssa.developer\" , \"client_secret\" : \"4148f812-92d6-4245-80e0-243524b3b6a4\" , \"client_id_issued_at\" : 1678700818 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"client_name\" : \"my.jans.client\" , \"par_lifetime\" : 600 , \"lifetime\" : 3600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : false , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" ], \"subject_type\" : \"pairwise\" , \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris\" : [ \"https://my.jans.client/page\" ], \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1678787218 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" ] } In a typical DCR request the client or developer calls the client registration endpoint with a set of client metadata as specified in RFC7591 curl -X POST -k -i 'https://my.jans.server/jans-auth/restv1/register' \\ --data '{ \\ \"redirect_uris\": [\"https://client.example.org/cb\"] \\ \"client_id\": \"c3BhdRkqfX\", \\ \"client_secret\": \"bd136123eeffeef234235805d\", \\ \"grant_types\": [\"authorization_code\", \"refresh_token\"], \\ \"token_endpoint_auth_method\": \"client_secret_basic\", \\ \"jwks_uri\": \"https://client.example.org/my_public_keys.jwks\", \\ \"client_name\": \"My Example\", \\ \"client_name#fr\": \"Mon Exemple\" \\ }'", "title": "Using request body"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#using-signed-request-object-jwt", "text": "In some use-cases like FAPI implementation, DCR request payload is a JWT. Example: curl -X POST -k -H 'Content-Type: application/jwt' \\ -H 'Accept: application/json' \\ -i 'https://my-jans-server/jans-auth/restv1/register' \\ --data 'eyJraWQiOiJrWTIyZXBUT......ueOg2HkjpggwAEP84jq9Q' When such will be the nature of client registration requests, the following configuration properties should be set in the authorization server: dcrSignatureValidationEnabled - enables DCR signature validation dcrSignatureValidationJwksUri - specifies JWKS URI for all DCR's validations. dcrSignatureValidationJwks - specifies JWKS for all DCR's validations. Configure the Janssen AS using steps explained in the link", "title": "Using signed request object (JWT)"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#using-software-statement", "text": "A signed assertion from a trusted party, a Software statement or Software Statement Assertion (SSA), is used to dynamically register clients to an Authorization server. Example: curl -X POST https://my.jans.server/jans-auth/restv1/register \\ -H \"Content-Type: application/json\" \\ --data-binary @- <<DATA \\ { \"redirect_uris\": [ \"https://client.example.org/cab1\" ], \\ \"software_statement\":\"eyJ0eXAi........j3ouyeYOv8\", \\ \"jwks_uri\":\"https://my.portal/portal/jwks\" \\ } DATA To enable client registrations using Software statements, the AS should be configured using the following configuration parameters: softwareStatementValidationType - The value of this variable is one of the following: NONE - validation is skipped for software statement SCRIPT - (default), invokes getSoftwareStatementJwks of dynamic registration script which has to return jwks. JWKS - claim name within software statement that has inlined JWKS JWKS_URI - claim name within software statement that points to JWKS URI that should lead to keys. dcrSignatureValidationSoftwareStatementJwksURIClaim - specifies claim name inside software statement that should point to JWKS URI. dcrSignatureValidationSoftwareStatementJwksClaim - specifies claim name inside software statement. Value of claim should point to inlined JWKS. trustedSsaIssuers - map of trusted SSA issuers with configuration (e.g. automatically granted scopes). When empty - no issuers validation is performed. When not empty - AS forces validation and each SSA must match at least one entry from list. automaticallyGrantedScopes - automatically granted scopes for trusted issuer { \"https://trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"a\" , \"b\" ] }, \"https://another-trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"d\" ] } } Configure the AS using steps explained in the link", "title": "Using software statement"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#special-mention-about-fapi", "text": "In case of a typical client registration request in FAPI implementation , the request object which is a signed JWT (as seen in point 3) is also called an SSA (Software statement Assertion) or DCR payload. This SSA can contain the software_statement inside it which is also a signed JWT. Each of the JWTs, the outer JWT called the SSA and the inner JWT called the software_statement are signed by different entities - the TPP and OBIE respectively.", "title": "Special mention about FAPI:"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#security-pointers", "text": "If dynamicRegistrationEnabled is enabled in the Authorization Server, assess the following points to minimize potential exposure of sensitive personal data: trustedClientEnabled and dynamicRegistrationPersistClientAuthorizations properties determine whether clients are trusted and if consent should be sought from the user before releasing their personal data to the RP dynamicRegistrationScopesParamEnabled controls whether default scopes are globally enabled. If dynamicRegistrationScopesParamEnabled is true then scopes defined as default will be automatically added to any dynamically registered client entry without consent of OP's administrator. Therefore, make an informed decision before setting this field to true .", "title": "Security Pointers"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#curl-commands-to-configure-jans-auth-server", "text": "Jans-auth server is configured using Jans Config Api :", "title": "CURL commands to configure Jans-auth server"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#obtain-the-access-token", "text": "curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/jans-auth-server/config/properties.write\"", "title": "Obtain the access token"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#patch-jans-auth-server-configurations", "text": "Patch jans-auth server configurations to reflect anExampleConfigField with the value anExampleConfigField_value curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://<your.jans.server>/jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"anExampleConfigField\", \"value\": \"anExampleConfigField_value\" } ]' For example, to patch the jans-auth server configurations to reflect dynamicRegistrationEnabled with value as true curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://<your.jans.server>/jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"dynamicRegistrationEnabled\", \"value\": \"true\" } ]'", "title": "Patch jans-auth server configurations"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#client-metadata", "text": "Command to obtain metadata schema jans cli --schema /components/schemas/Client Output: { \"dn\" : \"string\" , \"inum\" : \"string\" , \"displayName\" : \"string\" , \"clientSecret\" : \"string\" , \"frontChannelLogoutUri\" : \"string\" , \"frontChannelLogoutSessionRequired\" : true , \"registrationAccessToken\" : \"string\" , \"clientIdIssuedAt\" : \"2022-08-31T10:39:31.385Z\" , \"clientSecretExpiresAt\" : \"2022-08-31T10:39:31.385Z\" , \"redirectUris\" : [ \"https://client.example.org/cb\" ], \"claimRedirectUris\" : [ \"string\" ], \"responseTypes\" : [ \"code\" ], \"grantTypes\" : [ \"authorization_code\" ], \"applicationType\" : \"web\" , \"contacts\" : [ \"string\" ], \"idTokenTokenBindingCnf\" : \"string\" , \"logoUri\" : \"string\" , \"clientUri\" : \"string\" , \"policyUri\" : \"string\" , \"tosUri\" : \"string\" , \"jwksUri\" : \"string\" , \"jwks\" : \"{ \\\"keys\\\" : [ { \\\"e\\\" : \\\"AQAB\\\", \\\"n\\\" : \\\"gmlDX_mgMcHX..\\\" ] }\" , \"sectorIdentifierUri\" : \"string\" , \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"HS256\" , \"idTokenEncryptedResponseAlg\" : \"RSA1_5\" , \"idTokenEncryptedResponseEnc\" : \"A128CBC+HS256\" , \"userInfoSignedResponseAlg\" : \"HS256\" , \"userInfoEncryptedResponseAlg\" : \"RSA1_5\" , \"userInfoEncryptedResponseEnc\" : \"A128CBC+HS256\" , \"requestObjectSigningAlg\" : \"HS256\" , \"requestObjectEncryptionAlg\" : \"RSA1_5\" , \"requestObjectEncryptionEnc\" : \"A128CBC+HS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"tokenEndpointAuthSigningAlg\" : \"HS256\" , \"defaultMaxAge\" : 1000000 , \"requireAuthTime\" : true , \"defaultAcrValues\" : [ \"string\" ], \"initiateLoginUri\" : \"string\" , \"postLogoutRedirectUris\" : [ \"https://client.example.org/logout/page1\" , \"https://client.example.org/logout/page2\" , \"https://client.example.org/logout/page3\" ], \"requestUris\" : [ \"string\" ], \"scopes\" : [ \"read write dolphin\" ], \"claims\" : [ \"string\" ], \"trustedClient\" : false , \"lastAccessTime\" : \"2022-08-31T10:39:31.385Z\" , \"lastLogonTime\" : \"2022-08-31T10:39:31.385Z\" , \"persistClientAuthorizations\" : true , \"includeClaimsInIdToken\" : false , \"refreshTokenLifetime\" : 100000000 , \"accessTokenLifetime\" : 100000000 , \"customAttributes\" : [ { \"name\" : \"name, displayName, birthdate, email\" , \"multiValued\" : true , \"values\" : [ \"string\" ] } ], \"customObjectClasses\" : [ \"string\" ], \"rptAsJwt\" : true , \"accessTokenAsJwt\" : true , \"accessTokenSigningAlg\" : \"HS256\" , \"disabled\" : false , \"authorizedOrigins\" : [ \"string\" ], \"softwareId\" : \"4NRB1-0XZABZI9E6-5SM3R\" , \"softwareVersion\" : \"2.1\" , \"softwareStatement\" : \"string\" , \"attributes\" : { \"tlsClientAuthSubjectDn\" : \"string\" , \"runIntrospectionScriptBeforeAccessTokenAsJwtCreationAndIncludeClaims\" : true , \"keepClientAuthorizationAfterExpiration\" : true , \"allowSpontaneousScopes\" : true , \"spontaneousScopes\" : [ \"string\" ], \"spontaneousScopeScriptDns\" : [ \"string\" ], \"updateTokenScriptDns\" : [ \"string\" ], \"backchannelLogoutUri\" : [ \"string\" ], \"backchannelLogoutSessionRequired\" : true , \"additionalAudience\" : [ \"string\" ], \"postAuthnScripts\" : [ \"string\" ], \"consentGatheringScripts\" : [ \"string\" ], \"introspectionScripts\" : [ \"string\" ], \"rptClaimsScripts\" : [ \"string\" ], \"ropcScripts\" : [ \"string\" ], \"parLifetime\" : 0 , \"requirePar\" : true , \"jansAuthSignedRespAlg\" : \"string\" , \"jansAuthEncRespAlg\" : \"string\" , \"jansAuthEncRespEnc\" : \"string\" , \"jansSubAttr\" : \"string\" , \"redirectUrisRegex\" : \"string\" , \"jansAuthorizedAcr\" : [ \"string\" ], \"jansDefaultPromptLogin\" : true }, \"backchannelTokenDeliveryMode\" : \"poll\" , \"backchannelClientNotificationEndpoint\" : \"string\" , \"backchannelAuthenticationRequestSigningAlg\" : \"RS256\" , \"backchannelUserCodeParameter\" : true , \"expirationDate\" : \"2022-08-31T10:39:31.385Z\" , \"deletable\" : false , \"jansId\" : \"string\" , \"description\" : \"string\" }", "title": "Client metadata"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#signed-dcr-and-ssa-validation", "text": "In OpenBanking case DCR (Dynamic Client Request) is signed and must contain SSA (Software Statement Assertion) inside it. Non-Normative Example: POST /register HTTP/1.1 Content-Type: application/jwt Accept: application/json Host: auth.bankone.com eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJJREFtYX... Decoded DCR Example: { \"typ\" : \"JWT\" , \"alg\" : \"ES256\" , \"kid\" : \"ABCD1234\" } { \"iss\" : \"Amazon TPPID\" , \"iat\" : 1492760444 , \"exp\" : 1524296444 , \"aud\" : \"https://authn.gluu.org\" , \"scope\" : \"openid makepayment\" , \"token_endpoint_auth_method\" : \"private_key_jwt\" , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"response_types\" : [ \"code\" ], \"id_token_signed_response_alg\" : \"ES256\" , \"request_object_signing_alg\" : \"ES256\" , \"software_id\" : \"65d1f27c-4aea-4549-9c21-60e495a7a86f\" , \"software_statement\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJlbXB0eSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJhZG1pbiI6dHJ1ZSwic2NvcGUiOiJzY29wZTEgc2NvcGUyIiwiY2xhaW1zIjoiY2xhaW0xIGNsYWltMiIsImlhdCI6MTY2OTgwNjc2MywiZXhwIjoxNjY5ODEwMzYzfQ.db0WQh2lmHkNYCWT8tSW684hqWTPJDTElppy42XM_lc\" } { Sig nature } AS has dcrSsaValidationConfigs configuration value which holds json array. It can be used to validated both DCR and SSA. Single item of this array has following properties: id - REQUIRED primary key for the entity type - REQUIRED either ssa or dcr displayName - Human friendly name in case we build an admin GUI for this description - Human friendly details scope - For SSA only -- list of allowed scopes the issuer can enable the client to request automatically. If not present, all scopes are allowed. allowed_claims - Any claims not listed in this list will be dropped. If not present, all claims are allowed. jwks - Public key jwks_uri - URI of public key issuers - For MTLS, list of issuers trusted configuration_endpoint - points to discovery page, e.g. https://examle.com/.well-known/openid-configuration configuration_endpoint_claim - e.g. ssa_jwks_endpoint shared_secret - for MTLS HMAC One of jwks , jwks_uri or issuers or configuration_endpoint is required. Non-normative example of dcrSsaValidationConfigs [ { \"id\" : \"735ee1c0-895d-4398-9c1b-9ad852257cc0\" , \"type\" : \"DCR\" , \"scopes\" : [ \"read\" , \"write\" ], \"allowedClaims\" : [ \"exp\" , \"iat\" ], \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"Acme\" ], \"sharedSecret\" : \"secret\" }, { \"id\" : \"7907cd0b-0f9f-4b4f-aaa2-0d0614546246\" , \"type\" : \"SSA\" , \"scopes\" : [ \"my_read\" , \"my_write\" ], \"allowedClaims\" : [ \"test_exp\" , \"test_iat\" ], \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"jans-auth\" ], \"sharedSecret\" : \"secret\" }, { \"id\" : \"1e95c9b1-04d0-4440-9362-88f4e1e62d76\" , \"type\" : \"SSA\" , \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"empty\" ], \"sharedSecret\" : \"secret\" } ]", "title": "Signed DCR and SSA validation"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#signed-dcr-validation", "text": "DCR can be validated with two approaches. Via dcrSsaValidationConfigs configuration property - RECOMMENDED When create entry in dcrSsaValidationConfigs configuration property : - type MUST be equal to DCR value - issuers MUST have value which equals to iss claim in DCR. Via other configuration properties trustedSsaIssuers - map of trusted SSA issuers with configuration (e.g. automatically granted scopes). When empty - no issuers validation is performed. When not empty - AS forces validation and each SSA must match at least one entry from list. automaticallyGrantedScopes - automatically granted scopes for trusted issuer { \"https://trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"a\" , \"b\" ] }, \"https://another-trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"d\" ] } } dcrSignatureValidationJwks - specifies JWKS for DCR's validations dcrSignatureValidationJwksUri - specifies JWKS URI for DCR's validations dcrSignatureValidationSharedSecret - if HMAC is used, this is the shared secret dcrSignatureValidationEnabled - boolean value enables DCR signature validation. Default is false dcrSignatureValidationSoftwareStatementJwksURIClaim - specifies claim name inside software statement. Value of claim should point to JWKS URI dcrSignatureValidationSoftwareStatementJwksClaim - specifies claim name inside software statement. Value of claim should point to inlined JWKS dcrAuthorizationWithClientCredentials - boolean value indicating if DCR authorization to be performed using client credentials", "title": "Signed DCR validation"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#ssa-validation", "text": "SSA is validated based on softwareStatementValidationType which is enum. softwareStatementValidationType = builtin - validation is performed against dcrSsaValidationConfigs configuration property, where type MUST be equal to SSA value issuers MUST have value which equals to iss claim in DCR. softwareStatementValidationType = script - jwks and hmac secret are returned by dynamic client registration script softwareStatementValidationType = jwks_uri , allows to specify jwks_uri claim name from software_statement. Claim name specified by softwareStatementValidationClaimName configuration property. softwareStatementValidationType = jwks , allows to specify jwks claim name from software_statement. Claim name specified by softwareStatementValidationClaimName configuration property. softwareStatementValidationType = none , no validation.", "title": "SSA Validation"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#customizing-the-behavior-of-the-as-using-interception-script", "text": "Janssen's allows developers to register a client with the Authorization Server (AS) without any intervention by the administrator. By default, all clients are given the same default scopes and attributes. Through the use of an interception script, this behavior can be modified. These scripts can be used to analyze the registration request and apply customizations to the registered client. For example, a client can be given specific scopes by analyzing the Software Statement that is sent with the registration request. Further reading here", "title": "Customizing the behavior of the AS using Interception script"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#the-use-of-attestation-in-dynamic-client-registration", "text": "AS supports \"The Use of Attestation in OAuth 2.0 Dynamic Client Registration\" specification draft . Specification draft does not define exact attestation request/response formats. Thus AS supports Attestation calls to Verifier via ClientRegistrationType custom script type. Use createClient method of ClientRegistrationType to prevent client creation if attestation result does not satisfy expectation. def createClient ( self , context ): print \"Client registration. CreateClient method\" registerRequest = context . getRegisterRequest () configurationAttributes = context . getConfigurationAttibutes () client = context . getClient () # getting evidence as string or as JWT evidenceAsString = registerRequest . getEvidence () evidenceAsJwt = context . getEvidence () # following code depends on attestation client used to make calls to Verifier attestationResult = attestationClient . attestation ( evidence ) if attestationResult . isFail : print \"Attestation result forbids client creation\" return False print \"Attestation result is OK\" return True Configuration options - dcrAttestationEvidenceRequired - Boolean value indicating if DCR attestation evidence is required. Default value is false . If evidence request parameter is not present and dcrAttestationEvidenceRequired is true AS returns stale_evidence error: HTTP/1.1 400 Bad Request Content-Type: application/json Cache-Control: no-store Pragma: no-cache { \"error\": \"stale_evidence\", \"error_description\": \"The provided evidence is not current.\", \"nonce\": \"lBjvTtuPbpzIaqyiAOOkrIol3WmflPUUepzUXNDFuUgMKUL\" } It is common to get nonce value from Attestation Server. In this case set dcrAttestationEvidenceRequired=false and throw error from custom script. def createClient ( self , context ): evidenceAsString = registerRequest . getEvidence () if StringHelper . isEmpty ( evidenceAsString ) nonceFromVerifier = attestationClient . requestNonce () context . createStaleEvidenceWebApplicationException ( nonceFromVerifier ) return False ... print \"Attestation result is OK\" return True context.createStaleEvidenceWebApplicationException(nonceFromVerifier) leads to stale_evidence error creation, see example above ( nonceFromVerifier must be string value). In case goal is to create own custom error, please use standard context.createWebApplicationException methods and return False from script to prevent client creation. Example entity = < construct error message > context . createWebApplicationException ( 400 , entity )", "title": "The Use of Attestation in Dynamic Client Registration"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#dynamic-registration-custom-attributes", "text": "", "title": "Dynamic registration custom attributes"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#crud-operations", "text": "Janssen Server allows client management through client configuration endpoint (RFC 7592) . JSON response to client registration request contains registration_client_uri and registration_access_token data elements. The URI mentioned using registration_client_uri provides functionality to read, update and delete the client. This endpoint is a protected endpoint where request has to be authenticated using access token registration_access_token .", "title": "CRUD Operations"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#read-client-metadata", "text": "A read request to the same client that got created in earlier section should be as shown in the example below. HTTP method GET is used to send the request which signifies that it is a request to read client metadata. curl -k -H 'Authorization: Bearer eaee20de-54ce-4217-b960-6b72b55e6cab' \\ -i 'https://my.jans.server/jans-auth/restv1/register?client_id=85192707-a38c-496c-806c-ef01a6a3ae4a' JSON response from Janssen Server will contain the current state of client metadata.", "title": "Read client metadata"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#update-client-metadata", "text": "Client metadata can be updated by sending request with PUT HTTP method to registration_client_uri . Janssen Server replaces current metadata with the one sent with update request as outlined in the specification", "title": "Update client metadata"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#delete-client", "text": "Client can be deleted by sending a request using DELETE method to registration_client_uri . A successful delete action will invalidate the \"client_id\", \"client_secret\", and \"registration_access_token\" for this client, thereby preventing the \"client_id\" from being used at either the authorization endpoint or token endpoint of the authorization server.", "title": "Delete Client"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#internationalization-for-client-metadata", "text": "", "title": "Internationalization for Client metadata"}, {"location": "janssen-server/auth-server/endpoints/clientinfo/", "tags": ["administration", "auth-server", "clientinfo", "endpoint"], "text": "Overview # /clientinfo endpoint is an OAuth2 protected endpoint that is used to retrieve claims about registered client. URL to access clientinfo endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration clientinfo_endpoint claim in the response specifies the URL for clientinfo endpoint. By default, clientinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/clientinfo Since clientinfo endpoint is an OAuth2 protected resource, a valid access token with appropriate scope is required to access the endpoint. More information about request and response of the clientinfo endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # /clientinfo endpoint can be enabled or disable using clientinfo feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable clientinfo flag as required. Configuration Properties # Clientinfo endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . clientInfoEndpoint mtlsClientInfoEndpoint Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Clientinfo"}, {"location": "janssen-server/auth-server/endpoints/clientinfo/#overview", "text": "/clientinfo endpoint is an OAuth2 protected endpoint that is used to retrieve claims about registered client. URL to access clientinfo endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration clientinfo_endpoint claim in the response specifies the URL for clientinfo endpoint. By default, clientinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/clientinfo Since clientinfo endpoint is an OAuth2 protected resource, a valid access token with appropriate scope is required to access the endpoint. More information about request and response of the clientinfo endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/clientinfo/#disabling-the-endpoint-using-feature-flag", "text": "/clientinfo endpoint can be enabled or disable using clientinfo feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable clientinfo flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/clientinfo/#configuration-properties", "text": "Clientinfo endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . clientInfoEndpoint mtlsClientInfoEndpoint", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/clientinfo/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/configuration/", "tags": ["administration", "auth-server", "well-known", "configuration", "endpoint"], "text": "OpenID Configuration Endpoint aka .well-known/openid-configuration # The Configuration Endpoint returns both the OP server metadata, and OAuth AS metdata, most of which is defined in the OpenID Discovery Spec , although other configuration metadata is defined in other OpenID specifications, or in OAuth specifications. If you want to customize the configuration response, you can use the OpenID Config Interception Script , which enables you to filter the results, modify claim values, or add claims. If you want to explicitly allow only certain OpenID Metadata claims, you can supply a list of the claims in the opConfigMetadataAllowList Auth Server Property. Below is a list of all the current available claims, and where they are specified. Claim Origin access_token_signing_alg_values_supported ? acr_values_supported OpenID authorization_encryption_alg_values_supported ? authorization_encryption_enc_values_supported ? authorization_endpoint OpenID authorization_signing_alg_values_supported ? backchannel_authentication_endpoint ? backchannel_logout_session_supported ? backchannel_logout_supported ? backchannel_token_delivery_modes_supported ? backchannel_user_code_parameter_supported ? check_session_iframe ? claim_types_supported ? claims_locales_supported ? claims_parameter_supported ? claims_supported OpenID clientinfo_endpoint ? device_authorization_endpoint ? display_values_supported ? dpop_signing_alg_values_supported ? end_session_endpoint ? frontchannel_logout_session_supported ? frontchannel_logout_supported ? grant_types_supported ? id_token_encryption_alg_values_supported ? id_token_encryption_enc_values_supported ? id_token_signing_alg_values_supported ? id_token_token_binding_cnf_values_supported ? introspection_endpoint ? issuer OpenID jwks_uri OpenID op_tos_uri OpenID pushed_authorization_request_endpoint ? registration_endpoint OpenID request_object_encryption_alg_values_supported OpenID request_object_encryption_enc_values_supported OpenID request_object_signing_alg_values_supported OpenID request_parameter_supported OpenID request_uri_parameter_supported OpenID require_pushed_authorization_requests ? require_request_uri_registration ? response_modes_supported OpenID response_types_supported OpenID revocation_endpoint ? scopes_supported ? service_documentation ? session_revocation_endpoint ? ssa_endpoint Janssen subject_types_supported OpenID tls_client_certificate_bound_access_tokens ? token_endpoint OpenID token_endpoint_auth_methods_supported OpenID token_endpoint_auth_signing_alg_values_supported OpenID ui_locales_supported OpenID userinfo_encryption_alg_values_supported OpenID userinfo_encryption_enc_values_supported OpenID userinfo_endpoint OpenID userinfo_signing_alg_values_supported OpenID Notes on specific OP Server Metadata claims # claims_supported Each user claim (in Jans jargon, \"Attribute\") has a property called jansHideOnDiscovery --if you don't want a claim to appear in .well-known/openid-configuration , set this to true for the Attribute entity. ssa_endpoint This is the endpoint which issues Software Statement Assertions JWT's. It is an OAuth protected endpoint.", "title": "OpenID Configuration"}, {"location": "janssen-server/auth-server/endpoints/configuration/#openid-configuration-endpoint-aka-well-knownopenid-configuration", "text": "The Configuration Endpoint returns both the OP server metadata, and OAuth AS metdata, most of which is defined in the OpenID Discovery Spec , although other configuration metadata is defined in other OpenID specifications, or in OAuth specifications. If you want to customize the configuration response, you can use the OpenID Config Interception Script , which enables you to filter the results, modify claim values, or add claims. If you want to explicitly allow only certain OpenID Metadata claims, you can supply a list of the claims in the opConfigMetadataAllowList Auth Server Property. Below is a list of all the current available claims, and where they are specified. Claim Origin access_token_signing_alg_values_supported ? acr_values_supported OpenID authorization_encryption_alg_values_supported ? authorization_encryption_enc_values_supported ? authorization_endpoint OpenID authorization_signing_alg_values_supported ? backchannel_authentication_endpoint ? backchannel_logout_session_supported ? backchannel_logout_supported ? backchannel_token_delivery_modes_supported ? backchannel_user_code_parameter_supported ? check_session_iframe ? claim_types_supported ? claims_locales_supported ? claims_parameter_supported ? claims_supported OpenID clientinfo_endpoint ? device_authorization_endpoint ? display_values_supported ? dpop_signing_alg_values_supported ? end_session_endpoint ? frontchannel_logout_session_supported ? frontchannel_logout_supported ? grant_types_supported ? id_token_encryption_alg_values_supported ? id_token_encryption_enc_values_supported ? id_token_signing_alg_values_supported ? id_token_token_binding_cnf_values_supported ? introspection_endpoint ? issuer OpenID jwks_uri OpenID op_tos_uri OpenID pushed_authorization_request_endpoint ? registration_endpoint OpenID request_object_encryption_alg_values_supported OpenID request_object_encryption_enc_values_supported OpenID request_object_signing_alg_values_supported OpenID request_parameter_supported OpenID request_uri_parameter_supported OpenID require_pushed_authorization_requests ? require_request_uri_registration ? response_modes_supported OpenID response_types_supported OpenID revocation_endpoint ? scopes_supported ? service_documentation ? session_revocation_endpoint ? ssa_endpoint Janssen subject_types_supported OpenID tls_client_certificate_bound_access_tokens ? token_endpoint OpenID token_endpoint_auth_methods_supported OpenID token_endpoint_auth_signing_alg_values_supported OpenID ui_locales_supported OpenID userinfo_encryption_alg_values_supported OpenID userinfo_encryption_enc_values_supported OpenID userinfo_endpoint OpenID userinfo_signing_alg_values_supported OpenID", "title": "OpenID Configuration Endpoint aka .well-known/openid-configuration"}, {"location": "janssen-server/auth-server/endpoints/configuration/#notes-on-specific-op-server-metadata-claims", "text": "claims_supported Each user claim (in Jans jargon, \"Attribute\") has a property called jansHideOnDiscovery --if you don't want a claim to appear in .well-known/openid-configuration , set this to true for the Attribute entity. ssa_endpoint This is the endpoint which issues Software Statement Assertions JWT's. It is an OAuth protected endpoint.", "title": "Notes on specific OP Server Metadata claims"}, {"location": "janssen-server/auth-server/endpoints/device-authorization/", "tags": ["administration", "auth-server", "endpoint", "device authorization", "RFC 8628"], "text": "Device Authorization endpoint # The URI to invoke the Device Authorization Endpoint in Janssen Auth Server can be found by checking the introspection_endpoint claim of the OpenID Connect configuration response, typically deployed at https://<my.jans.server>/.well-known/openid-configuration \"device_authorization_endpoint\" : \"https://<my.jans.server>/jans-auth/restv1/device_authorization\" Invoking the endpoint in Device Authorization Flow # The Device Authorization Grant defined by RFC 8628 contains a call to the Device Authorization endpoint in Step 2 of the diagram below. The details of the entire flow can be found in this article sequenceDiagram autonumber 1 title Oauth2.0 Device Authorization flow participant User participant Browser on Computer / Smartphone participant Device App participant Jans AS participant Third Party App User->>Device App:Opens an app on device Device App->>Jans AS:Sends authorization request \\n\"jans-server.com/jans-auth/restv1/device_authorization\" Jans AS->>Device App:Response - \\nuser_code, device_code, verification_url, interval, expiration Device App ->>User: Instructs the user to access Verification URL \\nand enter user_code note over Device App:Device App will keep polling AS for Access Token \\nuntil device authorization is completed loop till Device App recieves Access Token: Device App->>Jans AS:request Access Token Jans AS->>Device App:Response - \\naccess_denied \\nOR expired_token \\nOR authorization_pending \\nOR Access token end User->>Browser on Computer / Smartphone:Opens a browser \\nand access verification URL Browser on Computer / Smartphone->>Jans AS:send user_code to verification URL Jans AS -->> Browser on Computer / Smartphone :Login and authorization prompt Browser on Computer / Smartphone->>Jans AS:Authentication and consent Jans AS->>Jans AS: Mark device as Authorized note over Jans AS:Subsequent polling by the Device App \\nwill return an Access Token as indicated \\nby the loop above Device App->>Third Party App:Invoke API with Access Token Third Party App->>Device App: return Response Request: POST /restv1/device_authorization HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.org Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 client_id=123-123-123&scope=openid+profile+address+email+phone Response: HTTP/1.1 200 Content-Length: 307 Content-Type: application/json Server: Jetty(9.4.19.v20190610) { \"user_code\": \"SJFP-DTPL\", \"device_code\": \"aeb28bdc90d806ac58d4b0f832f06c3ac9c4bd03292f0c09\", \"interval\": 5, \"verification_uri_complete\": \"https://test.jans.io:8443/device-code?user_code=SJFP-DTPL\", \"verification_uri\": \"https://test.jans.io:8443/device-code\", \"expires_in\": 1800 }", "title": "Device Authorization"}, {"location": "janssen-server/auth-server/endpoints/device-authorization/#device-authorization-endpoint", "text": "The URI to invoke the Device Authorization Endpoint in Janssen Auth Server can be found by checking the introspection_endpoint claim of the OpenID Connect configuration response, typically deployed at https://<my.jans.server>/.well-known/openid-configuration \"device_authorization_endpoint\" : \"https://<my.jans.server>/jans-auth/restv1/device_authorization\"", "title": "Device Authorization endpoint"}, {"location": "janssen-server/auth-server/endpoints/device-authorization/#invoking-the-endpoint-in-device-authorization-flow", "text": "The Device Authorization Grant defined by RFC 8628 contains a call to the Device Authorization endpoint in Step 2 of the diagram below. The details of the entire flow can be found in this article sequenceDiagram autonumber 1 title Oauth2.0 Device Authorization flow participant User participant Browser on Computer / Smartphone participant Device App participant Jans AS participant Third Party App User->>Device App:Opens an app on device Device App->>Jans AS:Sends authorization request \\n\"jans-server.com/jans-auth/restv1/device_authorization\" Jans AS->>Device App:Response - \\nuser_code, device_code, verification_url, interval, expiration Device App ->>User: Instructs the user to access Verification URL \\nand enter user_code note over Device App:Device App will keep polling AS for Access Token \\nuntil device authorization is completed loop till Device App recieves Access Token: Device App->>Jans AS:request Access Token Jans AS->>Device App:Response - \\naccess_denied \\nOR expired_token \\nOR authorization_pending \\nOR Access token end User->>Browser on Computer / Smartphone:Opens a browser \\nand access verification URL Browser on Computer / Smartphone->>Jans AS:send user_code to verification URL Jans AS -->> Browser on Computer / Smartphone :Login and authorization prompt Browser on Computer / Smartphone->>Jans AS:Authentication and consent Jans AS->>Jans AS: Mark device as Authorized note over Jans AS:Subsequent polling by the Device App \\nwill return an Access Token as indicated \\nby the loop above Device App->>Third Party App:Invoke API with Access Token Third Party App->>Device App: return Response Request: POST /restv1/device_authorization HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.org Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 client_id=123-123-123&scope=openid+profile+address+email+phone Response: HTTP/1.1 200 Content-Length: 307 Content-Type: application/json Server: Jetty(9.4.19.v20190610) { \"user_code\": \"SJFP-DTPL\", \"device_code\": \"aeb28bdc90d806ac58d4b0f832f06c3ac9c4bd03292f0c09\", \"interval\": 5, \"verification_uri_complete\": \"https://test.jans.io:8443/device-code?user_code=SJFP-DTPL\", \"verification_uri\": \"https://test.jans.io:8443/device-code\", \"expires_in\": 1800 }", "title": "Invoking the endpoint in Device Authorization Flow"}, {"location": "janssen-server/auth-server/endpoints/end-session/", "tags": ["administration", "auth-server", "end-session", "endpoint"], "text": "Overview # Janssen Server's /end_session endpoint supports logout using OpenId Connect RP-initiated Logout mechanism. When using OpenID Connect Logout, it is recommended to use Front-Channel Logout. In Front-Channel Logout the browser receives a page with a list of application logout urls within an iframe. This prompts the browser to call each application logout individually and the OpenID Connect end-session endpoint via Javascript. URL to access end session endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration end_session_endpoint claim in the response specifies the URL for end session endpoint. By default, end session ndpoint looks like below: https://janssen.server.host/jans-auth/restv1/end_session Refer to this article from Gluu Server documentation to understand how end session endpoint works in Janssen Server. More information about request and response of the end session endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # /end_session endpoint can be enabled or disable using END_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable END_SESSION flag as required. Configuration Properties # End session endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . allowEndSessionWithUnmatchedSid endSessionEndpoint endSessionWithAccessToken mtlsEndSessionEndpoint rejectEndSessionIfIdTokenExpired allowPostLogoutRedirectWithoutValidation forceIdTokenHintPresence Apart from the above-mentioned server properties, the properties relevant to individual clients can be configured during client registration or can be edited later. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Clients -> logout as show in image below: Interception Scripts # Response from end session endpoint can be further customized using end session interception script. This script can be used to customize the HTML response generated from end session endpoint. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "End Session"}, {"location": "janssen-server/auth-server/endpoints/end-session/#overview", "text": "Janssen Server's /end_session endpoint supports logout using OpenId Connect RP-initiated Logout mechanism. When using OpenID Connect Logout, it is recommended to use Front-Channel Logout. In Front-Channel Logout the browser receives a page with a list of application logout urls within an iframe. This prompts the browser to call each application logout individually and the OpenID Connect end-session endpoint via Javascript. URL to access end session endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration end_session_endpoint claim in the response specifies the URL for end session endpoint. By default, end session ndpoint looks like below: https://janssen.server.host/jans-auth/restv1/end_session Refer to this article from Gluu Server documentation to understand how end session endpoint works in Janssen Server. More information about request and response of the end session endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/end-session/#disabling-the-endpoint-using-feature-flag", "text": "/end_session endpoint can be enabled or disable using END_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable END_SESSION flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/end-session/#configuration-properties", "text": "End session endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . allowEndSessionWithUnmatchedSid endSessionEndpoint endSessionWithAccessToken mtlsEndSessionEndpoint rejectEndSessionIfIdTokenExpired allowPostLogoutRedirectWithoutValidation forceIdTokenHintPresence Apart from the above-mentioned server properties, the properties relevant to individual clients can be configured during client registration or can be edited later. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Clients -> logout as show in image below:", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/end-session/#interception-scripts", "text": "Response from end session endpoint can be further customized using end session interception script. This script can be used to customize the HTML response generated from end session endpoint.", "title": "Interception Scripts"}, {"location": "janssen-server/auth-server/endpoints/end-session/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/global-token-revocation/", "tags": ["administration", "auth-server", "session-revocation", "endpoint"], "text": "Overview # Janssen Server provides global token revocation endpoint to enable the client to revoke all tokens and sessions of a user. Janssen Server provides this endpoint to allow greater control and better management of sessions on OP. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration global_token_revocation_endpoint claim in the response specifies the URL for global token revocation endpoint. By default, global token revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/global-token-revocation More information about request and response of the global token revocation endpoint can be found in the OpenAPI specification of jans-auth-server module . Usage # A request to this endpoint can revoke all tokens and sessions of one particular user. Use the request parameters to specify criteria to select the user. If there are multiple users matching the given criteria, the first found user will be affected. View full sample execution log here Disabling The Endpoint Using Feature Flag # Global Token Revocation endpoint can be enabled or disable using GLOBAL_TOKEN_REVOCATION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable GLOBAL_TOKEN_REVOCATION flag as required. Required Scopes # A client must have the following scope in order to use this endpoint: global_token_revocation", "title": "Global Token Revocation"}, {"location": "janssen-server/auth-server/endpoints/global-token-revocation/#overview", "text": "Janssen Server provides global token revocation endpoint to enable the client to revoke all tokens and sessions of a user. Janssen Server provides this endpoint to allow greater control and better management of sessions on OP. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration global_token_revocation_endpoint claim in the response specifies the URL for global token revocation endpoint. By default, global token revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/global-token-revocation More information about request and response of the global token revocation endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/global-token-revocation/#usage", "text": "A request to this endpoint can revoke all tokens and sessions of one particular user. Use the request parameters to specify criteria to select the user. If there are multiple users matching the given criteria, the first found user will be affected. View full sample execution log here", "title": "Usage"}, {"location": "janssen-server/auth-server/endpoints/global-token-revocation/#disabling-the-endpoint-using-feature-flag", "text": "Global Token Revocation endpoint can be enabled or disable using GLOBAL_TOKEN_REVOCATION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable GLOBAL_TOKEN_REVOCATION flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/global-token-revocation/#required-scopes", "text": "A client must have the following scope in order to use this endpoint: global_token_revocation", "title": "Required Scopes"}, {"location": "janssen-server/auth-server/endpoints/introspection/", "tags": ["administration", "auth-server", "endpoint", "introspection", "accessTokenAsJwt", "introspectionScriptBackwardCompatibility"], "text": "Introspection Endpoint # Introspection endpoint allows a protected resource to determine the active state of an OAuth 2.0 token and to determine meta-information about this token. This endpoint can be used to introspect both opaque token (i.e. reference tokens) and structured tokens(i.e. value tokens). This endpoint conforms to OAuth2 token introspection specifications. The URI to invoke the introspection endpoint in Janssen Server can be found by checking the introspection_endpoint claim of the OpenID Connect configuration response, typically deployed at https://janssen.server.host/.well-known/openid-configuration \"introspection_endpoint\" : \"https://janssen.server.host/jans-auth/restv1/introspection\" ` More information about request and response of the Introspection endpoint can be found in the OpenAPI specification of jans-auth-server module . Request parameters token - REQUIRED. The string value of the token. For access tokens, this is the \"access_token\" value returned from the token endpoint token_type_hint - OPTIONAL. A hint about the type of the token submitted for introspection. Not used in current implementation of the AS. response_as_jwt - OPTIONAL. Boolean value with default value false. If true, returns introspection response as JWT (signed based on client configuration used for authentication to Introspection Endpoint). Sample GET Request # Request # curl -X 'GET' 'https://janssen.server.host/jans-auth/restv1/introspection?token=368fea2b-be14-4d30-bd57-bcc4cde2033c&response_as_jwt=false' -H 'accept: application/json' -H \"Authorization: Bearer 111d51a4-2828-4b47-abce-77034cddcfb5\" Response # { \"sub\" : \"\" , \"iss\" : \"https://janssen.server.host\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"1800.df1bb233-10b8-40ed-bbb9-07da50892a35\" , \"aud\" : \"1800.df1bb233-10b8-40ed-bbb9-07da50892a35\" , \"nbf\" : null , \"scope\" : \"https://jans.io/oauth/config/scripts.write\" , \"acr_values\" : null , \"cnf\" : null , \"exp\" : 1668705523 , \"iat\" : 1668705223 , \"jti\" : null , \"username\" : null } Sample POST Request # Request # curl -X 'POST' \\ 'https://janssen.server.host/jans-auth/restv1/introspection' \\ -H 'accept: application/json' \\ -H 'Content-Type: application/x-www-form-urlencoded' \\ -d 'token=eyJra....3ZkB-Ajwg' -H \"Authorization: Bearer eyJra...BpKo7g\" Response # { \"sub\" : \"\" , \"iss\" : \"https://janssen.server.host\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad\" , \"aud\" : \"3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad\" , \"nbf\" : null , \"scope\" : \"\" , \"acr_values\" : null , \"cnf\" : null , \"exp\" : 1668941216 , \"iat\" : 1668781885 , \"jti\" : null , \"username\" : null } Response as JWT # Response is returned as JWT if Accept header has value application/token-introspection+jwt or otherwise if explicit endpoint parameter response_as_jwt is set to true . POST /introspect HTTP/1.1 Host: as.example.com Accept: application/token-introspection+jwt Sample decoded JWT payload { \"iss\" : \"https://as.example.com/\" , \"aud\" : \"https://rs.example.com/resource\" , \"iat\" : 1514797892 , \"token_introspection\" : { \"active\" : true , \"iss\" : \"https://as.example.com/\" , \"aud\" : \"https://rs.example.com/resource\" , \"iat\" : 1514797822 , \"exp\" : 1514797942 , \"client_id\" : \"paiB2goo0a\" , \"scope\" : \"read write dolphin\" , \"sub\" : \"Z5O3upPC88QrAjx00dis\" , \"birthdate\" : \"1982-02-01\" , \"given_name\" : \"John\" , \"family_name\" : \"Doe\" , \"jti\" : \"t1FoCCaZd4Xv4ORJUWVUeTZfsKhW30CQCrWDDjwXy6w\" } } Sample response (line breaks in payload is for convenience) HTTP/1.1 200 OK Content-Type: application/token-introspection+jwt eyJraWQiOiJ3RzZEIiwidHlwIjoidG9rZW4taW50cm9zcGVjdGlvbitqd3QiLCJhbGc iOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6I mh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcmVzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4OTIs InRva2VuX2ludHJvc3BlY3Rpb24iOnsiYWN0aXZlIjp0cnVlLCJpc3MiOiJodHRwczo vL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6Imh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcm Vzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4MjIsImV4cCI6MTUxNDc5Nzk0MiwiY2xpZW50X 2lkIjoicGFpQjJnb28wYSIsInNjb3BlIjoicmVhZCB3cml0ZSBkb2xwaGluIiwic3Vi IjoiWjVPM3VwUEM4OFFyQWp4MDBkaXMiLCJiaXJ0aGRhdGUiOiIxOTgyLTAyLTAxIiw iZ2l2ZW5fbmFtZSI6IkpvaG4iLCJmYW1pbHlfbmFtZSI6IkRvZSIsImp0aSI6InQxRm 9DQ2FaZDRYdjRPUkpVV1ZVZVRaZnNLaFczMENRQ3JXRERqd1h5NncifX0.przJMU5Gh mNzvwtt1Sr-xa9xTkpiAg5IshbQsRiRVP_7eGR1GHYrNwQh84kxOkHCyje2g5WSRcYo sGEVIiC-eoPJJ-qBwqwSlgx9JEeCDw2W5DjrblOI_N0Jvsq_dUeOyoWVMqlOydOBhKN Y0smBrI4NZvEExucOm9WUJXMuJtvq1gBes-0go5j4TEv9sOP9uu81gqWTr_LOo6pgT0 tFFyZfWC4kbXPXiQ2YT6mxCiQRRNM-l9cBdF6Jx6IOrsfFhBuYdYQ_mlL19HgDDOFal eyqmru6lKlASOsaE8dmLSeKcX91FbG79FKN8un24iwIDCbKT9xlUFl54xWVShNDFA Disabling The Endpoint Using Feature Flag # /introspection endpoint can be enabled or disable using END_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable INTROSPECTION flag as required. Configuration Properties # Introspection endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . introspectionEndpoint mtlsIntrospectionEndpoint introspectionSkipAuthorization introspectionScriptBackwardCompatibility introspectionAccessTokenMustHaveUmaProtectionScope introspectionAccessTokenMustHaveIntrospectionScope introspectionResponseScopesBackwardCompatibility There difference between introspectionAccessTokenMustHaveUmaProtectionScope and introspectionAccessTokenMustHaveIntrospectionScope is that uma_protection scope is enabled for Dynamic Client Registration while introspection scope is not. Thus if set introspectionAccessTokenMustHaveIntrospectionScope to true value allows disable access to Introspection Endpoint to all clients which does not have explicitly granted introspection scope. Customising Introspection Endpoint Behaviour using Custom script: # Customizing certain aspects of endpoint behaviour, for example, one can modify claims of an access token as JWT, using introspection scripts . Use update token introspection script for transformation of claims and values in id-token and access-token. Configure below-mentioned client properties to enable usage of introspection scripts. When using Janssen Text-based UI(TUI) to configure these client properties, navigate to accessTokenAsJwt : Auth Server -> Clients ->select the client-> Tokens -> Access Token Type ->Select JWT runIntrospectionScriptBeforeJwtCreation : Auth Server -> Clients ->select the client-> Tokens ->enable Run Introspection Script before JWT access token creation References for custom scripts # Interface - IntrospectionType Introspection scripts Introspection script vs Update Token Script", "title": "Introspection"}, {"location": "janssen-server/auth-server/endpoints/introspection/#introspection-endpoint", "text": "Introspection endpoint allows a protected resource to determine the active state of an OAuth 2.0 token and to determine meta-information about this token. This endpoint can be used to introspect both opaque token (i.e. reference tokens) and structured tokens(i.e. value tokens). This endpoint conforms to OAuth2 token introspection specifications. The URI to invoke the introspection endpoint in Janssen Server can be found by checking the introspection_endpoint claim of the OpenID Connect configuration response, typically deployed at https://janssen.server.host/.well-known/openid-configuration \"introspection_endpoint\" : \"https://janssen.server.host/jans-auth/restv1/introspection\" ` More information about request and response of the Introspection endpoint can be found in the OpenAPI specification of jans-auth-server module . Request parameters token - REQUIRED. The string value of the token. For access tokens, this is the \"access_token\" value returned from the token endpoint token_type_hint - OPTIONAL. A hint about the type of the token submitted for introspection. Not used in current implementation of the AS. response_as_jwt - OPTIONAL. Boolean value with default value false. If true, returns introspection response as JWT (signed based on client configuration used for authentication to Introspection Endpoint).", "title": "Introspection Endpoint"}, {"location": "janssen-server/auth-server/endpoints/introspection/#sample-get-request", "text": "", "title": "Sample GET Request"}, {"location": "janssen-server/auth-server/endpoints/introspection/#request", "text": "curl -X 'GET' 'https://janssen.server.host/jans-auth/restv1/introspection?token=368fea2b-be14-4d30-bd57-bcc4cde2033c&response_as_jwt=false' -H 'accept: application/json' -H \"Authorization: Bearer 111d51a4-2828-4b47-abce-77034cddcfb5\"", "title": "Request"}, {"location": "janssen-server/auth-server/endpoints/introspection/#response", "text": "{ \"sub\" : \"\" , \"iss\" : \"https://janssen.server.host\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"1800.df1bb233-10b8-40ed-bbb9-07da50892a35\" , \"aud\" : \"1800.df1bb233-10b8-40ed-bbb9-07da50892a35\" , \"nbf\" : null , \"scope\" : \"https://jans.io/oauth/config/scripts.write\" , \"acr_values\" : null , \"cnf\" : null , \"exp\" : 1668705523 , \"iat\" : 1668705223 , \"jti\" : null , \"username\" : null }", "title": "Response"}, {"location": "janssen-server/auth-server/endpoints/introspection/#sample-post-request", "text": "", "title": "Sample POST Request"}, {"location": "janssen-server/auth-server/endpoints/introspection/#request_1", "text": "curl -X 'POST' \\ 'https://janssen.server.host/jans-auth/restv1/introspection' \\ -H 'accept: application/json' \\ -H 'Content-Type: application/x-www-form-urlencoded' \\ -d 'token=eyJra....3ZkB-Ajwg' -H \"Authorization: Bearer eyJra...BpKo7g\"", "title": "Request"}, {"location": "janssen-server/auth-server/endpoints/introspection/#response_1", "text": "{ \"sub\" : \"\" , \"iss\" : \"https://janssen.server.host\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad\" , \"aud\" : \"3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad\" , \"nbf\" : null , \"scope\" : \"\" , \"acr_values\" : null , \"cnf\" : null , \"exp\" : 1668941216 , \"iat\" : 1668781885 , \"jti\" : null , \"username\" : null }", "title": "Response"}, {"location": "janssen-server/auth-server/endpoints/introspection/#response-as-jwt", "text": "Response is returned as JWT if Accept header has value application/token-introspection+jwt or otherwise if explicit endpoint parameter response_as_jwt is set to true . POST /introspect HTTP/1.1 Host: as.example.com Accept: application/token-introspection+jwt Sample decoded JWT payload { \"iss\" : \"https://as.example.com/\" , \"aud\" : \"https://rs.example.com/resource\" , \"iat\" : 1514797892 , \"token_introspection\" : { \"active\" : true , \"iss\" : \"https://as.example.com/\" , \"aud\" : \"https://rs.example.com/resource\" , \"iat\" : 1514797822 , \"exp\" : 1514797942 , \"client_id\" : \"paiB2goo0a\" , \"scope\" : \"read write dolphin\" , \"sub\" : \"Z5O3upPC88QrAjx00dis\" , \"birthdate\" : \"1982-02-01\" , \"given_name\" : \"John\" , \"family_name\" : \"Doe\" , \"jti\" : \"t1FoCCaZd4Xv4ORJUWVUeTZfsKhW30CQCrWDDjwXy6w\" } } Sample response (line breaks in payload is for convenience) HTTP/1.1 200 OK Content-Type: application/token-introspection+jwt eyJraWQiOiJ3RzZEIiwidHlwIjoidG9rZW4taW50cm9zcGVjdGlvbitqd3QiLCJhbGc iOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6I mh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcmVzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4OTIs InRva2VuX2ludHJvc3BlY3Rpb24iOnsiYWN0aXZlIjp0cnVlLCJpc3MiOiJodHRwczo vL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6Imh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcm Vzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4MjIsImV4cCI6MTUxNDc5Nzk0MiwiY2xpZW50X 2lkIjoicGFpQjJnb28wYSIsInNjb3BlIjoicmVhZCB3cml0ZSBkb2xwaGluIiwic3Vi IjoiWjVPM3VwUEM4OFFyQWp4MDBkaXMiLCJiaXJ0aGRhdGUiOiIxOTgyLTAyLTAxIiw iZ2l2ZW5fbmFtZSI6IkpvaG4iLCJmYW1pbHlfbmFtZSI6IkRvZSIsImp0aSI6InQxRm 9DQ2FaZDRYdjRPUkpVV1ZVZVRaZnNLaFczMENRQ3JXRERqd1h5NncifX0.przJMU5Gh mNzvwtt1Sr-xa9xTkpiAg5IshbQsRiRVP_7eGR1GHYrNwQh84kxOkHCyje2g5WSRcYo sGEVIiC-eoPJJ-qBwqwSlgx9JEeCDw2W5DjrblOI_N0Jvsq_dUeOyoWVMqlOydOBhKN Y0smBrI4NZvEExucOm9WUJXMuJtvq1gBes-0go5j4TEv9sOP9uu81gqWTr_LOo6pgT0 tFFyZfWC4kbXPXiQ2YT6mxCiQRRNM-l9cBdF6Jx6IOrsfFhBuYdYQ_mlL19HgDDOFal eyqmru6lKlASOsaE8dmLSeKcX91FbG79FKN8un24iwIDCbKT9xlUFl54xWVShNDFA", "title": "Response as JWT"}, {"location": "janssen-server/auth-server/endpoints/introspection/#disabling-the-endpoint-using-feature-flag", "text": "/introspection endpoint can be enabled or disable using END_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable INTROSPECTION flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/introspection/#configuration-properties", "text": "Introspection endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . introspectionEndpoint mtlsIntrospectionEndpoint introspectionSkipAuthorization introspectionScriptBackwardCompatibility introspectionAccessTokenMustHaveUmaProtectionScope introspectionAccessTokenMustHaveIntrospectionScope introspectionResponseScopesBackwardCompatibility There difference between introspectionAccessTokenMustHaveUmaProtectionScope and introspectionAccessTokenMustHaveIntrospectionScope is that uma_protection scope is enabled for Dynamic Client Registration while introspection scope is not. Thus if set introspectionAccessTokenMustHaveIntrospectionScope to true value allows disable access to Introspection Endpoint to all clients which does not have explicitly granted introspection scope.", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/introspection/#customising-introspection-endpoint-behaviour-using-custom-script", "text": "Customizing certain aspects of endpoint behaviour, for example, one can modify claims of an access token as JWT, using introspection scripts . Use update token introspection script for transformation of claims and values in id-token and access-token. Configure below-mentioned client properties to enable usage of introspection scripts. When using Janssen Text-based UI(TUI) to configure these client properties, navigate to accessTokenAsJwt : Auth Server -> Clients ->select the client-> Tokens -> Access Token Type ->Select JWT runIntrospectionScriptBeforeJwtCreation : Auth Server -> Clients ->select the client-> Tokens ->enable Run Introspection Script before JWT access token creation", "title": "Customising Introspection Endpoint Behaviour using Custom script:"}, {"location": "janssen-server/auth-server/endpoints/introspection/#references-for-custom-scripts", "text": "Interface - IntrospectionType Introspection scripts Introspection script vs Update Token Script", "title": "References for custom scripts"}, {"location": "janssen-server/auth-server/endpoints/jwks-uri/", "tags": ["administration", "auth-server", "jwks", "json-web-key-set", "endpoint"], "text": "Overview # Janssen Server supports /jwks metadata endpoint and publishes its JSON Web Key Set (JWKS) at this endpoint. This endpoint publishes signing keys as well as encryption keys used by Janssen Server. RP can use these keys to validate signatures from Janssen Server, and also to perform encryption and decryption. Like other metadata endpoints, this is not a secure endpoint. Further details on this endpoint and JWKs can be found in OpenID Connect Discovery specification. URL to access jwks endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration jwks_uri claim in the response specifies the URL for jwks endpoint. By default, the jwks endpoint looks like below: https://janssen.server.host/jans-auth/restv1/jwks This endpoint is always enabled and can not be disabled using feature flags. Configuration Properties # End session endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . jwksUri jwksAlgorithmsSupported mtlsJwksUri Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "JWKS URI"}, {"location": "janssen-server/auth-server/endpoints/jwks-uri/#overview", "text": "Janssen Server supports /jwks metadata endpoint and publishes its JSON Web Key Set (JWKS) at this endpoint. This endpoint publishes signing keys as well as encryption keys used by Janssen Server. RP can use these keys to validate signatures from Janssen Server, and also to perform encryption and decryption. Like other metadata endpoints, this is not a secure endpoint. Further details on this endpoint and JWKs can be found in OpenID Connect Discovery specification. URL to access jwks endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration jwks_uri claim in the response specifies the URL for jwks endpoint. By default, the jwks endpoint looks like below: https://janssen.server.host/jans-auth/restv1/jwks This endpoint is always enabled and can not be disabled using feature flags.", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/jwks-uri/#configuration-properties", "text": "End session endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . jwksUri jwksAlgorithmsSupported mtlsJwksUri", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/jwks-uri/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/par/", "tags": ["administration", "auth-server", "par", "pushed authorization requests", "endpoint"], "text": "Pushed Authorization Request (PAR) Endpoint # PAR endpoint is used by client to send authorization request directly to the Janssen Server without using the usual redirection mechanism via user agent. When PAR endpoint receives a valid request, it responds with a request URI. The request URI is a reference created and stored by Janssen Server. It is a reference to authorization request and the metadata sent with it by the client. Client can send this request uri to the Janssen Server in a authorization request using user agent redirect mechanism. There are multiple benefits of using this flow which are described along with other details in PAR specification . Janssen Server PAR implementation conforms to PAR specification. URL to access PAR endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration pushed_authorization_request_endpoint claim in the response specifies the URL for the PAR endpoint. By default, PAR endpoint looks like below: https://jans-dynamic-mysql/jans-auth/restv1/par In response to a valid request, the PAR endpoint returns request_uri in response similar to below: HTTP/1.1 201 Created Content-Type: application/json Cache-Control: no-cache, no-store { \"request_uri\": \"urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c\", \"expires_in\": 60 } Since PAR endpoint is a protected resource. The client has to authenticate itself to the endpoint. Authentication methods used are same as the once used for client authentication at token endpoint . More information about request and response of the PAR endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # PAR endpoint can be enabled or disabled using PAR feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable PAR flag as required. Configuration Properties # Global Janssen Server configuration properties # PAR endpoint can be further configured using Janssen Server configuration properties listed below. It can be configured via Janssen Text-based UI(TUI) (navigate to Auth Server -> Properties ), admin UI or directly in persistence layer. mtlsParEndpoint - Mutual TLS (mTLS) Pushed Authorization Requests (PAR) endpoint URL parEndpoint - Pushed Authorization Requests (PAR) Endpoint location requirePar - Boolean value to indicate whether Pushed Authorisation Request (PAR) endpoint is required requestUriParameterSupported - Boolean value specifying whether the OP supports use of the request_uri parameter Client specific PAR related configuration properties # Some configuration properties are configured on client level to allow more granular configuration which depends on client. par_lifetime - PAR object lifetime in seconds. If value is not specified then defaults to 600 value. require_par - specified whether all authorization requests made by this client to Authorization Endpoint must be PAR. If true and authorization request is not PAR then error is returned back by Authorization Server. Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "PAR"}, {"location": "janssen-server/auth-server/endpoints/par/#pushed-authorization-request-par-endpoint", "text": "PAR endpoint is used by client to send authorization request directly to the Janssen Server without using the usual redirection mechanism via user agent. When PAR endpoint receives a valid request, it responds with a request URI. The request URI is a reference created and stored by Janssen Server. It is a reference to authorization request and the metadata sent with it by the client. Client can send this request uri to the Janssen Server in a authorization request using user agent redirect mechanism. There are multiple benefits of using this flow which are described along with other details in PAR specification . Janssen Server PAR implementation conforms to PAR specification. URL to access PAR endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration pushed_authorization_request_endpoint claim in the response specifies the URL for the PAR endpoint. By default, PAR endpoint looks like below: https://jans-dynamic-mysql/jans-auth/restv1/par In response to a valid request, the PAR endpoint returns request_uri in response similar to below: HTTP/1.1 201 Created Content-Type: application/json Cache-Control: no-cache, no-store { \"request_uri\": \"urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c\", \"expires_in\": 60 } Since PAR endpoint is a protected resource. The client has to authenticate itself to the endpoint. Authentication methods used are same as the once used for client authentication at token endpoint . More information about request and response of the PAR endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Pushed Authorization Request (PAR) Endpoint"}, {"location": "janssen-server/auth-server/endpoints/par/#disabling-the-endpoint-using-feature-flag", "text": "PAR endpoint can be enabled or disabled using PAR feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable PAR flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/par/#configuration-properties", "text": "", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/par/#global-janssen-server-configuration-properties", "text": "PAR endpoint can be further configured using Janssen Server configuration properties listed below. It can be configured via Janssen Text-based UI(TUI) (navigate to Auth Server -> Properties ), admin UI or directly in persistence layer. mtlsParEndpoint - Mutual TLS (mTLS) Pushed Authorization Requests (PAR) endpoint URL parEndpoint - Pushed Authorization Requests (PAR) Endpoint location requirePar - Boolean value to indicate whether Pushed Authorisation Request (PAR) endpoint is required requestUriParameterSupported - Boolean value specifying whether the OP supports use of the request_uri parameter", "title": "Global Janssen Server configuration properties"}, {"location": "janssen-server/auth-server/endpoints/par/#client-specific-par-related-configuration-properties", "text": "Some configuration properties are configured on client level to allow more granular configuration which depends on client. par_lifetime - PAR object lifetime in seconds. If value is not specified then defaults to 600 value. require_par - specified whether all authorization requests made by this client to Authorization Endpoint must be PAR. If true and authorization request is not PAR then error is returned back by Authorization Server.", "title": "Client specific PAR related configuration properties"}, {"location": "janssen-server/auth-server/endpoints/par/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/endpoints/par/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/session-revocation/", "tags": ["administration", "auth-server", "session-revocation", "endpoint"], "text": "Overview # Janssen Server provides session revocation endpoint to enable the client to revoke all sessions of a users. Though not being part of any industry standard/specification, Janssen Server provides this endpoint to allow greater control and better management of sessions on OP. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration session_revocation_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/revoke_session More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module . Usage # A request to this endpoint can revoke all sessions of one particular user. Use the request parameters to specify criteria to select the user. If there are multiple users matching the given criteria, the first found user will be affected. Disabling The Endpoint Using Feature Flag # Session revocation endpoint can be enabled or disable using REVOKE_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable REVOKE_SESSION flag as required. Required Scopes # A client must have the following scope in order to use this endpoint: revoke_session", "title": "Session Revocation"}, {"location": "janssen-server/auth-server/endpoints/session-revocation/#overview", "text": "Janssen Server provides session revocation endpoint to enable the client to revoke all sessions of a users. Though not being part of any industry standard/specification, Janssen Server provides this endpoint to allow greater control and better management of sessions on OP. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration session_revocation_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/revoke_session More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/session-revocation/#usage", "text": "A request to this endpoint can revoke all sessions of one particular user. Use the request parameters to specify criteria to select the user. If there are multiple users matching the given criteria, the first found user will be affected.", "title": "Usage"}, {"location": "janssen-server/auth-server/endpoints/session-revocation/#disabling-the-endpoint-using-feature-flag", "text": "Session revocation endpoint can be enabled or disable using REVOKE_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable REVOKE_SESSION flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/session-revocation/#required-scopes", "text": "A client must have the following scope in order to use this endpoint: revoke_session", "title": "Required Scopes"}, {"location": "janssen-server/auth-server/endpoints/ssa/", "tags": ["administration", "auth-server", "SSA", "endpoint"], "text": "Software Statement Assertion (SSA) # Janssen Server provides SSA endpoint that enables management of SSAs. The SSA is a JSON Web Token (JWT) containing client metadata and some custom attributes. Specification for SSAs has been outlined as part of Dynamic Client Registration Protocol . URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration ssa_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/ssa More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # /ssa endpoint can be enabled or disable using SSA feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable SSA flag as required. Configuration Properties # SSA endpoint can be further configured using Janssen Server configuration property ssaConfiguration . When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties to update value for this property. This property take JSON configuration with parameters as described below: \"ssaConfiguration\": { \"ssaEndpoint\": \"{{your-url}}/ssa\", \"ssaCustomAttributes\": [ \"myCustomAttr1\", \"myCustomAttr2\", ... ], \"ssaSigningAlg\": \"RS512\", \"ssaExpirationInDays\": 30 } ssaEndpoint \u2014 Base endpoint for SSA. ssaCustomAttributes \u2014 List of custom attributes, which are received in the request when creating an SSA. ssaSigningAlg \u2014 Algorithm to sign the JWT that is returned after creating an SSA. ssaExpirationInDays \u2014 Expiration expressed in days, when an SSA is created and the expiration is not sent. SSA Security # To call SSA services, a token of type client_credentials must be generated with the following scopes enabled: https://jans.io/auth/ssa.admin \u2014 Allows calling all SSA services. https://jans.io/auth/ssa.portal \u2014 Allows only call Get SSA service. https://jans.io/auth/ssa.developer \u2014 Allows only call Get SSA , but you can only filter ssa that have been created by the same client. Create a new SSA # Create SSA for the organization with expiration (optional). Request body description # Field Detail Optional org_id The \"org_id\" is used for organization identification. false description Describe SSA false software_id The \"software_id\" is used for software identification. false software_roles List of string values, fixed value [\"password\", \"notify\"] . false grant_types Fixed value Fixed value [\"client_credentials\"] . false expiration Expiration date. (Default value: calculated based on global SSA settings) true one_time_use Defined whether the SSA will be used only once or can be used multiple times. (Default value: true) true rotate_ssa TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. (Default value: true) true lifetime SSA Lifetime in seconds true Note: You can add more custom attributes in the request, (you must have previously configured in the SSA global configuration). It should be clarified that these values are persisted in the database and are not returned in the SSA JWT. Example: { \"org_id\": \"your-org-id\", \"description\": \"your description\", ..., \"myCustomAttr1\": \"Your value custom attr 1\", \"myCustomAttr2\": \"Your value custom attr 2\" } Response description # Returned SSA is a JWT, containing the following structure: { \"ssa\": \"eyJraWQiOiI1NTk3MGFkZS00M2MwLTQ4YWMtODEyZi0yZTY1MzhjMTEyN2Zfc2lnX3JzNTEyIiwidHlwIjoiand0IiwiYWxnIjoiUlM1MTIifQ.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoxLCJpc3MiOiJodHRwczovL2phbnMubG9jYWxob3N0Iiwic29mdHdhcmVfcm9sZXMiOlsicGFzc3d1cmQiXSwiZXhwIjoxNjY4NjA5MDA1LCJpYXQiOjE2Njg2NDE5NjcsImp0aSI6ImU4OWVjYTQxLTM0ODUtNDUxNi1hMTYyLWZiODYyNjJhYmFjMyJ9.jRgh8_aiwMTJxeT9cwfup9QP9LBc6gQstvabCzUOJvELnzosxiNJHeU2mrvavaNK6BGvs_lbNjODVDeetGCD48_F2ay9r8qmo-f3GPzdzcJozKgfzonSkAE5Ran9LKcQQJpVc1rDYcV2xYiJLJ6FSuvnoClkDEE1tXysxshLPs-GXOZE7rD8XUXzezuxZWUE1jXwA-EFajoat8CP6QulHGxlcn_sKIhawhGODxJPz4Pf3jgeZVLG_7HfRJgxNiKcdzQIxnkbdpuS-0Q4-oc5yntsXhFhn31Pa3vGsiPPH9f3ndL2ZZKk3xCgyImLDJuGaxXg-qEVoIG4zNWNHMUNUQ\" } Header alg \u2014 The signature algorithm which used RS256 . typ \u2014 The type which used. kid \u2014 The key identification gluu-scan-api-rs256-ssa-signature-key . Payload iat \u2014 The time the JWT was created. iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. software_id \u2014 The \"software_id\" is used for software identification. org_id \u2014 The \"org_id\" is used for organization identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . lifetime \u2014 SSA lifetime in seconds. exp \u2014 Expiration Time. myCustom1, myCustom2, ... : if you have custom attributes, they will be displayed here. Example: # Request: POST {{your-url}}/ssa Content-Type: application/json Authorization: Bearer {{your-token}} { \"org_id\": \"your-org-id\", \"description\": \"This is test description\", \"software_id\": \"gluu-scan-api\", \"software_roles\": [ \"passwurd\" ], \"grant_types\": [ \"client_credentials\" ], \"expiration\": \"1696799089\", \"one_time_use\": false, \"rotate_ssa\": false, \"lifetime\": 86400 } Response: HTTP/1.1 201 Created Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 757 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" } Get SSA # Get existing active SSA based on jti or org_id . Query Parameters # jti \u2014 Unique identifier org_id \u2014 Organization ID Response description # [ { \"ssa\": { \"jti\": \"c3eb1c16-be9b-4e96-974e-aea5e3cf95b0\", \"org_id\": 1, \"software_id\": \"gluu-scan-api\", \"software_roles\": [ \"password\" ], \"grant_types\": [ \"client_credentials\" ], \"iss\": \"https://jans.localhost\", \"exp\": 1668608852, \"iat\": 1668608851, \"description: \"test description\", \"one_time_use\": true, \"rotate_ssa\": false, \"lifetime\": 86400 }, \"iss\": \"ed4d5f74-ce41-4180-aed4-54cffa974630\", \"created_at\": 1668608851, \"expiration\": 1668608852, \"status\": \"ACTIVE\" } ] SSA jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. org_id \u2014 The \"org_id\" is used for organization identification. software_id \u2014 The \"software_id\" is used for software identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. exp \u2014 Expiration time. iat \u2014 Creation time. description \u2014 Describe SSA. one_time_use \u2014 Defined whether the SSA will be used only once or can be used multiple times. rotate_ssa \u2014 TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. lifetime \u2014 SSA lifetime in seconds. myCustom1, myCustom2, ... \u2014 if you have custom attributes, they will be displayed here. iss \u2014 The \"iss\" is related to the client that created this SSA. created_at \u2014 Creation time. expiration \u2014 Expiration time. status \u2014 SSA status ( ACTIVE , USED , EXPIRED or REVOKED ). Example: # Request: Get SSA using jti . GET {{your-url}}/ssa?jti={{your-jti}} Content-Type: application/json Authorization: Bearer {{your-token}} Get SSA using org_id . GET {{your-url}}/ssa?org_id={{your-org_id}} Content-Type: application/json Authorization: Bearer {{your-token}} Response: HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 432 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive [ { \"ssa\": { \"software_id\": \"gluu-scan-api\", \"grant_types\": [ \"client_credentials\" ], \"org_id\": 1, \"iss\": \"https://jans.localhost\", \"software_roles\": [ \"passwurd\" ], \"exp\": 1668608852, \"iat\": 1668608851, \"jti\": \"c3eb1c16-be9b-4e96-974e-aea5e3cf95b0\", \"description: \"test description\", \"one_time_use\": true, \"rotate_ssa\": false }, \"iss\": \"ed4d5f74-ce41-4180-aed4-54cffa974630\", \"created_at\": 1668608851, \"expiration\": 1668608852, \"status\": \"ACTIVE\" } ] Get JWT SSA # Get existing active SSA based on jti . Query Parameters # jti \u2014 Unique identifier Response description # Returned SSA is a JWT, containing the following structure: { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" } Header alg \u2014 The signature algorithm which used RS256 . typ \u2014 The type which used. kid \u2014 The key identification gluu-scan-api-rs256-ssa-signature-key . Payload iat \u2014 The time the JWT was created. iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. software_id \u2014 The \"software_id\" is used for software identification. org_id \u2014 The \"org_id\" is used for organization identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . exp \u2014 Expiration Time. myCustom1, myCustom2, ... : if you have custom attributes, they will be displayed here. Example: # Request: GET {{your-url}}/ssa/jwt?jti={{your-jti}} Content-Type: application/json Authorization: Bearer {{your-token}} Response: HTTP/1.1 201 Created Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 757 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" } Validate SSA # Validate existing active SSA based on jti Header Parameters # jti \u2014 Unique identifier Response description # Method returns status 200 with an empty body if the corresponding SSA exists and is active. Example: # POST {{your-url}}/ssa/validation jti: {{your-jti}} HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Keep-Alive: timeout=5, max=100 Connection: Keep-Alive <Response body is empty> Revoke SSA # Revoke existing active SSA based on jti or org_id . Query Parameters # jti \u2014 for revoke only one SSA, the specified by jti org_id \u2014 for revoke all SSA of the specified organization. Response description # Method returns status 200 with an empty body if all required SSAs were revoked correctly. Example: # Request: Revoke using jti . DELETE {{your-url}}/ssa?jti={{your-jti}} Authorization: Bearer {{your-token}} Revoke using org_id . DELETE {{your-url}}/ssa?org_id={{your-org_id}} Authorization: Bearer {{your-token}} Response: HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 0 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive <Response body is empty> SSA Custom Script # The custom script will allow us to modify the SSA process. SSA Custom Script Modify the JWT returned by the creation SSA web service. Modify the list returned by the get SSA web service. Run a process after revoking an SSA. Create method # This method is executed after having generated the jwt that the service will return. In the following example, new fields is added to the header and payload of the JWT. def create(self, jsonWebResponse, context): print \"Modify ssa response script. Modify idToken: %s\" % jsonWebResponse jsonWebResponse.getHeader().setClaim(\"custom_header_name\", \"custom_header_value\") jsonWebResponse.getClaims().setClaim(\"custom_claim_name\", \"custom_claim_value\") print \"Modify ssa response script. After modify idToken: %s\" % jsonWebResponse return True Parameters # jsonWebResponse \u2014 JWT with SSA structure using io.jans.as.model.jwt.Jwt class context \u2014 Contains, SSA global configuration class, client, execution context, etc. Get method # This method is executed after having generated the SSA list that will be returned by the service. def get(self, jsonArray, context): print \"Modify ssa response script. Modify get ssa list: %s\" % jsonArray return True Parameters # jsonArray \u2014 Contains SSA list using org.json.JSONArray class context \u2014 Contains, SSA global configuration class, client, execution context, etc. Revoke method # This method is executed after the SSA list has been revoked. def revoke(self, ssaList, context): print \"Modify ssa response script. Modify revoke ssaList: %s\" % ssaList return True Parameters # ssaList \u2014 SSA revoked list. context \u2014 Contains, SSA global configuration class, client, execution context, etc. SSA Class structure # The SSA entity contains the following fields: id type String \u2014 Unique class identifier, and is used as the jti identifier for the JWT . orgId type String \u2014 Organization ID. description type String \u2014 SSA Description. state type enum SsaState \u2014 Contains the following SSA status values ( ACTIVE , EXPIRED , REVOKED , USED ). creationDate type Date \u2014 SSA Creation date. creatorId type String \u2014 Client that created SSA. creatorType type enum CreatorType \u2014 Contains the following CreatorType values ( NONE , CLIENT , USER , AUTO ). ttl type Integer \u2014 SSA lifetime in seconds. atributes type class SsaAtributes oneTimeUse type Boolean \u2014 Whether the SSA will be single use. lifetime type Integer \u2014 SSA lifetime in seconds. rotateSsa type Boolean \u2014 TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. clientDn type String \u2014 Client's DN. customAttributes type Map<String, String> \u2014 Contain additional fields, previously configured in the SSA global configuration. softwareId type String \u2014 Is used for software identification. softwareRoles type List<String> \u2014 List of string values, fixed value [\"password\", \"notify\"] . grantTypes type List<String> \u2014 Fixed value [\"client_credentials\"] .", "title": "SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#software-statement-assertion-ssa", "text": "Janssen Server provides SSA endpoint that enables management of SSAs. The SSA is a JSON Web Token (JWT) containing client metadata and some custom attributes. Specification for SSAs has been outlined as part of Dynamic Client Registration Protocol . URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration ssa_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/ssa More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Software Statement Assertion (SSA)"}, {"location": "janssen-server/auth-server/endpoints/ssa/#disabling-the-endpoint-using-feature-flag", "text": "/ssa endpoint can be enabled or disable using SSA feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable SSA flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/ssa/#configuration-properties", "text": "SSA endpoint can be further configured using Janssen Server configuration property ssaConfiguration . When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties to update value for this property. This property take JSON configuration with parameters as described below: \"ssaConfiguration\": { \"ssaEndpoint\": \"{{your-url}}/ssa\", \"ssaCustomAttributes\": [ \"myCustomAttr1\", \"myCustomAttr2\", ... ], \"ssaSigningAlg\": \"RS512\", \"ssaExpirationInDays\": 30 } ssaEndpoint \u2014 Base endpoint for SSA. ssaCustomAttributes \u2014 List of custom attributes, which are received in the request when creating an SSA. ssaSigningAlg \u2014 Algorithm to sign the JWT that is returned after creating an SSA. ssaExpirationInDays \u2014 Expiration expressed in days, when an SSA is created and the expiration is not sent.", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/ssa/#ssa-security", "text": "To call SSA services, a token of type client_credentials must be generated with the following scopes enabled: https://jans.io/auth/ssa.admin \u2014 Allows calling all SSA services. https://jans.io/auth/ssa.portal \u2014 Allows only call Get SSA service. https://jans.io/auth/ssa.developer \u2014 Allows only call Get SSA , but you can only filter ssa that have been created by the same client.", "title": "SSA Security"}, {"location": "janssen-server/auth-server/endpoints/ssa/#create-a-new-ssa", "text": "Create SSA for the organization with expiration (optional).", "title": "Create a new SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#request-body-description", "text": "Field Detail Optional org_id The \"org_id\" is used for organization identification. false description Describe SSA false software_id The \"software_id\" is used for software identification. false software_roles List of string values, fixed value [\"password\", \"notify\"] . false grant_types Fixed value Fixed value [\"client_credentials\"] . false expiration Expiration date. (Default value: calculated based on global SSA settings) true one_time_use Defined whether the SSA will be used only once or can be used multiple times. (Default value: true) true rotate_ssa TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. (Default value: true) true lifetime SSA Lifetime in seconds true Note: You can add more custom attributes in the request, (you must have previously configured in the SSA global configuration). It should be clarified that these values are persisted in the database and are not returned in the SSA JWT. Example: { \"org_id\": \"your-org-id\", \"description\": \"your description\", ..., \"myCustomAttr1\": \"Your value custom attr 1\", \"myCustomAttr2\": \"Your value custom attr 2\" }", "title": "Request body description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#response-description", "text": "Returned SSA is a JWT, containing the following structure: { \"ssa\": \"eyJraWQiOiI1NTk3MGFkZS00M2MwLTQ4YWMtODEyZi0yZTY1MzhjMTEyN2Zfc2lnX3JzNTEyIiwidHlwIjoiand0IiwiYWxnIjoiUlM1MTIifQ.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoxLCJpc3MiOiJodHRwczovL2phbnMubG9jYWxob3N0Iiwic29mdHdhcmVfcm9sZXMiOlsicGFzc3d1cmQiXSwiZXhwIjoxNjY4NjA5MDA1LCJpYXQiOjE2Njg2NDE5NjcsImp0aSI6ImU4OWVjYTQxLTM0ODUtNDUxNi1hMTYyLWZiODYyNjJhYmFjMyJ9.jRgh8_aiwMTJxeT9cwfup9QP9LBc6gQstvabCzUOJvELnzosxiNJHeU2mrvavaNK6BGvs_lbNjODVDeetGCD48_F2ay9r8qmo-f3GPzdzcJozKgfzonSkAE5Ran9LKcQQJpVc1rDYcV2xYiJLJ6FSuvnoClkDEE1tXysxshLPs-GXOZE7rD8XUXzezuxZWUE1jXwA-EFajoat8CP6QulHGxlcn_sKIhawhGODxJPz4Pf3jgeZVLG_7HfRJgxNiKcdzQIxnkbdpuS-0Q4-oc5yntsXhFhn31Pa3vGsiPPH9f3ndL2ZZKk3xCgyImLDJuGaxXg-qEVoIG4zNWNHMUNUQ\" } Header alg \u2014 The signature algorithm which used RS256 . typ \u2014 The type which used. kid \u2014 The key identification gluu-scan-api-rs256-ssa-signature-key . Payload iat \u2014 The time the JWT was created. iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. software_id \u2014 The \"software_id\" is used for software identification. org_id \u2014 The \"org_id\" is used for organization identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . lifetime \u2014 SSA lifetime in seconds. exp \u2014 Expiration Time. myCustom1, myCustom2, ... : if you have custom attributes, they will be displayed here.", "title": "Response description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#example", "text": "Request: POST {{your-url}}/ssa Content-Type: application/json Authorization: Bearer {{your-token}} { \"org_id\": \"your-org-id\", \"description\": \"This is test description\", \"software_id\": \"gluu-scan-api\", \"software_roles\": [ \"passwurd\" ], \"grant_types\": [ \"client_credentials\" ], \"expiration\": \"1696799089\", \"one_time_use\": false, \"rotate_ssa\": false, \"lifetime\": 86400 } Response: HTTP/1.1 201 Created Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 757 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" }", "title": "Example:"}, {"location": "janssen-server/auth-server/endpoints/ssa/#get-ssa", "text": "Get existing active SSA based on jti or org_id .", "title": "Get SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#query-parameters", "text": "jti \u2014 Unique identifier org_id \u2014 Organization ID", "title": "Query Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#response-description_1", "text": "[ { \"ssa\": { \"jti\": \"c3eb1c16-be9b-4e96-974e-aea5e3cf95b0\", \"org_id\": 1, \"software_id\": \"gluu-scan-api\", \"software_roles\": [ \"password\" ], \"grant_types\": [ \"client_credentials\" ], \"iss\": \"https://jans.localhost\", \"exp\": 1668608852, \"iat\": 1668608851, \"description: \"test description\", \"one_time_use\": true, \"rotate_ssa\": false, \"lifetime\": 86400 }, \"iss\": \"ed4d5f74-ce41-4180-aed4-54cffa974630\", \"created_at\": 1668608851, \"expiration\": 1668608852, \"status\": \"ACTIVE\" } ] SSA jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. org_id \u2014 The \"org_id\" is used for organization identification. software_id \u2014 The \"software_id\" is used for software identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. exp \u2014 Expiration time. iat \u2014 Creation time. description \u2014 Describe SSA. one_time_use \u2014 Defined whether the SSA will be used only once or can be used multiple times. rotate_ssa \u2014 TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. lifetime \u2014 SSA lifetime in seconds. myCustom1, myCustom2, ... \u2014 if you have custom attributes, they will be displayed here. iss \u2014 The \"iss\" is related to the client that created this SSA. created_at \u2014 Creation time. expiration \u2014 Expiration time. status \u2014 SSA status ( ACTIVE , USED , EXPIRED or REVOKED ).", "title": "Response description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#example_1", "text": "Request: Get SSA using jti . GET {{your-url}}/ssa?jti={{your-jti}} Content-Type: application/json Authorization: Bearer {{your-token}} Get SSA using org_id . GET {{your-url}}/ssa?org_id={{your-org_id}} Content-Type: application/json Authorization: Bearer {{your-token}} Response: HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 432 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive [ { \"ssa\": { \"software_id\": \"gluu-scan-api\", \"grant_types\": [ \"client_credentials\" ], \"org_id\": 1, \"iss\": \"https://jans.localhost\", \"software_roles\": [ \"passwurd\" ], \"exp\": 1668608852, \"iat\": 1668608851, \"jti\": \"c3eb1c16-be9b-4e96-974e-aea5e3cf95b0\", \"description: \"test description\", \"one_time_use\": true, \"rotate_ssa\": false }, \"iss\": \"ed4d5f74-ce41-4180-aed4-54cffa974630\", \"created_at\": 1668608851, \"expiration\": 1668608852, \"status\": \"ACTIVE\" } ]", "title": "Example:"}, {"location": "janssen-server/auth-server/endpoints/ssa/#get-jwt-ssa", "text": "Get existing active SSA based on jti .", "title": "Get JWT SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#query-parameters_1", "text": "jti \u2014 Unique identifier", "title": "Query Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#response-description_2", "text": "Returned SSA is a JWT, containing the following structure: { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" } Header alg \u2014 The signature algorithm which used RS256 . typ \u2014 The type which used. kid \u2014 The key identification gluu-scan-api-rs256-ssa-signature-key . Payload iat \u2014 The time the JWT was created. iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. software_id \u2014 The \"software_id\" is used for software identification. org_id \u2014 The \"org_id\" is used for organization identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . exp \u2014 Expiration Time. myCustom1, myCustom2, ... : if you have custom attributes, they will be displayed here.", "title": "Response description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#example_2", "text": "Request: GET {{your-url}}/ssa/jwt?jti={{your-jti}} Content-Type: application/json Authorization: Bearer {{your-token}} Response: HTTP/1.1 201 Created Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 757 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" }", "title": "Example:"}, {"location": "janssen-server/auth-server/endpoints/ssa/#validate-ssa", "text": "Validate existing active SSA based on jti", "title": "Validate SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#header-parameters", "text": "jti \u2014 Unique identifier", "title": "Header Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#response-description_3", "text": "Method returns status 200 with an empty body if the corresponding SSA exists and is active.", "title": "Response description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#example_3", "text": "POST {{your-url}}/ssa/validation jti: {{your-jti}} HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Keep-Alive: timeout=5, max=100 Connection: Keep-Alive <Response body is empty>", "title": "Example:"}, {"location": "janssen-server/auth-server/endpoints/ssa/#revoke-ssa", "text": "Revoke existing active SSA based on jti or org_id .", "title": "Revoke SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#query-parameters_2", "text": "jti \u2014 for revoke only one SSA, the specified by jti org_id \u2014 for revoke all SSA of the specified organization.", "title": "Query Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#response-description_4", "text": "Method returns status 200 with an empty body if all required SSAs were revoked correctly.", "title": "Response description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#example_4", "text": "Request: Revoke using jti . DELETE {{your-url}}/ssa?jti={{your-jti}} Authorization: Bearer {{your-token}} Revoke using org_id . DELETE {{your-url}}/ssa?org_id={{your-org_id}} Authorization: Bearer {{your-token}} Response: HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 0 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive <Response body is empty>", "title": "Example:"}, {"location": "janssen-server/auth-server/endpoints/ssa/#ssa-custom-script", "text": "The custom script will allow us to modify the SSA process. SSA Custom Script Modify the JWT returned by the creation SSA web service. Modify the list returned by the get SSA web service. Run a process after revoking an SSA.", "title": "SSA Custom Script"}, {"location": "janssen-server/auth-server/endpoints/ssa/#create-method", "text": "This method is executed after having generated the jwt that the service will return. In the following example, new fields is added to the header and payload of the JWT. def create(self, jsonWebResponse, context): print \"Modify ssa response script. Modify idToken: %s\" % jsonWebResponse jsonWebResponse.getHeader().setClaim(\"custom_header_name\", \"custom_header_value\") jsonWebResponse.getClaims().setClaim(\"custom_claim_name\", \"custom_claim_value\") print \"Modify ssa response script. After modify idToken: %s\" % jsonWebResponse return True", "title": "Create method"}, {"location": "janssen-server/auth-server/endpoints/ssa/#parameters", "text": "jsonWebResponse \u2014 JWT with SSA structure using io.jans.as.model.jwt.Jwt class context \u2014 Contains, SSA global configuration class, client, execution context, etc.", "title": "Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#get-method", "text": "This method is executed after having generated the SSA list that will be returned by the service. def get(self, jsonArray, context): print \"Modify ssa response script. Modify get ssa list: %s\" % jsonArray return True", "title": "Get method"}, {"location": "janssen-server/auth-server/endpoints/ssa/#parameters_1", "text": "jsonArray \u2014 Contains SSA list using org.json.JSONArray class context \u2014 Contains, SSA global configuration class, client, execution context, etc.", "title": "Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#revoke-method", "text": "This method is executed after the SSA list has been revoked. def revoke(self, ssaList, context): print \"Modify ssa response script. Modify revoke ssaList: %s\" % ssaList return True", "title": "Revoke method"}, {"location": "janssen-server/auth-server/endpoints/ssa/#parameters_2", "text": "ssaList \u2014 SSA revoked list. context \u2014 Contains, SSA global configuration class, client, execution context, etc.", "title": "Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#ssa-class-structure", "text": "The SSA entity contains the following fields: id type String \u2014 Unique class identifier, and is used as the jti identifier for the JWT . orgId type String \u2014 Organization ID. description type String \u2014 SSA Description. state type enum SsaState \u2014 Contains the following SSA status values ( ACTIVE , EXPIRED , REVOKED , USED ). creationDate type Date \u2014 SSA Creation date. creatorId type String \u2014 Client that created SSA. creatorType type enum CreatorType \u2014 Contains the following CreatorType values ( NONE , CLIENT , USER , AUTO ). ttl type Integer \u2014 SSA lifetime in seconds. atributes type class SsaAtributes oneTimeUse type Boolean \u2014 Whether the SSA will be single use. lifetime type Integer \u2014 SSA lifetime in seconds. rotateSsa type Boolean \u2014 TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. clientDn type String \u2014 Client's DN. customAttributes type Map<String, String> \u2014 Contain additional fields, previously configured in the SSA global configuration. softwareId type String \u2014 Is used for software identification. softwareRoles type List<String> \u2014 List of string values, fixed value [\"password\", \"notify\"] . grantTypes type List<String> \u2014 Fixed value [\"client_credentials\"] .", "title": "SSA Class structure"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/", "tags": ["administration", "auth-server", "token-revocation", "endpoint"], "text": "Overview # Janssen Server supports token revocation endpoint enables a client to notify the server that previously obtained refresh or access token is no longer needed, allowing the server to clean up security credentials. Implementation conforms with token revocation specification . Since a token is part of a grant, when the token is invalidated, all other token within the same grant are also revoked. i.e when a refresh token related to a grant is invalidated, all access tokens from the same grant are also invalidated and vice-versa. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://<jans-server-host>/jans-auth/.well-known/openid-configuration revocation_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://jans-dynamic-mysql/jans-auth/restv1/revoke More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # Token revocation endpoint can be enabled or disable using REVOKE_TOKEN feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable REVOKE_TOKEN flag as required. Configuration Properties # Token revocation endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . mtlstokenrevocationendpoint tokenRevocationEndpoint allowRevokeForOtherClients Revoke all tokens by client_id # To remove all tokens for given client_id it's required: - set allowAllValueForRevokeEndpoint AS configuration property to true - pass in request parameter token_type_hint=all client is identified by Client Authentication performed by AS to grant access to /revoke endpoint. Revoke tokens of other clients # By default Revoke Endpoint allows revoke only own client's tokens. However it is possible to allow revoking of any token (which is issued with other client). For this it is required: - set global AS configuration property allowRevokeForOtherClients to true - add revoke_any_token scope to client which performs revoke call Revoke Interception Script # Endpoint can provide custom behavior via implementing Revoke Token interception script .", "title": "Token Revocation"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#overview", "text": "Janssen Server supports token revocation endpoint enables a client to notify the server that previously obtained refresh or access token is no longer needed, allowing the server to clean up security credentials. Implementation conforms with token revocation specification . Since a token is part of a grant, when the token is invalidated, all other token within the same grant are also revoked. i.e when a refresh token related to a grant is invalidated, all access tokens from the same grant are also invalidated and vice-versa. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://<jans-server-host>/jans-auth/.well-known/openid-configuration revocation_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://jans-dynamic-mysql/jans-auth/restv1/revoke More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#disabling-the-endpoint-using-feature-flag", "text": "Token revocation endpoint can be enabled or disable using REVOKE_TOKEN feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable REVOKE_TOKEN flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#configuration-properties", "text": "Token revocation endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . mtlstokenrevocationendpoint tokenRevocationEndpoint allowRevokeForOtherClients", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#revoke-all-tokens-by-client_id", "text": "To remove all tokens for given client_id it's required: - set allowAllValueForRevokeEndpoint AS configuration property to true - pass in request parameter token_type_hint=all client is identified by Client Authentication performed by AS to grant access to /revoke endpoint.", "title": "Revoke all tokens by client_id"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#revoke-tokens-of-other-clients", "text": "By default Revoke Endpoint allows revoke only own client's tokens. However it is possible to allow revoking of any token (which is issued with other client). For this it is required: - set global AS configuration property allowRevokeForOtherClients to true - add revoke_any_token scope to client which performs revoke call", "title": "Revoke tokens of other clients"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#revoke-interception-script", "text": "Endpoint can provide custom behavior via implementing Revoke Token interception script .", "title": "Revoke Interception Script"}, {"location": "janssen-server/auth-server/endpoints/token/", "tags": ["administration", "auth-server", "token", "endpoint"], "text": "Overview # Token endpoint is an OAuth2 protected endpoint that is used to grant tokens to client in response to valid request. Token endpoint is defined in the OAuth 2.0 framework , OpenID Connect specification and other specifications relevant to them. Tokens granted by this endpoint depends on grant type and scopes that are specified in the token request. The token endpoint is used with every authorization grant type except for the implicit grant type (since an access token is issued directly). Based on request, this endpoint can grant following types of tokens: Access Token Refresh Token ID Token URL to access token endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration token_endpoint claim in the response specifies the URL for userinfo endpoint. By default, userinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/token In response to a valid request, the token endpoint returns token/s in JSON format similar to below. This is just a sample response. Actual response can greatly vary in its contents based on request: HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store Pragma: no-cache { \"access_token\": \"SlAV32hkKG\", \"token_type\": \"Bearer\", \"refresh_token\": \"8xLOxBtZp8\", \"expires_in\": 3600, \"id_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5 NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4 XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg\" } More information about request and response of the token endpoint can be found in the OpenAPI specification of jans-auth-server module . Configuration Properties # Token endpoint and tokens issued by token endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . tokenEndpoint tokenEndpointAuthMethodsSupported tokenEndpointAuthSigningAlgValuesSupported accessTokenLifetime checkUserPresenceOnRefreshToken defaultSignatureAlgorithm forceOfflineAccessScopeToEnableRefreshToken grantTypesSupported accessTokenSigningAlgValuesSupported idTokenEncryptionAlgValuesSupported idTokenEncryptionEncValuesSupported idTokenFilterClaimsBasedOnAccessToken idTokenLifetime idTokenSigningAlgValuesSupported accessTokenSigningAlgValuesSupported legacyIdTokenClaims mtlsTokenEndpoint openidScopeBackwardCompatibility persistIdToken persistRefreshToken refreshTokenExtendLifetimeOnRotation refreshTokenLifetime responseTypesSupported skipRefreshTokenDuringRefreshing refreshTokenLifetime Client Authentication # Janssen Server Token Endpoint requires confidential clients to authenticate using one of the supported client authentication method listed below: client_secret_basic client_secret_post client_secret_jwt private_key_jwt Refer to Client Authentication section of OpenID Connect core specification for more details on these authentication methods. AS provides ability to customer Client Authentication behavior via Client Authentication custom script Client can specify the default authentication method. To set default authentication method using Janssen Text-based UI(TUI) , navigate via Auth Server -> Clients -> Add Client -> Basic -> Authn Method Token Endpoint . Supported Grant Types # Token endpoint supports below mentioned grant types. Authorization Code Implicit Refresh Token Client Credentials Password Token Exchange Transaction Tokens Device Grant CIBA Client can configure all the possible grant types it can request from token endpoint during client configuration. To select the available grant types using Janssen Text-based UI(TUI) , navigate via Auth Server -> Clients -> Add Client / search client -> Basic -> Grant . Interception Scripts # Token endpoint response can be further customized using interception scripts . Following interception scripts are relevant to token endpoint: Update Token Client can configure a particular script to be executed using client configuration. To update configuration using Janssen Text-based UI(TUI) navigate via Auth Server -> Clients -> Add Client / search -> Client Scripts", "title": "Token"}, {"location": "janssen-server/auth-server/endpoints/token/#overview", "text": "Token endpoint is an OAuth2 protected endpoint that is used to grant tokens to client in response to valid request. Token endpoint is defined in the OAuth 2.0 framework , OpenID Connect specification and other specifications relevant to them. Tokens granted by this endpoint depends on grant type and scopes that are specified in the token request. The token endpoint is used with every authorization grant type except for the implicit grant type (since an access token is issued directly). Based on request, this endpoint can grant following types of tokens: Access Token Refresh Token ID Token URL to access token endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration token_endpoint claim in the response specifies the URL for userinfo endpoint. By default, userinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/token In response to a valid request, the token endpoint returns token/s in JSON format similar to below. This is just a sample response. Actual response can greatly vary in its contents based on request: HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store Pragma: no-cache { \"access_token\": \"SlAV32hkKG\", \"token_type\": \"Bearer\", \"refresh_token\": \"8xLOxBtZp8\", \"expires_in\": 3600, \"id_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5 NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4 XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg\" } More information about request and response of the token endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/token/#configuration-properties", "text": "Token endpoint and tokens issued by token endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . tokenEndpoint tokenEndpointAuthMethodsSupported tokenEndpointAuthSigningAlgValuesSupported accessTokenLifetime checkUserPresenceOnRefreshToken defaultSignatureAlgorithm forceOfflineAccessScopeToEnableRefreshToken grantTypesSupported accessTokenSigningAlgValuesSupported idTokenEncryptionAlgValuesSupported idTokenEncryptionEncValuesSupported idTokenFilterClaimsBasedOnAccessToken idTokenLifetime idTokenSigningAlgValuesSupported accessTokenSigningAlgValuesSupported legacyIdTokenClaims mtlsTokenEndpoint openidScopeBackwardCompatibility persistIdToken persistRefreshToken refreshTokenExtendLifetimeOnRotation refreshTokenLifetime responseTypesSupported skipRefreshTokenDuringRefreshing refreshTokenLifetime", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/token/#client-authentication", "text": "Janssen Server Token Endpoint requires confidential clients to authenticate using one of the supported client authentication method listed below: client_secret_basic client_secret_post client_secret_jwt private_key_jwt Refer to Client Authentication section of OpenID Connect core specification for more details on these authentication methods. AS provides ability to customer Client Authentication behavior via Client Authentication custom script Client can specify the default authentication method. To set default authentication method using Janssen Text-based UI(TUI) , navigate via Auth Server -> Clients -> Add Client -> Basic -> Authn Method Token Endpoint .", "title": "Client Authentication"}, {"location": "janssen-server/auth-server/endpoints/token/#supported-grant-types", "text": "Token endpoint supports below mentioned grant types. Authorization Code Implicit Refresh Token Client Credentials Password Token Exchange Transaction Tokens Device Grant CIBA Client can configure all the possible grant types it can request from token endpoint during client configuration. To select the available grant types using Janssen Text-based UI(TUI) , navigate via Auth Server -> Clients -> Add Client / search client -> Basic -> Grant .", "title": "Supported Grant Types"}, {"location": "janssen-server/auth-server/endpoints/token/#interception-scripts", "text": "Token endpoint response can be further customized using interception scripts . Following interception scripts are relevant to token endpoint: Update Token Client can configure a particular script to be executed using client configuration. To update configuration using Janssen Text-based UI(TUI) navigate via Auth Server -> Clients -> Add Client / search -> Client Scripts", "title": "Interception Scripts"}, {"location": "janssen-server/auth-server/endpoints/userinfo/", "tags": ["administration", "auth-server", "userinfo", "endpoint"], "text": "Overview # Userinfo endpoint is an OAuth2 protected endpoint that is used to retrieve claims about an authenticated end-user. Userinfo endpoint is defined in the OpenID Connect specification . URL to access userinfo endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration userinfo_endpoint claim in the response specifies the URL for userinfo endpoint. By default, userinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/userinfo In response to a valid request, the userinfo endpoint returns user information in JSON format similar to below: HTTP/1.1 200 OK Content-Type: application/json { \"sub\": \"3482897610054\", \"jti\": \"sdu28g9c761g0y0g5\", \"client_id\": \"db6daf8c-ab1b-4010-9fb0\", \"name\": \"Chad Wick\", \"given_name\": \"Chad\", \"family_name\": \"Wick\", \"preferred_username\": \"c.wick\", \"email\": \"cwick@jans.com\", \"picture\": \"http://mysite.com/mypic.jpg\" } User Info response should contain: sub , jti and client_id claims. Since userinfo endpoint is an OAuth2 protected resource, a valid access token with appropriate scope is required to access the endpoint. More information about request and response of the userinfo endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # userinfo endpoint can be enabled or disable using USERINFO feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable USERINFO flag as required. Configuration Properties # Userinfo endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . mtlsUserInfoEndpoint userInfoEncryptionAlgValuesSupported userInfoEncryptionEncValuesSupported userInfoEndpoint userInfoSigningAlgValuesSupported Using Scopes To Control Claim Release # Standard Scopes # In context of OpenID Connect specification, claim information released by userinfo endpoint can be controlled using scopes. Janssen Server supports all standard scopes and releases corresponding claims as per OpenID Connect specification. Administrator can customise standard scopes and define claims to be linked to each standard scope. When using Janssen Text-based UI(TUI) to configure the scopes, navigate via Auth Server -> Scopes -> Add Scopes -> Scope Type as OpenID ->search for a standard scope like address Dynamic Scopes # In addition to standard scopes, Janssen server allows defining custom scopes which can be associated to user-defined list of claims. This allows administrators to create custom groupings of claims. When using Janssen Text-based UI(TUI) , navigate via Auth Server -> Scopes -> Add Scopes -> Scope Type as Dynamic Interception Scripts # Response from userinfo can be further customized using dynamic scope interception script. Administrator can attach a dynamic scope script to a dynamic scope using Janssen Text-based UI(TUI) . Navigate to Auth Server -> Scopes -> Add Scopes -> Scope Type as Dynamic -> Dynamic Scope Script Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Userinfo"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#overview", "text": "Userinfo endpoint is an OAuth2 protected endpoint that is used to retrieve claims about an authenticated end-user. Userinfo endpoint is defined in the OpenID Connect specification . URL to access userinfo endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration userinfo_endpoint claim in the response specifies the URL for userinfo endpoint. By default, userinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/userinfo In response to a valid request, the userinfo endpoint returns user information in JSON format similar to below: HTTP/1.1 200 OK Content-Type: application/json { \"sub\": \"3482897610054\", \"jti\": \"sdu28g9c761g0y0g5\", \"client_id\": \"db6daf8c-ab1b-4010-9fb0\", \"name\": \"Chad Wick\", \"given_name\": \"Chad\", \"family_name\": \"Wick\", \"preferred_username\": \"c.wick\", \"email\": \"cwick@jans.com\", \"picture\": \"http://mysite.com/mypic.jpg\" } User Info response should contain: sub , jti and client_id claims. Since userinfo endpoint is an OAuth2 protected resource, a valid access token with appropriate scope is required to access the endpoint. More information about request and response of the userinfo endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#disabling-the-endpoint-using-feature-flag", "text": "userinfo endpoint can be enabled or disable using USERINFO feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable USERINFO flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#configuration-properties", "text": "Userinfo endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . mtlsUserInfoEndpoint userInfoEncryptionAlgValuesSupported userInfoEncryptionEncValuesSupported userInfoEndpoint userInfoSigningAlgValuesSupported", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#using-scopes-to-control-claim-release", "text": "", "title": "Using Scopes To Control Claim Release"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#standard-scopes", "text": "In context of OpenID Connect specification, claim information released by userinfo endpoint can be controlled using scopes. Janssen Server supports all standard scopes and releases corresponding claims as per OpenID Connect specification. Administrator can customise standard scopes and define claims to be linked to each standard scope. When using Janssen Text-based UI(TUI) to configure the scopes, navigate via Auth Server -> Scopes -> Add Scopes -> Scope Type as OpenID ->search for a standard scope like address", "title": "Standard Scopes"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#dynamic-scopes", "text": "In addition to standard scopes, Janssen server allows defining custom scopes which can be associated to user-defined list of claims. This allows administrators to create custom groupings of claims. When using Janssen Text-based UI(TUI) , navigate via Auth Server -> Scopes -> Add Scopes -> Scope Type as Dynamic", "title": "Dynamic Scopes"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#interception-scripts", "text": "Response from userinfo can be further customized using dynamic scope interception script. Administrator can attach a dynamic scope script to a dynamic scope using Janssen Text-based UI(TUI) . Navigate to Auth Server -> Scopes -> Add Scopes -> Scope Type as Dynamic -> Dynamic Scope Script", "title": "Interception Scripts"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/international/client-config/", "tags": ["administration", "auth-server", "i18n"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Client Configuration"}, {"location": "janssen-server/auth-server/international/client-config/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/international/client-config/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/international/client-config/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/international/scope-descriptions/", "tags": ["administration", "auth-server", "i18n"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Scope Descriptions"}, {"location": "janssen-server/auth-server/international/scope-descriptions/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/international/scope-descriptions/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/international/scope-descriptions/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/international/web-pages/", "tags": ["administration", "auth-server", "i18n"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Web Pages"}, {"location": "janssen-server/auth-server/international/web-pages/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/international/web-pages/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/international/web-pages/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/logging/audit-logs/", "tags": ["administration", "auth-server", "logging"], "text": "Audit Logs # Audit logs are located in jans-auth_audit.log log file. All jans-auth-server log files are located in /opt/jans/jetty/jans-auth/logs/ . Audit is disabled by default on AS and can be enabled via enabledOAuthAuditLogging AS configuration property. Audit logs are logged to file when enabled, however if JMS configuration is specified it will be logged to JMS as well. JMS Configuration must be set inside AS global configuration Name Description jmsBrokerURISet JMS Broker URI Set jmsUserName JMS UserName jmsPassword JMS Password. Audit events: - CLIENT_REGISTRATION - CLIENT_UPDATE - CLIENT_READ - CLIENT_DELETE - USER_AUTHORIZATION - BACKCHANNEL_AUTHENTICATION - BACKCHANNEL_DEVICE_REGISTRATION - USER_INFO - TOKEN_REQUEST - TOKEN_VALIDATE - TOKEN_REVOCATION - SESSION_UNAUTHENTICATED - SESSION_AUTHENTICATED - SESSION_DESTROYED - DEVICE_CODE_AUTHORIZATION - SSA_CREATE - SSA_READ Enable/Disable Audit Logs on Jans TUI # Using Jans TUI we can easily Enable or Disable Audit Logs. Go to jans tui select Auth Server tab then Properties tab. Now set the value of enabledOAuthAuditLogging pressing Enter button on your keyboard. Save it and let's see below image Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Audit Logs"}, {"location": "janssen-server/auth-server/logging/audit-logs/#audit-logs", "text": "Audit logs are located in jans-auth_audit.log log file. All jans-auth-server log files are located in /opt/jans/jetty/jans-auth/logs/ . Audit is disabled by default on AS and can be enabled via enabledOAuthAuditLogging AS configuration property. Audit logs are logged to file when enabled, however if JMS configuration is specified it will be logged to JMS as well. JMS Configuration must be set inside AS global configuration Name Description jmsBrokerURISet JMS Broker URI Set jmsUserName JMS UserName jmsPassword JMS Password. Audit events: - CLIENT_REGISTRATION - CLIENT_UPDATE - CLIENT_READ - CLIENT_DELETE - USER_AUTHORIZATION - BACKCHANNEL_AUTHENTICATION - BACKCHANNEL_DEVICE_REGISTRATION - USER_INFO - TOKEN_REQUEST - TOKEN_VALIDATE - TOKEN_REVOCATION - SESSION_UNAUTHENTICATED - SESSION_AUTHENTICATED - SESSION_DESTROYED - DEVICE_CODE_AUTHORIZATION - SSA_CREATE - SSA_READ", "title": "Audit Logs"}, {"location": "janssen-server/auth-server/logging/audit-logs/#enabledisable-audit-logs-on-jans-tui", "text": "Using Jans TUI we can easily Enable or Disable Audit Logs. Go to jans tui select Auth Server tab then Properties tab. Now set the value of enabledOAuthAuditLogging pressing Enter button on your keyboard. Save it and let's see below image", "title": "Enable/Disable Audit Logs on Jans TUI"}, {"location": "janssen-server/auth-server/logging/audit-logs/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/logging/audit-logs/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/logging/custom-logs/", "tags": ["administration", "auth-server", "logging", "custom-logs"], "text": "Customize logs # Sometimes it can be useful to customize logging behavior or override AS loggers. It is possible to fully override AS logging configuration by specifying own log4j2.xml file in externalLoggerConfiguration AS configuration property. It must point to valid log4j2.xml file. Note: invalid external log4j2.xml can lead to AS start up issues and no logs in standard log files or otherwise in other log files if such are defined by log4j2.xml . Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Custom Logs"}, {"location": "janssen-server/auth-server/logging/custom-logs/#customize-logs", "text": "Sometimes it can be useful to customize logging behavior or override AS loggers. It is possible to fully override AS logging configuration by specifying own log4j2.xml file in externalLoggerConfiguration AS configuration property. It must point to valid log4j2.xml file. Note: invalid external log4j2.xml can lead to AS start up issues and no logs in standard log files or otherwise in other log files if such are defined by log4j2.xml .", "title": "Customize logs"}, {"location": "janssen-server/auth-server/logging/custom-logs/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/logging/custom-logs/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/logging/log-levels/", "tags": ["administration", "auth-server", "logging-levels"], "text": "Log Levels # Log level for AS can be set in loggingLevel AS configuration property. AS under the hood is using log4j2 and slf4j . Thus logging levels in loggingLevel stick to log4j2 and are following: Log Level Description OFF No events will be logged. FATAL A fatal event that will prevent the application from continuing. ERROR An error in the application, possibly recoverable. WARN An event that might possible lead to an error. INFO An event for informational purposes. DEBUG A general debugging event. TRACE A fine-grained debug message, typically capturing the flow through the application. ALL All events should be logged. Select Log Levels on TUI # Go to Jans TUI jans tui . Select Auth Server tab then select Logging tab after that select Auth Server Log Level finally save logging and exit from TUI. Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Log Levels"}, {"location": "janssen-server/auth-server/logging/log-levels/#log-levels", "text": "Log level for AS can be set in loggingLevel AS configuration property. AS under the hood is using log4j2 and slf4j . Thus logging levels in loggingLevel stick to log4j2 and are following: Log Level Description OFF No events will be logged. FATAL A fatal event that will prevent the application from continuing. ERROR An error in the application, possibly recoverable. WARN An event that might possible lead to an error. INFO An event for informational purposes. DEBUG A general debugging event. TRACE A fine-grained debug message, typically capturing the flow through the application. ALL All events should be logged.", "title": "Log Levels"}, {"location": "janssen-server/auth-server/logging/log-levels/#select-log-levels-on-tui", "text": "Go to Jans TUI jans tui . Select Auth Server tab then select Logging tab after that select Auth Server Log Level finally save logging and exit from TUI.", "title": "Select Log Levels on TUI"}, {"location": "janssen-server/auth-server/logging/log-levels/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/logging/log-levels/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/logging/log4j2/", "tags": ["administration", "auth-server", "logging"], "text": "log4j2 # AS under the hood is using log4j2 and slf4j . AS is configured by log4j2.xml Main structure of which defines standard logs and which can be overwritten by specifying own custom log4j2.xml . Please reference log4j configuration for available logging options. Sample <?xml version=\"1.0\" encoding=\"UTF-8\"?> <Configuration packages= \"io.jans.log\" > <Appenders> <Console name= \"STDOUT\" target= \"SYSTEM_OUT\" > <PatternLayout pattern= \"%d %-5p [%t] [%C{6}] (%F:%L) - %m%n\" /> </Console> <RollingFile name= \"JANS_AUTH_HTTP_REQUEST_RESPONSE_FILE\" fileName= \"${sys:log.base}/logs/http_request_response.log\" filePattern= \"${sys:log.base}/logs/http_request_response-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"FILE\" fileName= \"${sys:log.base}/logs/jans-auth.log\" filePattern= \"${sys:log.base}/logs/jans-auth-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_PERSISTENCE_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_persistence.log\" filePattern= \"${sys:log.base}/logs/jans-auth_persistence-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_persistence_duration.log\" filePattern= \"${sys:log.base}/logs/jans-auth_persistence_duration-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_SCRIPT_LOG_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_script.log\" filePattern= \"${sys:log.base}/logs/jans-auth_script-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_AUDIT_LOG_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_audit.log\" filePattern= \"${sys:log.base}/logs/jans-auth_audit-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%macAddr] [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> </Appenders> <Loggers> <!-- ############### Gluu ################# --> <Logger name= \"io.jans\" level= \"${log4j.default.log.level}\" /> <!-- EMB-6, JMS activation throws an error due to deployment ordering, but as there is a timeout and retry the tests pass. Hide the error message --> <Logger name= \"jboss.resource.adapter.jms.inflow.JmsActivation\" level= \"error\" /> <Logger name= \"com.ocpsoft\" level= \"info\" /> <!-- ############### Hibernate logging ################# --> <Logger name= \"org.hibernate\" level= \"error\" /> <Logger name= \"io.jans.as.server.audit.debug\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_HTTP_REQUEST_RESPONSE_FILE\" /> </Logger> <Logger name= \"io.jans.orm\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_FILE\" /> </Logger> <logger name= \"com.couchbase.client\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_FILE\" /> </logger> <Logger name= \"io.jans.orm.couchbase.operation.watch\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" /> </Logger> <Logger name= \"io.jans.orm.watch\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" /> </Logger> <Logger name= \"io.jans.service.PythonService\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.service.custom.script\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.as.server.service.custom\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.agama.engine.script.LogUtils\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.as.server.audit.ApplicationAuditLogger\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_AUDIT_LOG_FILE\" /> </Logger> <Root level= \"info\" > <AppenderRef ref= \"FILE\" /> <AppenderRef ref= \"STDOUT\" /> </Root> </Loggers> </Configuration> Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "log4j2 Configuration"}, {"location": "janssen-server/auth-server/logging/log4j2/#log4j2", "text": "AS under the hood is using log4j2 and slf4j . AS is configured by log4j2.xml Main structure of which defines standard logs and which can be overwritten by specifying own custom log4j2.xml . Please reference log4j configuration for available logging options. Sample <?xml version=\"1.0\" encoding=\"UTF-8\"?> <Configuration packages= \"io.jans.log\" > <Appenders> <Console name= \"STDOUT\" target= \"SYSTEM_OUT\" > <PatternLayout pattern= \"%d %-5p [%t] [%C{6}] (%F:%L) - %m%n\" /> </Console> <RollingFile name= \"JANS_AUTH_HTTP_REQUEST_RESPONSE_FILE\" fileName= \"${sys:log.base}/logs/http_request_response.log\" filePattern= \"${sys:log.base}/logs/http_request_response-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"FILE\" fileName= \"${sys:log.base}/logs/jans-auth.log\" filePattern= \"${sys:log.base}/logs/jans-auth-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_PERSISTENCE_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_persistence.log\" filePattern= \"${sys:log.base}/logs/jans-auth_persistence-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_persistence_duration.log\" filePattern= \"${sys:log.base}/logs/jans-auth_persistence_duration-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_SCRIPT_LOG_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_script.log\" filePattern= \"${sys:log.base}/logs/jans-auth_script-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_AUDIT_LOG_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_audit.log\" filePattern= \"${sys:log.base}/logs/jans-auth_audit-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%macAddr] [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> </Appenders> <Loggers> <!-- ############### Gluu ################# --> <Logger name= \"io.jans\" level= \"${log4j.default.log.level}\" /> <!-- EMB-6, JMS activation throws an error due to deployment ordering, but as there is a timeout and retry the tests pass. Hide the error message --> <Logger name= \"jboss.resource.adapter.jms.inflow.JmsActivation\" level= \"error\" /> <Logger name= \"com.ocpsoft\" level= \"info\" /> <!-- ############### Hibernate logging ################# --> <Logger name= \"org.hibernate\" level= \"error\" /> <Logger name= \"io.jans.as.server.audit.debug\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_HTTP_REQUEST_RESPONSE_FILE\" /> </Logger> <Logger name= \"io.jans.orm\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_FILE\" /> </Logger> <logger name= \"com.couchbase.client\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_FILE\" /> </logger> <Logger name= \"io.jans.orm.couchbase.operation.watch\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" /> </Logger> <Logger name= \"io.jans.orm.watch\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" /> </Logger> <Logger name= \"io.jans.service.PythonService\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.service.custom.script\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.as.server.service.custom\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.agama.engine.script.LogUtils\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.as.server.audit.ApplicationAuditLogger\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_AUDIT_LOG_FILE\" /> </Logger> <Root level= \"info\" > <AppenderRef ref= \"FILE\" /> <AppenderRef ref= \"STDOUT\" /> </Root> </Loggers> </Configuration>", "title": "log4j2"}, {"location": "janssen-server/auth-server/logging/log4j2/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/logging/log4j2/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/logging/standard-logs/", "tags": ["administration", "auth-server", "logging"], "text": "Standard Logs # All jans-auth-server log files are located in /opt/jans/jetty/jans-auth/logs/ . jans-auth.log - main AS log file. All logs during execution goes here. jans-auth_script.log : - contains custom interception scripts related log messages. Use scriptLogger inside custom script to log messages to this log file. jans-auth_persistence.log - log which contains entries from AS persistance layer jans-auth_persistence_duration.log - log which contains duration of query execution. It can be useful during performance issues investigation app_persistence_orm_statistics.log - contains statistics about persistence layer activities jans-auth_audit.log - contains audit log information (audit is disabled by default and can be enabled via enabledOAuthAuditLogging AS configuration property) http_request_response.log - contains http request/response data. It can be enabled via httpLoggingEnabled AS configuration property. Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Standard Logs"}, {"location": "janssen-server/auth-server/logging/standard-logs/#standard-logs", "text": "All jans-auth-server log files are located in /opt/jans/jetty/jans-auth/logs/ . jans-auth.log - main AS log file. All logs during execution goes here. jans-auth_script.log : - contains custom interception scripts related log messages. Use scriptLogger inside custom script to log messages to this log file. jans-auth_persistence.log - log which contains entries from AS persistance layer jans-auth_persistence_duration.log - log which contains duration of query execution. It can be useful during performance issues investigation app_persistence_orm_statistics.log - contains statistics about persistence layer activities jans-auth_audit.log - contains audit log information (audit is disabled by default and can be enabled via enabledOAuthAuditLogging AS configuration property) http_request_response.log - contains http request/response data. It can be enabled via httpLoggingEnabled AS configuration property.", "title": "Standard Logs"}, {"location": "janssen-server/auth-server/logging/standard-logs/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/logging/standard-logs/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/oauth-features/auth-code-grant/", "tags": ["administration", "auth-server", "oauth", "feature", "grant", "code"], "text": "OAuth 2.0 Authorization Code Grant # The Authorization Code grant type is used by confidential and public clients to exchange an authorization code for an access token. After the user returns to the client via the redirect URL, the application will get the authorization code from the URL and use it to request an access token. Sequence Diagram # sequenceDiagram title Authorization code flow autonumber 1 participant Resource owner User activate Resource owner User Client->>Jans AS:Authorization Request activate Client activate Jans AS Resource owner User ->>Jans AS:User login and consent Jans AS-->>Client:Authorization code response deactivate Client deactivate Jans AS Client->>Jans AS: Exchange code for Access Token activate Client activate Jans AS Jans AS-->>Client: Access Token with optional Refresh Token deactivate Client deactivate Jans AS loop Client->>Resource Server: Call API with Access Token activate Client activate Resource Server Resource Server-->>Client: Protected Resource deactivate Client deactivate Resource Server end Client->>Resource Server: Call API with expired Access Token activate Client activate Resource Server Resource Server-->>Client: Invalid token error deactivate Client deactivate Resource Server Client->>Jans AS: Resource Token activate Client activate Jans AS Jans AS-->>Client: Access Token with optional Refresh Token deactivate Client deactivate Jans AS deactivate Resource owner User Testing # https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/AuthorizationCodeFlowHttpTest.java On a browser access https://my.jans.server/jans-auth/restv1/authorize?redirect_uri=https://my-redirect-app:8080&client_id=Put_client_id_here&scope=username+openid&response_type=code Based on the default authentication method set (acr), the user will be presented with credentials for login. The OpenID Provider (Gluu Server) verifies the user\u2019s identity and authenticates the user. In the back channel the following steps take place : The OpenID Provider (Gluu Server) sends the user back to the application with an authorization code. The application sends the code to the Token Endpoint to receive an Access Token and ID Token in the response. The application uses the ID Token to authorize the user. At this point the application/RP can access the UserInfo endpoint for claims.", "title": "Authorization Code Grant"}, {"location": "janssen-server/auth-server/oauth-features/auth-code-grant/#oauth-20-authorization-code-grant", "text": "The Authorization Code grant type is used by confidential and public clients to exchange an authorization code for an access token. After the user returns to the client via the redirect URL, the application will get the authorization code from the URL and use it to request an access token.", "title": "OAuth 2.0 Authorization Code Grant"}, {"location": "janssen-server/auth-server/oauth-features/auth-code-grant/#sequence-diagram", "text": "sequenceDiagram title Authorization code flow autonumber 1 participant Resource owner User activate Resource owner User Client->>Jans AS:Authorization Request activate Client activate Jans AS Resource owner User ->>Jans AS:User login and consent Jans AS-->>Client:Authorization code response deactivate Client deactivate Jans AS Client->>Jans AS: Exchange code for Access Token activate Client activate Jans AS Jans AS-->>Client: Access Token with optional Refresh Token deactivate Client deactivate Jans AS loop Client->>Resource Server: Call API with Access Token activate Client activate Resource Server Resource Server-->>Client: Protected Resource deactivate Client deactivate Resource Server end Client->>Resource Server: Call API with expired Access Token activate Client activate Resource Server Resource Server-->>Client: Invalid token error deactivate Client deactivate Resource Server Client->>Jans AS: Resource Token activate Client activate Jans AS Jans AS-->>Client: Access Token with optional Refresh Token deactivate Client deactivate Jans AS deactivate Resource owner User", "title": "Sequence Diagram"}, {"location": "janssen-server/auth-server/oauth-features/auth-code-grant/#testing", "text": "https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/AuthorizationCodeFlowHttpTest.java On a browser access https://my.jans.server/jans-auth/restv1/authorize?redirect_uri=https://my-redirect-app:8080&client_id=Put_client_id_here&scope=username+openid&response_type=code Based on the default authentication method set (acr), the user will be presented with credentials for login. The OpenID Provider (Gluu Server) verifies the user\u2019s identity and authenticates the user. In the back channel the following steps take place : The OpenID Provider (Gluu Server) sends the user back to the application with an authorization code. The application sends the code to the Token Endpoint to receive an Access Token and ID Token in the response. The application uses the ID Token to authorize the user. At this point the application/RP can access the UserInfo endpoint for claims.", "title": "Testing"}, {"location": "janssen-server/auth-server/oauth-features/client-credential-grant/", "tags": ["administration", "auth-server", "oauth", "feature", "grant", "client-credentials"], "text": "OAuth 2.0 client credentials Grant # Sequence Diagram # sequenceDiagram title Client credentials flow autonumber 1 activate Resource owner Client Resource owner Client->>Jans AS:Client Authentication activate Jans AS Jans AS-->>Resource owner Client:Access Token deactivate Jans AS Testing # https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/ClientCredentialsGrantHttpTest.java CURL Command: curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=put_scope_name_here\"", "title": "Client Credential Grant"}, {"location": "janssen-server/auth-server/oauth-features/client-credential-grant/#oauth-20-client-credentials-grant", "text": "", "title": "OAuth 2.0 client credentials Grant"}, {"location": "janssen-server/auth-server/oauth-features/client-credential-grant/#sequence-diagram", "text": "sequenceDiagram title Client credentials flow autonumber 1 activate Resource owner Client Resource owner Client->>Jans AS:Client Authentication activate Jans AS Jans AS-->>Resource owner Client:Access Token deactivate Jans AS", "title": "Sequence Diagram"}, {"location": "janssen-server/auth-server/oauth-features/client-credential-grant/#testing", "text": "https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/ClientCredentialsGrantHttpTest.java CURL Command: curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=put_scope_name_here\"", "title": "Testing"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/", "tags": ["administration", "auth-server", "oauth", "feature", "device", "grant"], "text": "OAuth 2.0 Device Authorization Grant # This OAuth 2.0 protocol extension enables OAuth clients to request user authorization from applications on devices (e.g. smart TVs, media consoles, printers) that are input-constrained or browser-less . The authorization flow defined by this RFC 8628 , sometimes referred to as the \"device flow\", instructs the user to review the authorization request on a secondary device, such as a smartphone or a personal computer, which has the requisite input and browser capabilities to complete the user interaction. Sequence Diagram # Paste the following source text of the sequence diagram on sequencediagram.org title Oauth2.0 Device Authorization flow participant User participant Browser on Computer / Smartphone participant Device App participant Jans AS participant Third Party App User->Device App:Opens an app on device Device App->Jans AS:Sends authorization request \\n\"jans-server.com/jans-auth/restv1/device_authorization\" Jans AS->Device App:Response - \\nuser_code, device_code, verification_url, interval, expiration Device App ->User: Instructs the user to access Verification URL \\nand enter user_code note over Device App:Device App will keep polling AS for Access Token \\nuntil device authorization is completed loop till Device App recieves Access Token: Device App->Jans AS:request Access Token Jans AS->Device App:Response - \\naccess_denied \\nOR expired_token \\nOR authorization_pending \\nOR Access token end User->Browser on Computer / Smartphone:Opens a browser \\nand access verification URL Browser on Computer / Smartphone->Jans AS:send user_code to verification URL Browser on Computer / Smartphone <-Jans AS:Login and authorization prompt Browser on Computer / Smartphone->Jans AS:Authentication and consent Jans AS->Jans AS: Mark device as Authorized note over Jans AS:Subsequent polling by the Device App \\nwill return an Access Token as indicated \\nby the loop above Device App->Third Party App:Invoke API with Access Token Third Party App->Device App: return Response User Experience # First, the user requests authorization from the device: At the URL displayed on the screen, the user can input the displayed code in the device. After that, user could need to authenticate, then decide whether permissions will be granted. acr value can be specified in deviceAuthzAcr AS configuration property. Finally, the confirmation screen will be shown. ACR value during Device Authorization # User is required to authenticate if not authenticated yet. By default acr_values is not set in authorization request, which means it relies on default AS handling. However it's possible explicitly set acr value during Device Authorization by setting deviceAuthzAcr AS configuration property. Request user and device codes # This first step, device sends an HTTP POST request to Jans authorization server, at /jans-auth/restv1/device_authorization which is also presented in the Discovery url published by Jans Server, this endpoint could process a common authentication method or it could also not do any authentication, depending on the configuration for the client in Jans Server. Parameters # Parameter Description client_id Required The client ID for your application. scope Required A space separated list of scopes that identify the resources that the device could access on the user's behalf. These values inform the consent screen that Jans server displays to the user. Example # POST /restv1/device_authorization HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.org Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 client_id=123-123-123&scope=openid+profile+address+email+phone Device Request response # In response, the Jans authorization server generates a unique device verification code and an end-user code that are valid for a limited time and includes them in the HTTP response body using the \"application/json\" format with a 200 (OK) status code. The response contains the following parameters: Parameter Description user_code Required The end-user verification code device_code Required The device verification code verification_uri Required The end-user verification URI on the authorization server. This should be shown to the end-user because he should open this url in the rich user-agent. verification_uri_complete Optional This is similar than verification_uri , however it also includes user_code as a query param in the url. It's issued if the device wants to use QR mode for example. expires_in Required The lifetime in seconds of the device_code and user_code . interval Required The minimum amount of time in seconds that the client should wait between polling requests to the token endpoint. Example: # HTTP/1.1 200 Content-Length: 307 Content-Type: application/json Server: Jetty(9.4.19.v20190610) { \"user_code\": \"SJFP-DTPL\", \"device_code\": \"aeb28bdc90d806ac58d4b0f832f06c3ac9c4bd03292f0c09\", \"interval\": 5, \"verification_uri_complete\": \"https://test.jans.io:8443/device-code?user_code=SJFP-DTPL\", \"verification_uri\": \"https://test.jans.io:8443/device-code\", \"expires_in\": 1800 } Device Display # Common flow, the device should display verification_url and user_code received from Jans server. The content that the device displays to the user should instruct the user to navigate to the verification_url on a separate device and enter the user_code . Design device interface following these rules: user_code has the following format: XXXX-XXXX where Xs represent to any ASCII character, for example: RTXD-HTLK . The length of the user_code will be always the same, therefore it's highly recommended to show it as clear and big that the user can read it easly. verification_url should be displayed also in a way that the user can read it easily. The normal length should be around 40 characters, however it could depends also on the domain used for the server. Remember that the user will need to write the whole URL manually in the web browser, therefore it's recommended to use a short URL. verification_url_complete will be used for those cases where device can show QR (Quick Response) codes or NFC (Near Field Communication) to save the user from typing the whole URI. Interaction between device and Jans server will be the same, however user can process the authorization faster. For example: User Login & Authorization # The user will need to put user_code value in the browser and after that, he will be redirected to the common authorization flow, it requires login whether there is no session between the user-agent and the Jans server and grant the permissions based on the device request. Poll Token # Since the user will be using a separate device to navigate to the verification_url and grant or deny access, the requesting device is not automatically notified when the user responds to the access request. For that reason, the requesting device needs to poll the Jans Server to determine when the user has responded to the request. The requesting device should continue sending polling requests until it receives a response indicating that the user has responded to the access request or until the device_code expires. The parameter interval returned in step 2 specifies the amount of time, in seconds, to wait between requests. The URL of the endpoint to poll is /jans-auth/restv1/token . The polling request contains the following parameters: Parameters # Parameter Description client_id Required The client ID for your application. grant_type Required Must be urn:ietf:params:oauth:grant-type:device_code . device_code Required The device verification code which is returned by Jans server in Step 2. Authentication can be done using any of those authentication methods for this token endpoint. Example: # POST /restv1/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.io Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&device_code=0bd7068e7fdab4bb91b313296a96462256a7370d12f073f0 Token Response # The Jans authorization server responds to each polling request with one of the following responses: Access granted If the user granted access to the device (by clicking Allow on the consent screen), then the response contains an access token and a refresh token. The tokens enable the device to access to the resource server on the user's behalf. In this case, the server responds with all tokens required and allowed to be issued depending on the configuration in the server. Example: HTTP/1.1 200 Content-Length: 858 Content-Type: application/json Server: Jetty(9.4.19.v20190610) {\"access_token\":\"c31fc092-453b-4275-a36f-b2740c3eb1a6\",\"id_token\":\"eyJraWQiOiJlY4.2Tc4NDgxYy05OTJkLTRmN2UtYTkzMS03NjM2NTYyMzgwZjVfc2lnX3JzMjU2IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoidWdMSnAzMkxXdnI4QUdlbmdNTlF3QSIsImF1ZCI6IjEyMy0xMjMtMTIzIiwic3ViIjoiM2M2M25HdWZnWFNkMWFwNU81NFZkVjlUUDdmdjJHc0YtLWl0eVBHeFJBTSIsImlzcyI6Imh0dHBzOi8vdGVzdC5nbHV1Lm9yZzo4NDQzIiwiZXhwIjoxNTk1NjQzOTg0LCJpYXQiOjE1OTU2NDAzODQsIm94T3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCJ9.fElZtuUslhSSuqTOuvGeafG4QuQoHKLpya25RHWkC5V9Xf9ODYa6tD_Tdav2D9Gff2Zz7pt8WKso-WYOqmJ3NrgMoVU7d1SMj6pYGilTL1JokjB18Yw1TI6oR6Z4wegy8_ajftLLhqosI5-ZE36TzPwoAKzjPl-iZEpV2U1OPHWZrdwc9N3YOyO0I_IJGQmFnXC_oacitMV2VZaTxfuCew5cPwNp5durooFNvv3DPzc9JYEctmaLsiRtfqN7pCaV30B3hnYTYZ4p2HNsUbOewBI8_Brm1v1CByitQPUFqETgmPGbf4HCTEoaH-7DfaXnAsePt73blNwJrlTlUBieew\",\"token_type\":\"bearer\",\"expires_in\":299} Access denied If the user refuses to grant access to the device, then the server response has a 400 HTTP response status code. The response contains the following error: HTTP/1.1 400 Cache-Control: no-store Content-Length: 74 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"access_denied\", \"error\": \"access_denied\" } Authorization pending It means that the request hasn't been processed by the end-user yet, therefore the request is still in process. Example: HTTP/1.1 400 Cache-Control: no-store Content-Length: 90 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"authorization_pending\", \"error\": \"authorization_pending\" } Polling too frequently If the device sends polling requests too frequently, then the server returns a 400 HTTP response status code. Then the device should increase the time interval between requests. Example: HTTP/1.1 400 Cache-Control: no-store Content-Length: 66 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"slow_down\", \"error\": \"slow_down\" } Other errors This token endpoint can return any error code already defined, for example whether client can't be authenticated or the grant type sent is invalid. Some of them could be: invalid_client , invalid_grant , invalid_request and others. Customizing Device Grant page # More about customising this page to include your organization's stylesheets, images and content in this article", "title": "Device Grant"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#oauth-20-device-authorization-grant", "text": "This OAuth 2.0 protocol extension enables OAuth clients to request user authorization from applications on devices (e.g. smart TVs, media consoles, printers) that are input-constrained or browser-less . The authorization flow defined by this RFC 8628 , sometimes referred to as the \"device flow\", instructs the user to review the authorization request on a secondary device, such as a smartphone or a personal computer, which has the requisite input and browser capabilities to complete the user interaction.", "title": "OAuth 2.0 Device Authorization Grant"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#sequence-diagram", "text": "Paste the following source text of the sequence diagram on sequencediagram.org title Oauth2.0 Device Authorization flow participant User participant Browser on Computer / Smartphone participant Device App participant Jans AS participant Third Party App User->Device App:Opens an app on device Device App->Jans AS:Sends authorization request \\n\"jans-server.com/jans-auth/restv1/device_authorization\" Jans AS->Device App:Response - \\nuser_code, device_code, verification_url, interval, expiration Device App ->User: Instructs the user to access Verification URL \\nand enter user_code note over Device App:Device App will keep polling AS for Access Token \\nuntil device authorization is completed loop till Device App recieves Access Token: Device App->Jans AS:request Access Token Jans AS->Device App:Response - \\naccess_denied \\nOR expired_token \\nOR authorization_pending \\nOR Access token end User->Browser on Computer / Smartphone:Opens a browser \\nand access verification URL Browser on Computer / Smartphone->Jans AS:send user_code to verification URL Browser on Computer / Smartphone <-Jans AS:Login and authorization prompt Browser on Computer / Smartphone->Jans AS:Authentication and consent Jans AS->Jans AS: Mark device as Authorized note over Jans AS:Subsequent polling by the Device App \\nwill return an Access Token as indicated \\nby the loop above Device App->Third Party App:Invoke API with Access Token Third Party App->Device App: return Response", "title": "Sequence Diagram"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#user-experience", "text": "First, the user requests authorization from the device: At the URL displayed on the screen, the user can input the displayed code in the device. After that, user could need to authenticate, then decide whether permissions will be granted. acr value can be specified in deviceAuthzAcr AS configuration property. Finally, the confirmation screen will be shown.", "title": "User Experience"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#acr-value-during-device-authorization", "text": "User is required to authenticate if not authenticated yet. By default acr_values is not set in authorization request, which means it relies on default AS handling. However it's possible explicitly set acr value during Device Authorization by setting deviceAuthzAcr AS configuration property.", "title": "ACR value during Device Authorization"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#request-user-and-device-codes", "text": "This first step, device sends an HTTP POST request to Jans authorization server, at /jans-auth/restv1/device_authorization which is also presented in the Discovery url published by Jans Server, this endpoint could process a common authentication method or it could also not do any authentication, depending on the configuration for the client in Jans Server.", "title": "Request user and device codes"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#parameters", "text": "Parameter Description client_id Required The client ID for your application. scope Required A space separated list of scopes that identify the resources that the device could access on the user's behalf. These values inform the consent screen that Jans server displays to the user.", "title": "Parameters"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#example", "text": "POST /restv1/device_authorization HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.org Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 client_id=123-123-123&scope=openid+profile+address+email+phone", "title": "Example"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#device-request-response", "text": "In response, the Jans authorization server generates a unique device verification code and an end-user code that are valid for a limited time and includes them in the HTTP response body using the \"application/json\" format with a 200 (OK) status code. The response contains the following parameters: Parameter Description user_code Required The end-user verification code device_code Required The device verification code verification_uri Required The end-user verification URI on the authorization server. This should be shown to the end-user because he should open this url in the rich user-agent. verification_uri_complete Optional This is similar than verification_uri , however it also includes user_code as a query param in the url. It's issued if the device wants to use QR mode for example. expires_in Required The lifetime in seconds of the device_code and user_code . interval Required The minimum amount of time in seconds that the client should wait between polling requests to the token endpoint.", "title": "Device Request response"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#example_1", "text": "HTTP/1.1 200 Content-Length: 307 Content-Type: application/json Server: Jetty(9.4.19.v20190610) { \"user_code\": \"SJFP-DTPL\", \"device_code\": \"aeb28bdc90d806ac58d4b0f832f06c3ac9c4bd03292f0c09\", \"interval\": 5, \"verification_uri_complete\": \"https://test.jans.io:8443/device-code?user_code=SJFP-DTPL\", \"verification_uri\": \"https://test.jans.io:8443/device-code\", \"expires_in\": 1800 }", "title": "Example:"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#device-display", "text": "Common flow, the device should display verification_url and user_code received from Jans server. The content that the device displays to the user should instruct the user to navigate to the verification_url on a separate device and enter the user_code . Design device interface following these rules: user_code has the following format: XXXX-XXXX where Xs represent to any ASCII character, for example: RTXD-HTLK . The length of the user_code will be always the same, therefore it's highly recommended to show it as clear and big that the user can read it easly. verification_url should be displayed also in a way that the user can read it easily. The normal length should be around 40 characters, however it could depends also on the domain used for the server. Remember that the user will need to write the whole URL manually in the web browser, therefore it's recommended to use a short URL. verification_url_complete will be used for those cases where device can show QR (Quick Response) codes or NFC (Near Field Communication) to save the user from typing the whole URI. Interaction between device and Jans server will be the same, however user can process the authorization faster. For example:", "title": "Device Display"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#user-login-authorization", "text": "The user will need to put user_code value in the browser and after that, he will be redirected to the common authorization flow, it requires login whether there is no session between the user-agent and the Jans server and grant the permissions based on the device request.", "title": "User Login & Authorization"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#poll-token", "text": "Since the user will be using a separate device to navigate to the verification_url and grant or deny access, the requesting device is not automatically notified when the user responds to the access request. For that reason, the requesting device needs to poll the Jans Server to determine when the user has responded to the request. The requesting device should continue sending polling requests until it receives a response indicating that the user has responded to the access request or until the device_code expires. The parameter interval returned in step 2 specifies the amount of time, in seconds, to wait between requests. The URL of the endpoint to poll is /jans-auth/restv1/token . The polling request contains the following parameters:", "title": "Poll Token"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#parameters_1", "text": "Parameter Description client_id Required The client ID for your application. grant_type Required Must be urn:ietf:params:oauth:grant-type:device_code . device_code Required The device verification code which is returned by Jans server in Step 2. Authentication can be done using any of those authentication methods for this token endpoint.", "title": "Parameters"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#example_2", "text": "POST /restv1/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.io Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&device_code=0bd7068e7fdab4bb91b313296a96462256a7370d12f073f0", "title": "Example:"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#token-response", "text": "The Jans authorization server responds to each polling request with one of the following responses: Access granted If the user granted access to the device (by clicking Allow on the consent screen), then the response contains an access token and a refresh token. The tokens enable the device to access to the resource server on the user's behalf. In this case, the server responds with all tokens required and allowed to be issued depending on the configuration in the server. Example: HTTP/1.1 200 Content-Length: 858 Content-Type: application/json Server: Jetty(9.4.19.v20190610) {\"access_token\":\"c31fc092-453b-4275-a36f-b2740c3eb1a6\",\"id_token\":\"eyJraWQiOiJlY4.2Tc4NDgxYy05OTJkLTRmN2UtYTkzMS03NjM2NTYyMzgwZjVfc2lnX3JzMjU2IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoidWdMSnAzMkxXdnI4QUdlbmdNTlF3QSIsImF1ZCI6IjEyMy0xMjMtMTIzIiwic3ViIjoiM2M2M25HdWZnWFNkMWFwNU81NFZkVjlUUDdmdjJHc0YtLWl0eVBHeFJBTSIsImlzcyI6Imh0dHBzOi8vdGVzdC5nbHV1Lm9yZzo4NDQzIiwiZXhwIjoxNTk1NjQzOTg0LCJpYXQiOjE1OTU2NDAzODQsIm94T3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCJ9.fElZtuUslhSSuqTOuvGeafG4QuQoHKLpya25RHWkC5V9Xf9ODYa6tD_Tdav2D9Gff2Zz7pt8WKso-WYOqmJ3NrgMoVU7d1SMj6pYGilTL1JokjB18Yw1TI6oR6Z4wegy8_ajftLLhqosI5-ZE36TzPwoAKzjPl-iZEpV2U1OPHWZrdwc9N3YOyO0I_IJGQmFnXC_oacitMV2VZaTxfuCew5cPwNp5durooFNvv3DPzc9JYEctmaLsiRtfqN7pCaV30B3hnYTYZ4p2HNsUbOewBI8_Brm1v1CByitQPUFqETgmPGbf4HCTEoaH-7DfaXnAsePt73blNwJrlTlUBieew\",\"token_type\":\"bearer\",\"expires_in\":299} Access denied If the user refuses to grant access to the device, then the server response has a 400 HTTP response status code. The response contains the following error: HTTP/1.1 400 Cache-Control: no-store Content-Length: 74 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"access_denied\", \"error\": \"access_denied\" } Authorization pending It means that the request hasn't been processed by the end-user yet, therefore the request is still in process. Example: HTTP/1.1 400 Cache-Control: no-store Content-Length: 90 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"authorization_pending\", \"error\": \"authorization_pending\" } Polling too frequently If the device sends polling requests too frequently, then the server returns a 400 HTTP response status code. Then the device should increase the time interval between requests. Example: HTTP/1.1 400 Cache-Control: no-store Content-Length: 66 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"slow_down\", \"error\": \"slow_down\" } Other errors This token endpoint can return any error code already defined, for example whether client can't be authenticated or the grant type sent is invalid. Some of them could be: invalid_client , invalid_grant , invalid_request and others.", "title": "Token Response"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#customizing-device-grant-page", "text": "More about customising this page to include your organization's stylesheets, images and content in this article", "title": "Customizing Device Grant page"}, {"location": "janssen-server/auth-server/oauth-features/dpop/", "tags": ["administration", "auth-server", "oauth", "feature", "dpop"], "text": "DPoP (Demonstrating Proof-of-Possession at the Application Layer) # Janssen Server supports DPoP (Demonstrating Proof-of-Possession) at the Application Layer, which is OAuth 2.0 feature to enhance the security of resources protected by access tokens. When DPoP is being used, the Janssen Server checks whether the presenter of the access token is the one to whom the access token was issued. Hence, making sure that a stolen access token is not being used by someone else to access the protected resource. OAuth 2.0 DPoP specification is available here Janssen Server also supports OAuth MTLS(Mutual TLS) as a mechanism to ensure that the token presenting party is legitimate. While MTLS should be preferred whenever it is possible to use it, for other cases like single page application(SPA), DPoP can be used. Using DPoP # Using DPoP Proof JWT # To use DPoP protection, the client needs to create DPoP Proof JWT (or DPoP Proof) and send it using DPoP request header to Janssen Server when: Requesting for a new access token Accessing a protected resource using the access token DPoP proofs are created differently for the cases listed above. DPoP specification describes how . When an access token is requested with the DPoP header (1 above), the Janssen Server returns an access token (or refresh token) that is bound(mapped) to the public key attached with the DPoP proof. Subsequently, when the client uses the access token to access the protected resource (2 above), it again creates and attaches the DPoP Proof with the request. The resource server checks the validity of the request by ensuring that the access token used is bound to the same public key which is presented in the DPoP proof in the request. The resource server uses steps laid out in the specification to acertain this. sequenceDiagram title DPoP sender-constraint access_token and refresh_token autonumber note right of RP: Authorization Code Flow RP->AS: Request authorization with dpop_jtk AS->AS: dpop_jkt saved for authorization code AS->RP: Return authorization code note right of RP: Token Request RP->AS: Request token with DPoP JWT AS->AS: Validates DPoP JWT AS->AS: Validates dpop_jkt against DPoP JWT if it's authz code AS->AS: Creates access_token bound to public key cnf/jkt note right of AS: if AT is bearer cnf/jkt is available via introspection AS->RP: Returns DPoP-bound access_token with cnf/jkt (response token_type=DPoP) RP->RS: Request resource with access_token and DPoP JWT (with \"ath\" - AT hash) RS->RS: Validates access_token against DPoP (public key match cnf/jkt) RS->RS: Validates DPoP against access_token (access_token hash in DPoP \"ath\") RS->RP: Return protected resource Authorization Code Binding to DPoP Key # Authorization Endpoint supports dpop_jkt parameter for DPoP binding of authorization code. GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz\\ &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb\\ &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\\ &code_challenge_method=S256\\ &dpop_jkt=NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs HTTP/1.1 Host: server.example.com For PAR, both ways of binging are supported: Via dpop_jkt Via DPoP header where dpop_jkt is calculated out of DPoP header value Using Introspection Endpoint # Janssen Server introspection endpoint supports the JWK thumbprint confirmation method. Using this, the resource server can introspect an access token and obtain the hash of the public key associated with the access token. Response from the introspection endpoint will share this information in the format recommended in the specificaiton Janssen Server Configuration for DPoP # Following properties of the Janssen Server can be used to tailor the behavior concerning DPoP. dpopJtiCacheTime dpopSigningAlgValuesSupported dpopTimeframe dpopUseNonce dpopNonceCacheTime dpopJktForceForAuthorizationCode Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "DPoP"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#dpop-demonstrating-proof-of-possession-at-the-application-layer", "text": "Janssen Server supports DPoP (Demonstrating Proof-of-Possession) at the Application Layer, which is OAuth 2.0 feature to enhance the security of resources protected by access tokens. When DPoP is being used, the Janssen Server checks whether the presenter of the access token is the one to whom the access token was issued. Hence, making sure that a stolen access token is not being used by someone else to access the protected resource. OAuth 2.0 DPoP specification is available here Janssen Server also supports OAuth MTLS(Mutual TLS) as a mechanism to ensure that the token presenting party is legitimate. While MTLS should be preferred whenever it is possible to use it, for other cases like single page application(SPA), DPoP can be used.", "title": "DPoP (Demonstrating Proof-of-Possession at the Application Layer)"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#using-dpop", "text": "", "title": "Using DPoP"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#using-dpop-proof-jwt", "text": "To use DPoP protection, the client needs to create DPoP Proof JWT (or DPoP Proof) and send it using DPoP request header to Janssen Server when: Requesting for a new access token Accessing a protected resource using the access token DPoP proofs are created differently for the cases listed above. DPoP specification describes how . When an access token is requested with the DPoP header (1 above), the Janssen Server returns an access token (or refresh token) that is bound(mapped) to the public key attached with the DPoP proof. Subsequently, when the client uses the access token to access the protected resource (2 above), it again creates and attaches the DPoP Proof with the request. The resource server checks the validity of the request by ensuring that the access token used is bound to the same public key which is presented in the DPoP proof in the request. The resource server uses steps laid out in the specification to acertain this. sequenceDiagram title DPoP sender-constraint access_token and refresh_token autonumber note right of RP: Authorization Code Flow RP->AS: Request authorization with dpop_jtk AS->AS: dpop_jkt saved for authorization code AS->RP: Return authorization code note right of RP: Token Request RP->AS: Request token with DPoP JWT AS->AS: Validates DPoP JWT AS->AS: Validates dpop_jkt against DPoP JWT if it's authz code AS->AS: Creates access_token bound to public key cnf/jkt note right of AS: if AT is bearer cnf/jkt is available via introspection AS->RP: Returns DPoP-bound access_token with cnf/jkt (response token_type=DPoP) RP->RS: Request resource with access_token and DPoP JWT (with \"ath\" - AT hash) RS->RS: Validates access_token against DPoP (public key match cnf/jkt) RS->RS: Validates DPoP against access_token (access_token hash in DPoP \"ath\") RS->RP: Return protected resource", "title": "Using DPoP Proof JWT"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#authorization-code-binding-to-dpop-key", "text": "Authorization Endpoint supports dpop_jkt parameter for DPoP binding of authorization code. GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz\\ &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb\\ &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\\ &code_challenge_method=S256\\ &dpop_jkt=NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs HTTP/1.1 Host: server.example.com For PAR, both ways of binging are supported: Via dpop_jkt Via DPoP header where dpop_jkt is calculated out of DPoP header value", "title": "Authorization Code Binding to DPoP Key"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#using-introspection-endpoint", "text": "Janssen Server introspection endpoint supports the JWK thumbprint confirmation method. Using this, the resource server can introspect an access token and obtain the hash of the public key associated with the access token. Response from the introspection endpoint will share this information in the format recommended in the specificaiton", "title": "Using Introspection Endpoint"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#janssen-server-configuration-for-dpop", "text": "Following properties of the Janssen Server can be used to tailor the behavior concerning DPoP. dpopJtiCacheTime dpopSigningAlgValuesSupported dpopTimeframe dpopUseNonce dpopNonceCacheTime dpopJktForceForAuthorizationCode", "title": "Janssen Server Configuration for DPoP"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/oauth-features/implicit-grant/", "tags": ["administration", "auth-server", "oauth", "feature", "grant", "implicit"], "text": "OAuth 2.0 Implicit Grant # The Implicit Grant : !!! OAuth 2.0 Security Best Current Practice absolutely discourages the use of Implicit flow. Instead, use Authorization code flow with PKCE - OAuth 2.0 for Browser-Based Apps . Further reading Sequence Diagram # sequenceDiagram title Implicit flow autonumber 1 participant Resource owner User Client->>Jans AS:Authorization Request activate Client activate Jans AS Resource owner User ->>Jans AS:User login and consent Jans AS-->>Client:Access Token in the URI fragment deactivate Client deactivate Jans AS Client ->>Jans AS:Validate Access Token activate Client activate Jans AS Jans AS-->>Client:Validate response deactivate Client deactivate Jans AS Client ->>Web - Hosted client resource:Call API with Access Token activate Client activate Jans AS Jans AS-->>Client:Protected resource deactivate Client deactivate Jans AS", "title": "Implicit Grant"}, {"location": "janssen-server/auth-server/oauth-features/implicit-grant/#oauth-20-implicit-grant", "text": "The Implicit Grant : !!! OAuth 2.0 Security Best Current Practice absolutely discourages the use of Implicit flow. Instead, use Authorization code flow with PKCE - OAuth 2.0 for Browser-Based Apps . Further reading", "title": "OAuth 2.0 Implicit Grant"}, {"location": "janssen-server/auth-server/oauth-features/implicit-grant/#sequence-diagram", "text": "sequenceDiagram title Implicit flow autonumber 1 participant Resource owner User Client->>Jans AS:Authorization Request activate Client activate Jans AS Resource owner User ->>Jans AS:User login and consent Jans AS-->>Client:Access Token in the URI fragment deactivate Client deactivate Jans AS Client ->>Jans AS:Validate Access Token activate Client activate Jans AS Jans AS-->>Client:Validate response deactivate Client deactivate Jans AS Client ->>Web - Hosted client resource:Call API with Access Token activate Client activate Jans AS Jans AS-->>Client:Protected resource deactivate Client deactivate Jans AS", "title": "Sequence Diagram"}, {"location": "janssen-server/auth-server/oauth-features/mtls/", "tags": ["administration", "auth-server", "oauth", "feature", "mtls", "mutual TLS"], "text": "mTLS (Mutual Transport Layer Security) # What Is mTLS? # mTLS is a process that establishes an encrypted TLS connection in which both parties use X.509 digital certificates to authenticate each other. mTLS can help mitigate the risk of moving services to the cloud and can help prevent malicious third parties from imitating genuine apps. Where Is mTLS Useful? # Mutual client certificate authentication can be used any time the server needs to ensure the authenticity and validity of either a specific user or a specific device. For example, a client certificate can be issued to a company-owned laptop to identify and authorize it on a corporate network. Alternatively, a client certificate could be issued to an employee and stored on a smart card, which then allows the employee to gain access to applications or restricted areas of a building. In practice, mTLS can identify and authorize the following: Devices onto a corporate network. Users into applications. Content delivery network (CDNs) or cloud security services to back-end web servers. Business-to-business (B2B) data exchanges that use APIs. Internet of Things (IoT) sensors, such as remote traffic cameras. Microservice architectures in which each microservice must ensure that each component it communicates with is valid and not tampered with. mTLS in Jans Auth # Jans Auth supports mTLS , and to configure it we must take these considerations into account: During DCR client registration, the token_endpoint_auth_method field can receive 2 new values: tls_client_auth : indicates that client authentication to the authorization server will occur with mutual TLS utilizing the PKI method of associating a certificate to a client. self_signed_tls_client_auth : Indicates that client authentication to the authorization server will occur using mutual TLS with the client utilizing a self-signed certificate. There is new client property tls_client_auth_subject_dn used to compare Subject DN of the certificate with configured value of client entry when authentication method is set to tls_client_auth (saved in tls_client_auth_subject_dn or oxAttributes on persistence layer). If MTLS Authentication is used then access_token automatically saves certificate S256 hash of certificates which can be validated by RP. If access_token is JWT then x5t#S256 claim is added to payload of the token. Otherwise, token can be introspected. { \"active\": true, \"iss\": \"https://server.example.com\", \"sub\": \"ty.webb@example.com\", \"exp\": 1493726400, \"nbf\": 1493722800, \"cnf\": { \"x5t#S256\": \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" }, ..., ... } Configuring Apache for mTLS # The information below belongs to apache and web client (usually web browser) mutual authentication setup method. This also includes basic checks to be performed for the setup. Is mod_ssl installed: Run below command to confirm if the ssl module is installed. apachectl -M | grep ssl If we get ssl_module related output, then we're good to proceed. The output could look like: root@jans:~# apachectl -M | grep ssl ssl_module (shared) Usually third party or Certbot SSL certs are used for web server ssl connections. In that case no extra configuration is necessary. But if we want to use self-signed certs, then follow on. Self-Signed SSL Certs # Server-Side mTLS setup # Now, we're covering the case if you want to deploy your own CA Cert. 1. Open Terminal. # 2. Create a new directory to generate certificates. # mkdir /etc/certs/mtlscert Change to the directory created. cd /etc/certs/mtlscert 3. Generate Self-Signed CA Cert. # Run below command: openssl req -newkey rsa:2048 -nodes -keyform PEM -keyout example-ca.key -x509 -days 3650 -outform PEM -out example-ca.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -newkey rsa:2048 -nodes -keyform PEM -keyout example-ca.key -x509 -days 3650 -outform PEM -out example-ca.crt Generating a RSA private key .........................................+++++ .........................................+++++ writing new private key to 'example-ca.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Above command will create two files: example-ca.key and example-ca.crt . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key 4. Generate private key. # Run below command: openssl genrsa -out example.key 2048 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl genrsa -out example.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ......................................+++++ ..........................................................................................................+++++ e is 65537 (0x010001) Above command creates: example.key . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.key 5. Generate a server CSR (Certificate Signing Request): # Run below command: openssl req -new -key example.key -out example.csr Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -new -key example.key -out example.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Above command will create the file: example.csr . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.csr example.key 6. Sign the CSR example.csr we just generated. # Run below command: openssl x509 -req -in example.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 100 -days 365 -outform PEM -out example.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl x509 -req -in example.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 100 -days 365 -outform PEM -out example.crt Signature ok subject=C = US, ST = Austin, L = TX, O = Janssen Org., OU = IT, CN = yourdomain.com, emailAddress = youremail@yourdomain.com Getting CA Private Key Above command will create the file: example.crt for 365 days. root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.crt example.csr example.key 7. Configure Apache2. # Add the following lines in the /etc/apache2/sites-available/https_jans.conf file. SSLEngine On SSLCertificateFile /etc/certs/mtlscert/example.crt SSLCertificateKeyFile /etc/certs/mtlscert/example.key SSLCACertificateFile /etc/certs/mtlscert/example-ca.crt It is critical to configure certificates validation on Apache 2 correctly, since actual validation of the certificates is performed by Apache 2. After Apache certificate validation is configured correctly, make sure there is client certificate forward to jans-auth application. jans-auth (AS) expects certificate in X-ClientCert header. <LocationMatch /jans-auth> SSLVerifyClient require SSLVerifyDepth 10 SSLOptions -StdEnvVars +ExportCertData # Forward certificate to destination server (oxauth) RequestHeader set X-ClientCert %{SSL_CLIENT_CERT}s </LocationMatch> Now we must restart the Apache2 server. service apache2 restart To check if SSL cert on apache works: openssl s_client -connect yourdomain.com:443 Client-Side mTLS setup # 1. Generate private key. # Run below command: openssl genrsa -out example-cli.key 2048 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl genrsa -out example-cli.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ...........................................+++++ .............................................+++++ e is 65537 (0x010001) Above command will create the file: example-cli.key . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.key example.crt example.csr example.key 2. Generate a client CSR (Certificate Signing Request). # Run below command: openssl req -new -key example-cli.key -out example-cli.csr Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -new -key example-cli.key -out example-cli.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Client Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Above command will create the file: example-cli.csr . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.csr example-cli.key example.crt example.csr example.key 3. Sign the CSR example-cli.csr we just generated. # Run below command: openssl x509 -req -in example-cli.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 101 -days 365 -outform PEM -out example-cli.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl x509 -req -in example-cli.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 101 -days 365 -outform PEM -out example-cli.crt Signature ok subject=C = US, ST = Austin, L = TX, O = Janssen Client Org., OU = IT, CN = yourdomain.com, emailAddress = youremail@yourdomain.com Getting CA Private Key Above command will create the file: example-cli.crt for 365 days. root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.crt example-cli.csr example-cli.key example.crt example.csr example.key 4. Generate PKCS12 cert # Some browsers need client certs to be in the format pkcs12 . Run below command: openssl pkcs12 -export -inkey example-cli.key -in example-cli.crt -out example-cli.p12 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl pkcs12 -export -inkey example-cli.key -in example-cli.crt -out example-cli.p12 Enter Export Password: Verifying - Enter Export Password: Above command will create the file: example-cli.p12 . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.crt example-cli.csr example-cli.key example-cli.p12 example.crt example.csr example.key mTLS testing # We are going to run an mTLS example where we will perform the following flow: Register new client. Call authorize endpoint. Call token endpoint. Call introspection endpoint. Previously we need to configure the client's certificate in the browser of your choice. Google Chrome Settings # In the search bar go to chrome://settings/certificates . In the Your Certificates section, click on Import button. Select the certificate example-cli.p12 and enter the password you set when generating it. Firefox Settings # In the search bar go to about:preferences#privacy . Click on View Certificates . In the Your Certificates section, click on Import button. Select the certificate example-cli.p12 and enter the password you set when generating it. Solving the curl problem # If you have openssl version 3.x.x , most likely when you are trying to consume the /.well-known/openid-configuration endpoint. curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' You will get the following error: root@jans~# curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' curl: (58) could not parse PKCS12 file, check password, OpenSSL error error:0308010C:digital envelope routines::unsupported To fix this error, edit the file /etc/ssl/openssl.cnf and make sure that these lines are uncommented and if they are not, add them: openssl_conf = openssl_init [openssl_init] providers = provider_sect [provider_sect] default = default_sect legacy = legacy_sect [default_sect] activate = 1 [legacy_sect] activate = 1 Once this change is done, you should be able to consume the /.well-known/openid-configuration endpoint without any problems root@jans~# curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : true, \"issuer\" : \"https://<YOUR_DOMAIN>\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/authorize\", ..., ..., ... } 1. Register new client # Run below command: curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/register' \\ --header 'Content-Type: application/json' \\ --data '{ \"client_name\": \"Test Client mTLS\", \"application_type\": \"web\", \"access_token_as_jwt\": true, \"token_endpoint_auth_method\": \"self_signed_tls_client_auth\", \"jwks\": { \"keys\": [ { \"kid\": \"YOUR_KID\", \"kty\": \"RSA\", \"alg\": \"RS256\", \"use\": \"sig\", \"e\": \"AQAB\", \"n\": \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" } ] }, \"scope\": [ \"openid\", \"profile\", \"email\" ], \"grant_types\": [ \"authorization_code\" ], \"response_types\": [ \"code\", \"token\", \"id_token\" ], \"redirect_uris\": [ https://<YOUR_DOMAIN>/jans-auth-rp/home.htm ] }' Response: { \"allow_spontaneous_scopes\" : false , \"jwks\" : { \"keys\" : [ { \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"kid\" : \"your-kid\" , \"alg\" : \"RS256\" , \"n\" : \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" } ] }, \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/register?client_id=d16994c2-313c-4440-9713-25290fbb89a9\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"93a52334-bf79-4414-bc9a-983b6921597c\" , \"client_id\" : \"d16994c2-313c-4440-9713-25290fbb89a9\" , \"token_endpoint_auth_method\" : \"self_signed_tls_client_auth\" , \"scope\" : \"email openid profile\" , \"client_secret\" : \"e1c9e9df-e542-4225-adb4-d0590f85d97d\" , \"client_id_issued_at\" : 1698114939 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"client_name\" : \"Test Client mTLS\" , \"par_lifetime\" : 600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : true , \"grant_types\" : [ \"implicit\" , \"refresh_token\" , \"authorization_code\" ], \"subject_type\" : \"pairwise\" , \"additional_token_endpoint_auth_methods\" : [], \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris\" : [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1698201339 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" , \"id_token\" , \"token\" ] } NOTE: To obtain the jwks field data, follow the next step. P12 to JWKS # To get the fields from jwks you can use the following command: openssl x509 -in example-cli.p12 -pubkey -noout | pem-jwk | jq '{kid: \"your-kid\", kty: .kty , alg: \"RS256\" , use: \"sig\", e: .e, n: .n }' Make sure you have pem-jwk installed, use the command: npm install -g pem-jwk or yarn global add pem-jwk . Below is a sample run of the command. root@jans:~# openssl x509 -in example-cli.p12 -pubkey -noout | pem-jwk | jq '{kid: \"your-kid\", kty: .kty , alg: \"RS256\" , use: \"sig\", e: .e, n: .n }' Enter pass phrase for PKCS12 import pass phrase: { \"kid\": \"your-kid\", \"kty\": \"RSA\", \"alg\": \"RS256\", \"use\": \"sig\", \"e\": \"AQAB\", \"n\": \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" } 2. Call authorize endpoint # From your browser of choice call the following url: https://<YOUR_DOMAIN>/jans-auth/restv1/authorize?response_type=code&client_id=d16994c2-313c-4440-9713-25290fbb89a9&scope=openid+profil+email&redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm&state=f9bb35cb-3485-4ae4-aa8e-63e9a97b6e5d&nonce=4a2f07cb-521b-465c-8b06-0c17711a96a7 URL parameters: response_type=code client_id=d16994c2-313c-4440-9713-25290fbb89a9 scope=openid+profil+email redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm state=f9bb35cb-3485-4ae4-aa8e-63e9a97b6e5d nonce=4a2f07cb-521b-465c-8b06-0c17711a96a7 The field we need to obtain is the code . 3. Call token endpoint # Previously we have obtained the code field, we will use this value to call the endpoint token . curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/token' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=authorization_code' \\ --data-urlencode 'redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm' \\ --data-urlencode 'client_id=d16994c2-313c-4440-9713-25290fbb89a9' \\ --data-urlencode 'client_secret=<YOUR_CLIENT_SECRET>' \\ --data-urlencode 'code=<YOUR_CODE>' Response: { \"access_token\" : \"eyJraWQiOiJjb25uZWN0X2NmNjBiZWZmLTU1MzUtNDllNS04MWQ5LTM5ZDM4ZmNlMWNhMF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJNSGdqa2hnTktmZWF4ZUVEY0wycEt5c1EwVUQ4RDk1QUd5NFBGXzI2cmlnIiwiY29kZSI6ImE0NWE5ODI5LTFkMDQtNGQxNS05NjllLWRiMjk3Mzk4ZTdjMyIsImlzcyI6Imh0dHBzOi8vbWlsdG9uLWNoLWhhcmR5LW1pdGUuZ2x1dS5pbmZvIiwidG9rZW5fdHlwZSI6IkJlYXJlciIsImNsaWVudF9pZCI6IjVkODM1NDA3LTFlZjMtNDQxZC04YWU2LTZiYmRkNTcyNzZjYyIsImF1ZCI6IjVkODM1NDA3LTFlZjMtNDQxZC04YWU2LTZiYmRkNTcyNzZjYyIsImFjciI6ImJhc2ljIiwieDV0I1MyNTYiOiJPeHRJQXRBMEMwTkwteTR2UmZLeDd6TExFZXhfWG1DelduUWJ4ejZUem5ZIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsImVtYWlsIl0sImF1dGhfdGltZSI6MTY5ODE5NDczNiwiZXhwIjoxNjk4Mjc4MDQzLCJpYXQiOjE2OTgxOTY4MzIsInVzZXJuYW1lIjoiRGVmYXVsdCBBZG1pbiBVc2VyIn0.JpK7JYy6Avui3LNbxTKBYJW9fqjEIqijCXPw9fvqEO1kqO7AUozOEof00hPKzJo1Dh7VgGpY89MiAduDUoU3QCemtFsNSd1DCyExl2s3w5OF2mUm6nMzjaS377ZQQ39DAq91OGFFq_ISt4JIhWRf7_xUEvlLRAttTqxE5qp1ZYvgAYu07jbVJX8WqJvxYz3rZ3J-4kq2FLREunRf5KxYaHO-oKzrmhRVPTc_cj1vqwSfu8vRjLmx4P-eN7SgVNa0XmZ8WClLnmchucGBH6rYq3bXZWsOKixwLhno_2vPe1MmbK3XnNNBu_fm_bL2N5kgAwr9b-upoBJc08IyCje1vA\" , \"refresh_token\" : \"1e58e2c9-4175-4b3f-8170-65544b1a7c48\" , \"id_token\" : \"eyJraWQiOiJjb25uZWN0X2NmNjBiZWZmLTU1MzUtNDllNS04MWQ5LTM5ZDM4ZmNlMWNhMF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoib1NoVDE4YUdRVHdtNXBjT255dkNMUSIsInN1YiI6Ik1IZ2praGdOS2ZlYXhlRURjTDJwS3lzUTBVRDhEOTVBR3k0UEZfMjZyaWciLCJhbXIiOlsiMTAiXSwiaXNzIjoiaHR0cHM6Ly9taWx0b24tY2gtaGFyZHktbWl0ZS5nbHV1LmluZm8iLCJub25jZSI6ImMxNGQ2Y2RlLWQ5NTYtNDM4Zi04Mzk5LTQ3MzdkNWZlOTkyOSIsInNpZCI6IjI2ZTM4YTJmLTEzZTktNGY4Yi05MzdjLTQ3M2ViMjdlNzFkNiIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiNWQ4MzU0MDctMWVmMy00NDFkLThhZTYtNmJiZGQ1NzI3NmNjIiwicmFuZG9tIjoiMjVhZDViMmUtMGNkMi00Mjg3LTg1M2ItZWY3NWRhZjMzNWMwIiwiYWNyIjoiYmFzaWMiLCJjX2hhc2giOiJwM2ZJVHlGT09fd0tRZW9QT1VkWWF3IiwiYXV0aF90aW1lIjoxNjk4MTk0NzM2LCJleHAiOjE2OTgyMDA0MzIsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNjk4MTk2ODMyfQ.GMXkiFGcCy6dXI8gPPuCLd977Gs_rkG1w3FrNx_HlSnmcDUSsEQHvPxpA99Y3L8Z82uLHYCbP5Vga6iCEOmBBHnu9jEsmYgp-TSrB31HV-5g7-o4ZWJG05SdL9KgSP3PyDXRqcE0VFxBJ-uJSyvI-htQ4GUXMIhqVhbJJynPNosXtZvvDVIw1NBThupmqx58cozf5tIdnwaeiuN_Ce2XQrjZBiachI6KWFa-Mstrsdw1E6Ny_4bP-1UmeNgScd6pmIUemGsfclxIAgO0lACqgbGh7wo0PljbhEkGU_i9kP--0KJHkBkUxflULW3aAqdYtG9hEr_JEIddHVxXbi1c_w\" , \"token_type\" : \"Bearer\" , \"expires_in\" : 81210 } Once we have obtained the access_token in jwt(json web token) format, we will do the last step. 4. Call introspection endpoint # Run below command: curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/introspection' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --header 'Authorization: Bearer <ACCESS_TOKEN>' \\ --data-urlencode 'token=<ACCESS_TOKEN>' \\ --data-urlencode 'response_as_jwt=false' Response: { \"sub\" : \"MHgjkhgNKfeaxeEDcL2pKysQ0UD8D95AGy4PF_26rig\" , \"iss\" : \"https://<YOUR_DOMAIN>\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"d16994c2-313c-4440-9713-25290fbb89a9\" , \"aud\" : \"5d835407-1ef3-441d-8ae6-6bbdd57276cc\" , \"acr\" : \"basic\" , \"nbf\" : null , \"scope\" : \"openid profile email\" , \"auth_time\" : 1698194736 , \"cnf\" : { \"x5t#S256\" : \"OxtIAtA0C0NL-y4vRfKx7zLLEex_XmCzWnQbxz6TznY\" }, \"exp\" : 1698278043 , \"iat\" : 1698201265 , \"jti\" : null , \"username\" : \"admin\" } Specification document # For more details of the specification, you can have a look at the following link OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens", "title": "MTLS"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#mtls-mutual-transport-layer-security", "text": "", "title": "mTLS (Mutual Transport Layer Security)"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#what-is-mtls", "text": "mTLS is a process that establishes an encrypted TLS connection in which both parties use X.509 digital certificates to authenticate each other. mTLS can help mitigate the risk of moving services to the cloud and can help prevent malicious third parties from imitating genuine apps.", "title": "What Is mTLS?"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#where-is-mtls-useful", "text": "Mutual client certificate authentication can be used any time the server needs to ensure the authenticity and validity of either a specific user or a specific device. For example, a client certificate can be issued to a company-owned laptop to identify and authorize it on a corporate network. Alternatively, a client certificate could be issued to an employee and stored on a smart card, which then allows the employee to gain access to applications or restricted areas of a building. In practice, mTLS can identify and authorize the following: Devices onto a corporate network. Users into applications. Content delivery network (CDNs) or cloud security services to back-end web servers. Business-to-business (B2B) data exchanges that use APIs. Internet of Things (IoT) sensors, such as remote traffic cameras. Microservice architectures in which each microservice must ensure that each component it communicates with is valid and not tampered with.", "title": "Where Is mTLS Useful?"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#mtls-in-jans-auth", "text": "Jans Auth supports mTLS , and to configure it we must take these considerations into account: During DCR client registration, the token_endpoint_auth_method field can receive 2 new values: tls_client_auth : indicates that client authentication to the authorization server will occur with mutual TLS utilizing the PKI method of associating a certificate to a client. self_signed_tls_client_auth : Indicates that client authentication to the authorization server will occur using mutual TLS with the client utilizing a self-signed certificate. There is new client property tls_client_auth_subject_dn used to compare Subject DN of the certificate with configured value of client entry when authentication method is set to tls_client_auth (saved in tls_client_auth_subject_dn or oxAttributes on persistence layer). If MTLS Authentication is used then access_token automatically saves certificate S256 hash of certificates which can be validated by RP. If access_token is JWT then x5t#S256 claim is added to payload of the token. Otherwise, token can be introspected. { \"active\": true, \"iss\": \"https://server.example.com\", \"sub\": \"ty.webb@example.com\", \"exp\": 1493726400, \"nbf\": 1493722800, \"cnf\": { \"x5t#S256\": \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" }, ..., ... }", "title": "mTLS in Jans Auth"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#configuring-apache-for-mtls", "text": "The information below belongs to apache and web client (usually web browser) mutual authentication setup method. This also includes basic checks to be performed for the setup. Is mod_ssl installed: Run below command to confirm if the ssl module is installed. apachectl -M | grep ssl If we get ssl_module related output, then we're good to proceed. The output could look like: root@jans:~# apachectl -M | grep ssl ssl_module (shared) Usually third party or Certbot SSL certs are used for web server ssl connections. In that case no extra configuration is necessary. But if we want to use self-signed certs, then follow on.", "title": "Configuring Apache for mTLS"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#self-signed-ssl-certs", "text": "", "title": "Self-Signed SSL Certs"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#server-side-mtls-setup", "text": "Now, we're covering the case if you want to deploy your own CA Cert.", "title": "Server-Side mTLS setup"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#1-open-terminal", "text": "", "title": "1. Open Terminal."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#2-create-a-new-directory-to-generate-certificates", "text": "mkdir /etc/certs/mtlscert Change to the directory created. cd /etc/certs/mtlscert", "title": "2. Create a new directory to generate certificates."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#3-generate-self-signed-ca-cert", "text": "Run below command: openssl req -newkey rsa:2048 -nodes -keyform PEM -keyout example-ca.key -x509 -days 3650 -outform PEM -out example-ca.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -newkey rsa:2048 -nodes -keyform PEM -keyout example-ca.key -x509 -days 3650 -outform PEM -out example-ca.crt Generating a RSA private key .........................................+++++ .........................................+++++ writing new private key to 'example-ca.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Above command will create two files: example-ca.key and example-ca.crt . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key", "title": "3. Generate Self-Signed CA Cert."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#4-generate-private-key", "text": "Run below command: openssl genrsa -out example.key 2048 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl genrsa -out example.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ......................................+++++ ..........................................................................................................+++++ e is 65537 (0x010001) Above command creates: example.key . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.key", "title": "4. Generate private key."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#5-generate-a-server-csr-certificate-signing-request", "text": "Run below command: openssl req -new -key example.key -out example.csr Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -new -key example.key -out example.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Above command will create the file: example.csr . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.csr example.key", "title": "5. Generate a server CSR (Certificate Signing Request):"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#6-sign-the-csr-examplecsr-we-just-generated", "text": "Run below command: openssl x509 -req -in example.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 100 -days 365 -outform PEM -out example.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl x509 -req -in example.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 100 -days 365 -outform PEM -out example.crt Signature ok subject=C = US, ST = Austin, L = TX, O = Janssen Org., OU = IT, CN = yourdomain.com, emailAddress = youremail@yourdomain.com Getting CA Private Key Above command will create the file: example.crt for 365 days. root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.crt example.csr example.key", "title": "6. Sign the CSR example.csr we just generated."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#7-configure-apache2", "text": "Add the following lines in the /etc/apache2/sites-available/https_jans.conf file. SSLEngine On SSLCertificateFile /etc/certs/mtlscert/example.crt SSLCertificateKeyFile /etc/certs/mtlscert/example.key SSLCACertificateFile /etc/certs/mtlscert/example-ca.crt It is critical to configure certificates validation on Apache 2 correctly, since actual validation of the certificates is performed by Apache 2. After Apache certificate validation is configured correctly, make sure there is client certificate forward to jans-auth application. jans-auth (AS) expects certificate in X-ClientCert header. <LocationMatch /jans-auth> SSLVerifyClient require SSLVerifyDepth 10 SSLOptions -StdEnvVars +ExportCertData # Forward certificate to destination server (oxauth) RequestHeader set X-ClientCert %{SSL_CLIENT_CERT}s </LocationMatch> Now we must restart the Apache2 server. service apache2 restart To check if SSL cert on apache works: openssl s_client -connect yourdomain.com:443", "title": "7. Configure Apache2."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#client-side-mtls-setup", "text": "", "title": "Client-Side mTLS setup"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#1-generate-private-key", "text": "Run below command: openssl genrsa -out example-cli.key 2048 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl genrsa -out example-cli.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ...........................................+++++ .............................................+++++ e is 65537 (0x010001) Above command will create the file: example-cli.key . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.key example.crt example.csr example.key", "title": "1. Generate private key."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#2-generate-a-client-csr-certificate-signing-request", "text": "Run below command: openssl req -new -key example-cli.key -out example-cli.csr Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -new -key example-cli.key -out example-cli.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Client Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Above command will create the file: example-cli.csr . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.csr example-cli.key example.crt example.csr example.key", "title": "2. Generate a client CSR (Certificate Signing Request)."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#3-sign-the-csr-example-clicsr-we-just-generated", "text": "Run below command: openssl x509 -req -in example-cli.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 101 -days 365 -outform PEM -out example-cli.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl x509 -req -in example-cli.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 101 -days 365 -outform PEM -out example-cli.crt Signature ok subject=C = US, ST = Austin, L = TX, O = Janssen Client Org., OU = IT, CN = yourdomain.com, emailAddress = youremail@yourdomain.com Getting CA Private Key Above command will create the file: example-cli.crt for 365 days. root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.crt example-cli.csr example-cli.key example.crt example.csr example.key", "title": "3. Sign the CSR example-cli.csr we just generated."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#4-generate-pkcs12-cert", "text": "Some browsers need client certs to be in the format pkcs12 . Run below command: openssl pkcs12 -export -inkey example-cli.key -in example-cli.crt -out example-cli.p12 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl pkcs12 -export -inkey example-cli.key -in example-cli.crt -out example-cli.p12 Enter Export Password: Verifying - Enter Export Password: Above command will create the file: example-cli.p12 . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.crt example-cli.csr example-cli.key example-cli.p12 example.crt example.csr example.key", "title": "4. Generate PKCS12 cert"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#mtls-testing", "text": "We are going to run an mTLS example where we will perform the following flow: Register new client. Call authorize endpoint. Call token endpoint. Call introspection endpoint. Previously we need to configure the client's certificate in the browser of your choice.", "title": "mTLS testing"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#google-chrome-settings", "text": "In the search bar go to chrome://settings/certificates . In the Your Certificates section, click on Import button. Select the certificate example-cli.p12 and enter the password you set when generating it.", "title": "Google Chrome Settings"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#firefox-settings", "text": "In the search bar go to about:preferences#privacy . Click on View Certificates . In the Your Certificates section, click on Import button. Select the certificate example-cli.p12 and enter the password you set when generating it.", "title": "Firefox Settings"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#solving-the-curl-problem", "text": "If you have openssl version 3.x.x , most likely when you are trying to consume the /.well-known/openid-configuration endpoint. curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' You will get the following error: root@jans~# curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' curl: (58) could not parse PKCS12 file, check password, OpenSSL error error:0308010C:digital envelope routines::unsupported To fix this error, edit the file /etc/ssl/openssl.cnf and make sure that these lines are uncommented and if they are not, add them: openssl_conf = openssl_init [openssl_init] providers = provider_sect [provider_sect] default = default_sect legacy = legacy_sect [default_sect] activate = 1 [legacy_sect] activate = 1 Once this change is done, you should be able to consume the /.well-known/openid-configuration endpoint without any problems root@jans~# curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : true, \"issuer\" : \"https://<YOUR_DOMAIN>\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/authorize\", ..., ..., ... }", "title": "Solving the curl problem"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#1-register-new-client", "text": "Run below command: curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/register' \\ --header 'Content-Type: application/json' \\ --data '{ \"client_name\": \"Test Client mTLS\", \"application_type\": \"web\", \"access_token_as_jwt\": true, \"token_endpoint_auth_method\": \"self_signed_tls_client_auth\", \"jwks\": { \"keys\": [ { \"kid\": \"YOUR_KID\", \"kty\": \"RSA\", \"alg\": \"RS256\", \"use\": \"sig\", \"e\": \"AQAB\", \"n\": \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" } ] }, \"scope\": [ \"openid\", \"profile\", \"email\" ], \"grant_types\": [ \"authorization_code\" ], \"response_types\": [ \"code\", \"token\", \"id_token\" ], \"redirect_uris\": [ https://<YOUR_DOMAIN>/jans-auth-rp/home.htm ] }' Response: { \"allow_spontaneous_scopes\" : false , \"jwks\" : { \"keys\" : [ { \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"kid\" : \"your-kid\" , \"alg\" : \"RS256\" , \"n\" : \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" } ] }, \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/register?client_id=d16994c2-313c-4440-9713-25290fbb89a9\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"93a52334-bf79-4414-bc9a-983b6921597c\" , \"client_id\" : \"d16994c2-313c-4440-9713-25290fbb89a9\" , \"token_endpoint_auth_method\" : \"self_signed_tls_client_auth\" , \"scope\" : \"email openid profile\" , \"client_secret\" : \"e1c9e9df-e542-4225-adb4-d0590f85d97d\" , \"client_id_issued_at\" : 1698114939 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"client_name\" : \"Test Client mTLS\" , \"par_lifetime\" : 600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : true , \"grant_types\" : [ \"implicit\" , \"refresh_token\" , \"authorization_code\" ], \"subject_type\" : \"pairwise\" , \"additional_token_endpoint_auth_methods\" : [], \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris\" : [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1698201339 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" , \"id_token\" , \"token\" ] } NOTE: To obtain the jwks field data, follow the next step.", "title": "1. Register new client"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#p12-to-jwks", "text": "To get the fields from jwks you can use the following command: openssl x509 -in example-cli.p12 -pubkey -noout | pem-jwk | jq '{kid: \"your-kid\", kty: .kty , alg: \"RS256\" , use: \"sig\", e: .e, n: .n }' Make sure you have pem-jwk installed, use the command: npm install -g pem-jwk or yarn global add pem-jwk . Below is a sample run of the command. root@jans:~# openssl x509 -in example-cli.p12 -pubkey -noout | pem-jwk | jq '{kid: \"your-kid\", kty: .kty , alg: \"RS256\" , use: \"sig\", e: .e, n: .n }' Enter pass phrase for PKCS12 import pass phrase: { \"kid\": \"your-kid\", \"kty\": \"RSA\", \"alg\": \"RS256\", \"use\": \"sig\", \"e\": \"AQAB\", \"n\": \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" }", "title": "P12 to JWKS"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#2-call-authorize-endpoint", "text": "From your browser of choice call the following url: https://<YOUR_DOMAIN>/jans-auth/restv1/authorize?response_type=code&client_id=d16994c2-313c-4440-9713-25290fbb89a9&scope=openid+profil+email&redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm&state=f9bb35cb-3485-4ae4-aa8e-63e9a97b6e5d&nonce=4a2f07cb-521b-465c-8b06-0c17711a96a7 URL parameters: response_type=code client_id=d16994c2-313c-4440-9713-25290fbb89a9 scope=openid+profil+email redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm state=f9bb35cb-3485-4ae4-aa8e-63e9a97b6e5d nonce=4a2f07cb-521b-465c-8b06-0c17711a96a7 The field we need to obtain is the code .", "title": "2. Call authorize endpoint"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#3-call-token-endpoint", "text": "Previously we have obtained the code field, we will use this value to call the endpoint token . curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/token' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=authorization_code' \\ --data-urlencode 'redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm' \\ --data-urlencode 'client_id=d16994c2-313c-4440-9713-25290fbb89a9' \\ --data-urlencode 'client_secret=<YOUR_CLIENT_SECRET>' \\ --data-urlencode 'code=<YOUR_CODE>' Response: { \"access_token\" : \"eyJraWQiOiJjb25uZWN0X2NmNjBiZWZmLTU1MzUtNDllNS04MWQ5LTM5ZDM4ZmNlMWNhMF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJNSGdqa2hnTktmZWF4ZUVEY0wycEt5c1EwVUQ4RDk1QUd5NFBGXzI2cmlnIiwiY29kZSI6ImE0NWE5ODI5LTFkMDQtNGQxNS05NjllLWRiMjk3Mzk4ZTdjMyIsImlzcyI6Imh0dHBzOi8vbWlsdG9uLWNoLWhhcmR5LW1pdGUuZ2x1dS5pbmZvIiwidG9rZW5fdHlwZSI6IkJlYXJlciIsImNsaWVudF9pZCI6IjVkODM1NDA3LTFlZjMtNDQxZC04YWU2LTZiYmRkNTcyNzZjYyIsImF1ZCI6IjVkODM1NDA3LTFlZjMtNDQxZC04YWU2LTZiYmRkNTcyNzZjYyIsImFjciI6ImJhc2ljIiwieDV0I1MyNTYiOiJPeHRJQXRBMEMwTkwteTR2UmZLeDd6TExFZXhfWG1DelduUWJ4ejZUem5ZIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsImVtYWlsIl0sImF1dGhfdGltZSI6MTY5ODE5NDczNiwiZXhwIjoxNjk4Mjc4MDQzLCJpYXQiOjE2OTgxOTY4MzIsInVzZXJuYW1lIjoiRGVmYXVsdCBBZG1pbiBVc2VyIn0.JpK7JYy6Avui3LNbxTKBYJW9fqjEIqijCXPw9fvqEO1kqO7AUozOEof00hPKzJo1Dh7VgGpY89MiAduDUoU3QCemtFsNSd1DCyExl2s3w5OF2mUm6nMzjaS377ZQQ39DAq91OGFFq_ISt4JIhWRf7_xUEvlLRAttTqxE5qp1ZYvgAYu07jbVJX8WqJvxYz3rZ3J-4kq2FLREunRf5KxYaHO-oKzrmhRVPTc_cj1vqwSfu8vRjLmx4P-eN7SgVNa0XmZ8WClLnmchucGBH6rYq3bXZWsOKixwLhno_2vPe1MmbK3XnNNBu_fm_bL2N5kgAwr9b-upoBJc08IyCje1vA\" , \"refresh_token\" : \"1e58e2c9-4175-4b3f-8170-65544b1a7c48\" , \"id_token\" : \"eyJraWQiOiJjb25uZWN0X2NmNjBiZWZmLTU1MzUtNDllNS04MWQ5LTM5ZDM4ZmNlMWNhMF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoib1NoVDE4YUdRVHdtNXBjT255dkNMUSIsInN1YiI6Ik1IZ2praGdOS2ZlYXhlRURjTDJwS3lzUTBVRDhEOTVBR3k0UEZfMjZyaWciLCJhbXIiOlsiMTAiXSwiaXNzIjoiaHR0cHM6Ly9taWx0b24tY2gtaGFyZHktbWl0ZS5nbHV1LmluZm8iLCJub25jZSI6ImMxNGQ2Y2RlLWQ5NTYtNDM4Zi04Mzk5LTQ3MzdkNWZlOTkyOSIsInNpZCI6IjI2ZTM4YTJmLTEzZTktNGY4Yi05MzdjLTQ3M2ViMjdlNzFkNiIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiNWQ4MzU0MDctMWVmMy00NDFkLThhZTYtNmJiZGQ1NzI3NmNjIiwicmFuZG9tIjoiMjVhZDViMmUtMGNkMi00Mjg3LTg1M2ItZWY3NWRhZjMzNWMwIiwiYWNyIjoiYmFzaWMiLCJjX2hhc2giOiJwM2ZJVHlGT09fd0tRZW9QT1VkWWF3IiwiYXV0aF90aW1lIjoxNjk4MTk0NzM2LCJleHAiOjE2OTgyMDA0MzIsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNjk4MTk2ODMyfQ.GMXkiFGcCy6dXI8gPPuCLd977Gs_rkG1w3FrNx_HlSnmcDUSsEQHvPxpA99Y3L8Z82uLHYCbP5Vga6iCEOmBBHnu9jEsmYgp-TSrB31HV-5g7-o4ZWJG05SdL9KgSP3PyDXRqcE0VFxBJ-uJSyvI-htQ4GUXMIhqVhbJJynPNosXtZvvDVIw1NBThupmqx58cozf5tIdnwaeiuN_Ce2XQrjZBiachI6KWFa-Mstrsdw1E6Ny_4bP-1UmeNgScd6pmIUemGsfclxIAgO0lACqgbGh7wo0PljbhEkGU_i9kP--0KJHkBkUxflULW3aAqdYtG9hEr_JEIddHVxXbi1c_w\" , \"token_type\" : \"Bearer\" , \"expires_in\" : 81210 } Once we have obtained the access_token in jwt(json web token) format, we will do the last step.", "title": "3. Call token endpoint"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#4-call-introspection-endpoint", "text": "Run below command: curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/introspection' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --header 'Authorization: Bearer <ACCESS_TOKEN>' \\ --data-urlencode 'token=<ACCESS_TOKEN>' \\ --data-urlencode 'response_as_jwt=false' Response: { \"sub\" : \"MHgjkhgNKfeaxeEDcL2pKysQ0UD8D95AGy4PF_26rig\" , \"iss\" : \"https://<YOUR_DOMAIN>\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"d16994c2-313c-4440-9713-25290fbb89a9\" , \"aud\" : \"5d835407-1ef3-441d-8ae6-6bbdd57276cc\" , \"acr\" : \"basic\" , \"nbf\" : null , \"scope\" : \"openid profile email\" , \"auth_time\" : 1698194736 , \"cnf\" : { \"x5t#S256\" : \"OxtIAtA0C0NL-y4vRfKx7zLLEex_XmCzWnQbxz6TznY\" }, \"exp\" : 1698278043 , \"iat\" : 1698201265 , \"jti\" : null , \"username\" : \"admin\" }", "title": "4. Call introspection endpoint"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#specification-document", "text": "For more details of the specification, you can have a look at the following link OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens", "title": "Specification document"}, {"location": "janssen-server/auth-server/oauth-features/par/", "tags": ["administration", "auth-server", "oauth", "feature", "par"], "text": "Pushed Authorization Request (PAR) # Pushed Authorization Request (PAR) allows to push the payload of an OAuth 2.0 authorization request to the authorization server via a direct request and provides back with a request URI that is used as reference to the data in a subsequent call to the authorization endpoint. For more information and implementation details please check PAR Endpoint documentation PAR specification Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "PAR"}, {"location": "janssen-server/auth-server/oauth-features/par/#pushed-authorization-request-par", "text": "Pushed Authorization Request (PAR) allows to push the payload of an OAuth 2.0 authorization request to the authorization server via a direct request and provides back with a request URI that is used as reference to the data in a subsequent call to the authorization endpoint. For more information and implementation details please check PAR Endpoint documentation PAR specification", "title": "Pushed Authorization Request (PAR)"}, {"location": "janssen-server/auth-server/oauth-features/par/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/oauth-features/par/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/oauth-features/password-grant/", "tags": ["administration", "auth-server", "oauth", "feature", "grant", "password"], "text": "Password Grant # Janssen Server supports the password grant. At the same time, inline with OAuth 2.0 security best practices , this password grant should never be used in practice. OAuth 2.1 has removed this grant type. Configuration # A client can use the password grant if it is enabled in the configuration. An administrator can use TUI to enable password grant for a client. Usage # Using the password grant involves sharing user credentials with a third-party application. This third-party app which has registered with Janssen Server as a client, will then use user-id/password credentials from the user to obtain an access token from Janssen Server. Janssen Server also requires the client to authenticate itself based on the client configuration. Since sharing user credentials with a third-party app is a security risk and against the basic purpose of OAuth, this grant type shall not be used. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Password Grant"}, {"location": "janssen-server/auth-server/oauth-features/password-grant/#password-grant", "text": "Janssen Server supports the password grant. At the same time, inline with OAuth 2.0 security best practices , this password grant should never be used in practice. OAuth 2.1 has removed this grant type.", "title": "Password Grant"}, {"location": "janssen-server/auth-server/oauth-features/password-grant/#configuration", "text": "A client can use the password grant if it is enabled in the configuration. An administrator can use TUI to enable password grant for a client.", "title": "Configuration"}, {"location": "janssen-server/auth-server/oauth-features/password-grant/#usage", "text": "Using the password grant involves sharing user credentials with a third-party application. This third-party app which has registered with Janssen Server as a client, will then use user-id/password credentials from the user to obtain an access token from Janssen Server. Janssen Server also requires the client to authenticate itself based on the client configuration. Since sharing user credentials with a third-party app is a security risk and against the basic purpose of OAuth, this grant type shall not be used.", "title": "Usage"}, {"location": "janssen-server/auth-server/oauth-features/password-grant/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/oauth-features/pkce/", "tags": ["administration", "auth-server", "oauth", "feature", "pkce"], "text": "PKCE (Proof Key for Code Exchange) # PKCE(Proof Key for Code Exchange) is an extension to the Authorization on Code flow to prevent CSRF and authorization code injection attacks. Authorization code flow with PKCE is defined in this specification. Public clients ( Single Page Apps (SPA) or Mobile Apps ), have a serious problem obtaining access tokens. In the case of SPA you cannot securely store a secret key, because its source is available in the browser. The same will happen with Mobile Apps , since decompiling the application will reveal the secret keys. This is where PKCE comes in to solve the problem. The authorization code flow with PKCE is considered as best practice when using Single Page Apps (SPA) or Mobile Apps . Let's see in the following diagram how it works: Source PKCE Configuration # For this flow to work, we must make the following configuration in Janssen Server. We need to set the clientAuthenticationFiltersEnabled property to false , it defaults to true . We can use TUI to change this configuration as shown below: Authorization Code Flow + PKCE # In this flow, we will execute the following steps: Generate Code Verifier and Code Challenge Register new client Call authorize endpoint Call token endpoint 1. Generate Code Verifier and Code Challenge # It is necessary to generate these codes for this flow, since this data will be sent in the authorize and token endpoints. Code Verifier # The It is a random string of length N , and is denoted by the field code_verifier . The following command generates a code_verifier of length 128 . tr -dc 'A-Za-z0-9-._' </dev/urandom | head -c 128 ; echo Output example: root@jans:~# tr -dc 'A-Za-z0-9-._' </dev/urandom | head -c 128 ; echo MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr Code Challenge # To generate the code_challenge we need to know what type of method we will be using, so this field is accompanied by the code_challenge_method field. Janssen Server supports two methods of code_challenge_method : plain : When using this method, the code_challenge is the same as the code_verifier . s256 : When using this method, code_challenge must be encoded using the code_verifier with sha256 and * base64Url *. The following command generates the code_challenge using s256 . Note To execute command the command below, you need to have openssl , basenc and tr installed. echo -n \"MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr\" | openssl dgst -binary -sha256 | basenc --base64url | tr -d '=' Output example: root@jans:~# echo -n \"MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr\" | openssl dgst -binary -sha256 | basenc --base64url | tr -d '=' zyI60XbvMetJJuAzyRR_jnxoJkyfxXSqY-mTG4FtBtg 2. Register new client # Request POST <YOUR_DOMAIN>/jans-auth/restv1/register HTTP/1.1 Content-Type: application/json { \"client_name\": \"PKCE Test Client\", \"application_type\": \"web\", \"token_endpoint_auth_method\": \"none\", \"scope\": [ \"openid\", \"profile\", \"email\" ], \"grant_types\": [ \"authorization_code\" ], \"response_types\": [ \"code\", \"token\", \"id_token\" ], \"redirect_uris\": [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ] } Note Notee that the token_endpoint_auth_method field is none . Response HTTP/1.1 201 Created Date: Fri, 17 Nov 2023 22:51:13 GMT Server: Apache/2.4.41 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Expires: Thu, 01 Jan 1970 00:00:00 GMT Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1541 Set-Cookie: X-Correlation-Id=d92eddf5-ab08-4b4f-a8f1-10af67e83dbd; Secure; HttpOnly;HttpOnly Connection: close { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://<YOUR_DOMAIN>/jans-auth/restv1/register?client_id=057c3abf-a1a7-49cc-9e4e-8737e898ac72\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"659ccbf9-ac98-437a-b952-33bfc0366fc2\", \"client_id\": \"f48fbdfa-4c07-49e5-938b-10463980e145\", \"token_endpoint_auth_method\": \"none\", \"scope\": \"email openid profile\", \"client_secret\": \"a656a654-c930-4b52-9edb-68ead50d046e\", \"client_id_issued_at\": 1700261473, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"PKCE Test Client\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"implicit\", \"refresh_token\", \"authorization_code\" ], \"subject_type\": \"pairwise\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1700347873, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"token\", \"id_token\" ] } 3. Call authorize endpoint # From your browser of choice call the following url: Request https://<YOUR_DOMAIN>/jans-auth/restv1/authorize? response_type=code& client_id=f48fbdfa-4c07-49e5-938b-10463980e145& scope=openid+profile+email& redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm& state=bf1af4a1-8713-49c6-b229-537bf4cf712d& nonce=f2265e46-6d93-4d36-850b-8fd990cccd04& code_challenge=<YOUR_CODE_CHALLENGE>& code_challenge_method=<YOUR_CODE_CHALLENGE_METHOD> Note Remember that this endpoint is where you must send the code_challenge and code_challenge_method parameters. The field we need to obtain is the code . 4. Call token endpoint # Previously we have obtained the code field, we will use this value to call the endpoint token . Request POST <YOUR_DOMAIN>/jans-auth/restv1/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded grant_type=authorization_code& redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm& client_id=f48fbdfa-4c07-49e5-938b-10463980e145& code_verifier=<YOUR_CODE_VERIFIER>& code=<YOUR_CODE> Response { \"access_token\" : \"38abc903-9a68-48f9-9ccc-bf1b50fe8152\" , \"refresh_token\" : \"e945e8ab-19c1-4073-b3c1-913bb090459a\" , \"id_token\" : \"eyJraWQiOiJjb25uZWN0XzZmZmJkZTQ3LTU5MDgtNDljMy04MGVkLTFjODNhNGEyNWJmOF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiTndiVXg2NlFaUzFvMG1SMmdyRGxKZyIsInN1YiI6IkcxM2ZtQ3RDQkJ0VDN5TzBMWUY0eng3X1ROUktZeGhGNUd6cGFYOUFiZlkiLCJhbXIiOlsiMTAiXSwiaXNzIjoiaHR0cHM6Ly9taWx0b24tY2gtaGFyZHktbWl0ZS5nbHV1LmluZm8iLCJub25jZSI6IjRlOWVhZjdjLWZlMjUtNDlkMC05OGU1LTM2ZTNjYzJhMWNiZCIsInNpZCI6IjIwZThmNTAzLWZmN2EtNGU3OS05OTY3LTUxMTU5NTk1N2JhYiIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiN2M3OGE0MmUtNTc4YS00OWE2LWExNzAtZTg1N2E0NWYzNTBjIiwicmFuZG9tIjoiZGU0NjE5NDEtNzIzOC00YjZjLWI2NTQtNjg2OTU0MmZlZjc3IiwiYWNyIjoiYmFzaWMiLCJjX2hhc2giOiJ1eFlZWDc5a3c2S2llX0NvaTZERi1RIiwiYXV0aF90aW1lIjoxNzAwMzYxMzA1LCJleHAiOjE3MDAzNjY5MjIsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNzAwMzYzMzIyfQ.IRgf6L4HsTHwgIGY_i3Af1dUnS-fLkMz8ND2r6Fgux-W7lkfQYXrpAqyEn-bUZ-L47PhaNWaLIV2bCl8Bxtbk1RhOS0-Sq8YnATkCgsSTCC5gtcZx42N67oQahoInSA4QuySdz1OAChZhlgUHRWn2bnAm07gCf7jfBdqRwCY11GcJrkR4n714tKcr5olxSDok2MJKmkbTi4VPfQXKfTYb7p-mMoqg3cr7w53IrEvQrOM94tYVJs1sUX_HGLwD99d1kRZN8SW2fMUxDsXw4hcDtnL4ktVp1rzc9tseGeu8tWzbNqQHESodOSPYqsl_SaPhuLip2FNFbStqJDc1vjnlg\" , \"token_type\" : \"Bearer\" , \"expires_in\" : 299 }", "title": "PKCE"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#pkce-proof-key-for-code-exchange", "text": "PKCE(Proof Key for Code Exchange) is an extension to the Authorization on Code flow to prevent CSRF and authorization code injection attacks. Authorization code flow with PKCE is defined in this specification. Public clients ( Single Page Apps (SPA) or Mobile Apps ), have a serious problem obtaining access tokens. In the case of SPA you cannot securely store a secret key, because its source is available in the browser. The same will happen with Mobile Apps , since decompiling the application will reveal the secret keys. This is where PKCE comes in to solve the problem. The authorization code flow with PKCE is considered as best practice when using Single Page Apps (SPA) or Mobile Apps . Let's see in the following diagram how it works: Source", "title": "PKCE (Proof Key for Code Exchange)"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#pkce-configuration", "text": "For this flow to work, we must make the following configuration in Janssen Server. We need to set the clientAuthenticationFiltersEnabled property to false , it defaults to true . We can use TUI to change this configuration as shown below:", "title": "PKCE Configuration"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#authorization-code-flow-pkce", "text": "In this flow, we will execute the following steps: Generate Code Verifier and Code Challenge Register new client Call authorize endpoint Call token endpoint", "title": "Authorization Code Flow + PKCE"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#1-generate-code-verifier-and-code-challenge", "text": "It is necessary to generate these codes for this flow, since this data will be sent in the authorize and token endpoints.", "title": "1. Generate Code Verifier and Code Challenge"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#code-verifier", "text": "The It is a random string of length N , and is denoted by the field code_verifier . The following command generates a code_verifier of length 128 . tr -dc 'A-Za-z0-9-._' </dev/urandom | head -c 128 ; echo Output example: root@jans:~# tr -dc 'A-Za-z0-9-._' </dev/urandom | head -c 128 ; echo MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr", "title": "Code Verifier"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#code-challenge", "text": "To generate the code_challenge we need to know what type of method we will be using, so this field is accompanied by the code_challenge_method field. Janssen Server supports two methods of code_challenge_method : plain : When using this method, the code_challenge is the same as the code_verifier . s256 : When using this method, code_challenge must be encoded using the code_verifier with sha256 and * base64Url *. The following command generates the code_challenge using s256 . Note To execute command the command below, you need to have openssl , basenc and tr installed. echo -n \"MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr\" | openssl dgst -binary -sha256 | basenc --base64url | tr -d '=' Output example: root@jans:~# echo -n \"MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr\" | openssl dgst -binary -sha256 | basenc --base64url | tr -d '=' zyI60XbvMetJJuAzyRR_jnxoJkyfxXSqY-mTG4FtBtg", "title": "Code Challenge"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#2-register-new-client", "text": "Request POST <YOUR_DOMAIN>/jans-auth/restv1/register HTTP/1.1 Content-Type: application/json { \"client_name\": \"PKCE Test Client\", \"application_type\": \"web\", \"token_endpoint_auth_method\": \"none\", \"scope\": [ \"openid\", \"profile\", \"email\" ], \"grant_types\": [ \"authorization_code\" ], \"response_types\": [ \"code\", \"token\", \"id_token\" ], \"redirect_uris\": [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ] } Note Notee that the token_endpoint_auth_method field is none . Response HTTP/1.1 201 Created Date: Fri, 17 Nov 2023 22:51:13 GMT Server: Apache/2.4.41 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Expires: Thu, 01 Jan 1970 00:00:00 GMT Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1541 Set-Cookie: X-Correlation-Id=d92eddf5-ab08-4b4f-a8f1-10af67e83dbd; Secure; HttpOnly;HttpOnly Connection: close { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://<YOUR_DOMAIN>/jans-auth/restv1/register?client_id=057c3abf-a1a7-49cc-9e4e-8737e898ac72\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"659ccbf9-ac98-437a-b952-33bfc0366fc2\", \"client_id\": \"f48fbdfa-4c07-49e5-938b-10463980e145\", \"token_endpoint_auth_method\": \"none\", \"scope\": \"email openid profile\", \"client_secret\": \"a656a654-c930-4b52-9edb-68ead50d046e\", \"client_id_issued_at\": 1700261473, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"PKCE Test Client\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"implicit\", \"refresh_token\", \"authorization_code\" ], \"subject_type\": \"pairwise\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1700347873, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"token\", \"id_token\" ] }", "title": "2. Register new client"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#3-call-authorize-endpoint", "text": "From your browser of choice call the following url: Request https://<YOUR_DOMAIN>/jans-auth/restv1/authorize? response_type=code& client_id=f48fbdfa-4c07-49e5-938b-10463980e145& scope=openid+profile+email& redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm& state=bf1af4a1-8713-49c6-b229-537bf4cf712d& nonce=f2265e46-6d93-4d36-850b-8fd990cccd04& code_challenge=<YOUR_CODE_CHALLENGE>& code_challenge_method=<YOUR_CODE_CHALLENGE_METHOD> Note Remember that this endpoint is where you must send the code_challenge and code_challenge_method parameters. The field we need to obtain is the code .", "title": "3. Call authorize endpoint"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#4-call-token-endpoint", "text": "Previously we have obtained the code field, we will use this value to call the endpoint token . Request POST <YOUR_DOMAIN>/jans-auth/restv1/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded grant_type=authorization_code& redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm& client_id=f48fbdfa-4c07-49e5-938b-10463980e145& code_verifier=<YOUR_CODE_VERIFIER>& code=<YOUR_CODE> Response { \"access_token\" : \"38abc903-9a68-48f9-9ccc-bf1b50fe8152\" , \"refresh_token\" : \"e945e8ab-19c1-4073-b3c1-913bb090459a\" , \"id_token\" : \"eyJraWQiOiJjb25uZWN0XzZmZmJkZTQ3LTU5MDgtNDljMy04MGVkLTFjODNhNGEyNWJmOF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiTndiVXg2NlFaUzFvMG1SMmdyRGxKZyIsInN1YiI6IkcxM2ZtQ3RDQkJ0VDN5TzBMWUY0eng3X1ROUktZeGhGNUd6cGFYOUFiZlkiLCJhbXIiOlsiMTAiXSwiaXNzIjoiaHR0cHM6Ly9taWx0b24tY2gtaGFyZHktbWl0ZS5nbHV1LmluZm8iLCJub25jZSI6IjRlOWVhZjdjLWZlMjUtNDlkMC05OGU1LTM2ZTNjYzJhMWNiZCIsInNpZCI6IjIwZThmNTAzLWZmN2EtNGU3OS05OTY3LTUxMTU5NTk1N2JhYiIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiN2M3OGE0MmUtNTc4YS00OWE2LWExNzAtZTg1N2E0NWYzNTBjIiwicmFuZG9tIjoiZGU0NjE5NDEtNzIzOC00YjZjLWI2NTQtNjg2OTU0MmZlZjc3IiwiYWNyIjoiYmFzaWMiLCJjX2hhc2giOiJ1eFlZWDc5a3c2S2llX0NvaTZERi1RIiwiYXV0aF90aW1lIjoxNzAwMzYxMzA1LCJleHAiOjE3MDAzNjY5MjIsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNzAwMzYzMzIyfQ.IRgf6L4HsTHwgIGY_i3Af1dUnS-fLkMz8ND2r6Fgux-W7lkfQYXrpAqyEn-bUZ-L47PhaNWaLIV2bCl8Bxtbk1RhOS0-Sq8YnATkCgsSTCC5gtcZx42N67oQahoInSA4QuySdz1OAChZhlgUHRWn2bnAm07gCf7jfBdqRwCY11GcJrkR4n714tKcr5olxSDok2MJKmkbTi4VPfQXKfTYb7p-mMoqg3cr7w53IrEvQrOM94tYVJs1sUX_HGLwD99d1kRZN8SW2fMUxDsXw4hcDtnL4ktVp1rzc9tseGeu8tWzbNqQHESodOSPYqsl_SaPhuLip2FNFbStqJDc1vjnlg\" , \"token_type\" : \"Bearer\" , \"expires_in\" : 299 }", "title": "4. Call token endpoint"}, {"location": "janssen-server/auth-server/openid-features/acrs/", "tags": ["administration", "auth-server", "openidc", "feature", "acr"], "text": "ACR # ACR(Authentication Context Class Reference) is defined by OpenId Connect Specification . Using ACRs and ACR configuration, the client application can define end-user authentication experience while ensuring required level of security for the application. Supported ACRs # Janssen Server lists supported ACRs in the response from Janssen Server's well-known configuration endpoint given below. Only ACRs that are supported and enabled by configuration will be part of the list. https://janssen.server.host/jans-auth/.well-known/openid-configuration The acr_values_supported claim in the response shows the list of supported and enabled ACRs for particular Janssen Server deployment. ACR categories: # ACRs available in Janssen Server can be broadly put into three categories. These categories are just for ease of understanding. 1. Internal Janssen Server ACR # Janssen server will use internal ACR only if no other authentication method is set or could be invoked. This internal ACR, simple_password_auth , is set to level -1. This means that it has lower priority than any other script. This ACR is always available and enabled on any Janssen Server deployment. This ACR is a simple user-id and password-based authentication mechanism. It authenticates the end-user against the backend datastore. 2. Pre-packaged ACR for authenticating using external LDAP or Active Directory # All Janssen Server deployments have default_ldap_server ACR which can be enabled to perform authentication against a remote LDAP-based IDP (e.g. ActiveDirectory). By default, this ACR is disabled. This ACR can only authenticate against LDAP-based IDP. Use the instructions provided in jans-cli LDAP configuration options documentation to learn how to enable and configure ACRs that use external LDAP as IDP. 3. Script-based ACRs # To offer highly flexible and pluggable authentication flows, Janssen Server uses script-based ACRs. These ACRs are associated with a corresponding person authentication script . To use these ACRs in the authentication flow, the associated script should be enabled . 4. Agama ACRs # Agama acrs starts from agama_ prefix. All of them invoke underlying agama bridge script called agama . General pattern is agama_<flow name> . Configuring ACRs in the JANS AS: # ACRs can be configured on two levels: 1. Client Level ACR # The client can configure a specific ACR that should be used if the authentication request is missing acr_values parameter. This can be configured using Default ACR attribute of the client configuration. Also, the client can restrict ACR values that authentication requests can have as part of acr_values parameter. This can be configured using Allowed ACRs . Using the Janssen Text base UI (TUI) configuration tool, these values can be configured by navigating to Auth Server -> clients -> get clients -> choose a client and press enter -> Advanced Client Prop . On this screen populate ACR values in Default ACR and Allowed ACRs : 2. Server Level ACR # Janssen Server administrator can configure an ACR that should be invoked if ACR for incoming requests can not be determined using client-level configuration. This is the default authentication mechanism exposed to all the clients that send end-users to the Janssen Server for sign-in. To configure this parameter using Janssen Text base UI (TUI) configuration tool, navigate to Auth Server -> Authn -> Default ACR as shown below: ACR Precedence Levels # Each authentication mechanism (script) has a \"Level\" assigned to it which describes how secure and reliable it is. The higher the \"Level\" represents higher reliability. Though several mechanisms(ACRs) can be enabled for the same Janssen server deployment at the same time, for any specific user's session only one of them can be set as the current ACR (and will be returned as acr claim of id_token). After the creation of the initial session, if RP sends a new request with a different ACR, then ACR's \"Level\" will be compared to that of the method associated with the current session. If the requested method's \"Level\" is lower or equal to current ACR's level, nothing is changed and the usual SSO behavior is observed. If the new level is higher (i.e. a more secure method is requested), and it's not possible to serve such a request using the existing session's context, then the user must re-authenticate to continue. If the user succeeds, a new session with a new ACR gets associated. ACR mappings (aliases) # There is acrMappings AS configuration property which allows to specify aliases for acrs. acrMappings contains simple map in key-value form. Lets say RP sends request with acr_values=loginWithOtpCheck . If acrMappings contains mapping \"loginWithOtpCheck\":\"otp\" then AS will map loginWithOtpCheck to otp and will use acr_values=otp for actual processing on server side. It means that custom script must be called otp in this case on AS side and not loginWithOtpCheck (because loginWithOtpCheck is alias to otp ). ACR mappings are published on discovery page GET /.well-known/openid-configuration HTTP/1.1 { ... \"acr_mappings\" :{ \"alias1\" : \"acr1\" , \"loginWithOtpCheck\" : \"otp\" } ... } Flowchart : How the Jans AS derives an ACR value for a user session # flowchart TD A[RP send authentication request] --> B{Request contains <br /><code>acr_values</code> parameter?} B -->|Yes| C[Perform Authentication] B -->|No| D{<code>Default ACR</code> <br />configured for <br />client?} D -->|Yes| C D -->|No| E{<code>Default ACR</code> value <br />configured for <br />Janssen Server?} E --> |Yes| C E --> |No| F[Select <br />internal ACR as<br /> Authentication method] --> C When authentication request is received from a client(RP), the Janssen Server looks for acr_values parameter in the request. This parameter is defined in the OpenId Connect core specification, section 3.1.2.1 . If the acr_values parameter is not received with the request, then Janssen Server uses the value from the Default ACR configuration from the client If Janssen Server doesn't find acr_values request parameter nor does it find the Default ACR configured for the client, then the Janssen Server checks the server configuration property useHighestLevelScriptIfAcrScriptNotFound . If this property is set to true, then Janssen Server invokes the authentication mechanism for which the corresponding person authentication script is enabled. Choosing the script with the highest level . If no script can be invoked or the useHighestLevelScriptIfAcrScriptNotFound property is set to false, then the Janssen Server authenticates using the default ACR for the server . If the default ACR for the server is not configured by the Janssen Server administrator, or it can not be invoked due to any reason, then the Janssen Server uses the internal server ACR to authenticate the end-user. Errors # unmet_authentication_requirements # If authorization request is sent to Authorization Endpoint with acr_values for which AS it not able to find \"Person Authentication\" custom script, it returns \"unmet_authentication_requirements\" with detail log in jans-auth.log . Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "ACRs"}, {"location": "janssen-server/auth-server/openid-features/acrs/#acr", "text": "ACR(Authentication Context Class Reference) is defined by OpenId Connect Specification . Using ACRs and ACR configuration, the client application can define end-user authentication experience while ensuring required level of security for the application.", "title": "ACR"}, {"location": "janssen-server/auth-server/openid-features/acrs/#supported-acrs", "text": "Janssen Server lists supported ACRs in the response from Janssen Server's well-known configuration endpoint given below. Only ACRs that are supported and enabled by configuration will be part of the list. https://janssen.server.host/jans-auth/.well-known/openid-configuration The acr_values_supported claim in the response shows the list of supported and enabled ACRs for particular Janssen Server deployment.", "title": "Supported ACRs"}, {"location": "janssen-server/auth-server/openid-features/acrs/#acr-categories", "text": "ACRs available in Janssen Server can be broadly put into three categories. These categories are just for ease of understanding.", "title": "ACR categories:"}, {"location": "janssen-server/auth-server/openid-features/acrs/#1-internal-janssen-server-acr", "text": "Janssen server will use internal ACR only if no other authentication method is set or could be invoked. This internal ACR, simple_password_auth , is set to level -1. This means that it has lower priority than any other script. This ACR is always available and enabled on any Janssen Server deployment. This ACR is a simple user-id and password-based authentication mechanism. It authenticates the end-user against the backend datastore.", "title": "1. Internal Janssen Server ACR"}, {"location": "janssen-server/auth-server/openid-features/acrs/#2-pre-packaged-acr-for-authenticating-using-external-ldap-or-active-directory", "text": "All Janssen Server deployments have default_ldap_server ACR which can be enabled to perform authentication against a remote LDAP-based IDP (e.g. ActiveDirectory). By default, this ACR is disabled. This ACR can only authenticate against LDAP-based IDP. Use the instructions provided in jans-cli LDAP configuration options documentation to learn how to enable and configure ACRs that use external LDAP as IDP.", "title": "2. Pre-packaged ACR for authenticating using external LDAP or Active Directory"}, {"location": "janssen-server/auth-server/openid-features/acrs/#3-script-based-acrs", "text": "To offer highly flexible and pluggable authentication flows, Janssen Server uses script-based ACRs. These ACRs are associated with a corresponding person authentication script . To use these ACRs in the authentication flow, the associated script should be enabled .", "title": "3. Script-based ACRs"}, {"location": "janssen-server/auth-server/openid-features/acrs/#4-agama-acrs", "text": "Agama acrs starts from agama_ prefix. All of them invoke underlying agama bridge script called agama . General pattern is agama_<flow name> .", "title": "4. Agama ACRs"}, {"location": "janssen-server/auth-server/openid-features/acrs/#configuring-acrs-in-the-jans-as", "text": "ACRs can be configured on two levels:", "title": "Configuring ACRs in the JANS AS:"}, {"location": "janssen-server/auth-server/openid-features/acrs/#1-client-level-acr", "text": "The client can configure a specific ACR that should be used if the authentication request is missing acr_values parameter. This can be configured using Default ACR attribute of the client configuration. Also, the client can restrict ACR values that authentication requests can have as part of acr_values parameter. This can be configured using Allowed ACRs . Using the Janssen Text base UI (TUI) configuration tool, these values can be configured by navigating to Auth Server -> clients -> get clients -> choose a client and press enter -> Advanced Client Prop . On this screen populate ACR values in Default ACR and Allowed ACRs :", "title": "1. Client Level ACR"}, {"location": "janssen-server/auth-server/openid-features/acrs/#2-server-level-acr", "text": "Janssen Server administrator can configure an ACR that should be invoked if ACR for incoming requests can not be determined using client-level configuration. This is the default authentication mechanism exposed to all the clients that send end-users to the Janssen Server for sign-in. To configure this parameter using Janssen Text base UI (TUI) configuration tool, navigate to Auth Server -> Authn -> Default ACR as shown below:", "title": "2. Server Level ACR"}, {"location": "janssen-server/auth-server/openid-features/acrs/#acr-precedence-levels", "text": "Each authentication mechanism (script) has a \"Level\" assigned to it which describes how secure and reliable it is. The higher the \"Level\" represents higher reliability. Though several mechanisms(ACRs) can be enabled for the same Janssen server deployment at the same time, for any specific user's session only one of them can be set as the current ACR (and will be returned as acr claim of id_token). After the creation of the initial session, if RP sends a new request with a different ACR, then ACR's \"Level\" will be compared to that of the method associated with the current session. If the requested method's \"Level\" is lower or equal to current ACR's level, nothing is changed and the usual SSO behavior is observed. If the new level is higher (i.e. a more secure method is requested), and it's not possible to serve such a request using the existing session's context, then the user must re-authenticate to continue. If the user succeeds, a new session with a new ACR gets associated.", "title": "ACR Precedence Levels"}, {"location": "janssen-server/auth-server/openid-features/acrs/#acr-mappings-aliases", "text": "There is acrMappings AS configuration property which allows to specify aliases for acrs. acrMappings contains simple map in key-value form. Lets say RP sends request with acr_values=loginWithOtpCheck . If acrMappings contains mapping \"loginWithOtpCheck\":\"otp\" then AS will map loginWithOtpCheck to otp and will use acr_values=otp for actual processing on server side. It means that custom script must be called otp in this case on AS side and not loginWithOtpCheck (because loginWithOtpCheck is alias to otp ). ACR mappings are published on discovery page GET /.well-known/openid-configuration HTTP/1.1 { ... \"acr_mappings\" :{ \"alias1\" : \"acr1\" , \"loginWithOtpCheck\" : \"otp\" } ... }", "title": "ACR mappings (aliases)"}, {"location": "janssen-server/auth-server/openid-features/acrs/#flowchart-how-the-jans-as-derives-an-acr-value-for-a-user-session", "text": "flowchart TD A[RP send authentication request] --> B{Request contains <br /><code>acr_values</code> parameter?} B -->|Yes| C[Perform Authentication] B -->|No| D{<code>Default ACR</code> <br />configured for <br />client?} D -->|Yes| C D -->|No| E{<code>Default ACR</code> value <br />configured for <br />Janssen Server?} E --> |Yes| C E --> |No| F[Select <br />internal ACR as<br /> Authentication method] --> C When authentication request is received from a client(RP), the Janssen Server looks for acr_values parameter in the request. This parameter is defined in the OpenId Connect core specification, section 3.1.2.1 . If the acr_values parameter is not received with the request, then Janssen Server uses the value from the Default ACR configuration from the client If Janssen Server doesn't find acr_values request parameter nor does it find the Default ACR configured for the client, then the Janssen Server checks the server configuration property useHighestLevelScriptIfAcrScriptNotFound . If this property is set to true, then Janssen Server invokes the authentication mechanism for which the corresponding person authentication script is enabled. Choosing the script with the highest level . If no script can be invoked or the useHighestLevelScriptIfAcrScriptNotFound property is set to false, then the Janssen Server authenticates using the default ACR for the server . If the default ACR for the server is not configured by the Janssen Server administrator, or it can not be invoked due to any reason, then the Janssen Server uses the internal server ACR to authenticate the end-user.", "title": "Flowchart : How the Jans AS derives an ACR value for a user session"}, {"location": "janssen-server/auth-server/openid-features/acrs/#errors", "text": "", "title": "Errors"}, {"location": "janssen-server/auth-server/openid-features/acrs/#unmet_authentication_requirements", "text": "If authorization request is sent to Authorization Endpoint with acr_values for which AS it not able to find \"Person Authentication\" custom script, it returns \"unmet_authentication_requirements\" with detail log in jans-auth.log .", "title": "unmet_authentication_requirements"}, {"location": "janssen-server/auth-server/openid-features/acrs/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/ciba/", "tags": ["administration", "auth-server", "openidc", "feature"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "CIBA"}, {"location": "janssen-server/auth-server/openid-features/ciba/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/ciba/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/ciba/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/id-token/", "tags": ["administration", "auth-server", "openidc", "feature", "ID Token"], "text": "ID Token # Janssen Server is an OpenID Connect Provider(OP). OpenID Connect extends OAuth 2.0 and adds user authentication capabilities using ID token. To add end-user authentication capabilities to an OAuth flow, it is important to use openid scope in the request as specified here . In absence of openid scope, the Janssen Server will not treat the incoming request as OpenID Connect request. For further information on how to configure and customize OpenID Connect using ID Token read here Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "id_token"}, {"location": "janssen-server/auth-server/openid-features/id-token/#id-token", "text": "Janssen Server is an OpenID Connect Provider(OP). OpenID Connect extends OAuth 2.0 and adds user authentication capabilities using ID token. To add end-user authentication capabilities to an OAuth flow, it is important to use openid scope in the request as specified here . In absence of openid scope, the Janssen Server will not treat the incoming request as OpenID Connect request. For further information on how to configure and customize OpenID Connect using ID Token read here", "title": "ID Token"}, {"location": "janssen-server/auth-server/openid-features/id-token/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/jarm/", "tags": ["administration", "auth-server", "openidc", "feature"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "JARM"}, {"location": "janssen-server/auth-server/openid-features/jarm/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/jarm/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/jarm/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/native-sso/", "tags": ["administration", "auth-server", "openidc", "feature", "native sso", "mobile", "single sign-on"], "text": "Native Single Sign-On # An increasing number of mobile phone users are using multiple mobile applications from the same software vendor. For instance, it is fairly common to see people using multiple mobile apps from software vendors like Google and Microsoft, etc. Software vendors need a way to allow users to sign-in to one of the apps provided by the software vendor and users should be able to use all other apps from the same vendor without having to sign-in again. In short, single sign-on for applications belonging to the same vendor. Janssen Server supports OpenID Connect native SSO mechanism to enable SSO for mobile applications. Scope Support # Janssen Server supports the device_sso scope as defined by the specification. Software vendor wanting to leverage native SSO feature should build the apps so during initial user authentication, the app would send device_sso scope in the authorization request. The presence of the device_sso scope in the authorization request would enable AS to return device_secret in the token response from the token endpoint. Device Secret # device_secret is an opaque value returned to the application from the token endpoint as a response to a token exchange request. Janssen Server will return device_secret only if the code provided by the application in token exchange request has device_sso scope. Janssen Server also checks if the client has the token exchange grant type enabled. To enable the grant type, use Janssen Text-based UI(TUI) and enable token exchange grant ( urn:ietf:params:oauth:grant-type:token-exchange ). The device_token claim in the returned token response contains the device secret. Janssen Server stores the device secretes issued to a client in the corresponding session-id. Processing Token Exchange Request # Janssen Server carries out the processing of token requests as per rules and checks defined in the specification . Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Native SSO"}, {"location": "janssen-server/auth-server/openid-features/native-sso/#native-single-sign-on", "text": "An increasing number of mobile phone users are using multiple mobile applications from the same software vendor. For instance, it is fairly common to see people using multiple mobile apps from software vendors like Google and Microsoft, etc. Software vendors need a way to allow users to sign-in to one of the apps provided by the software vendor and users should be able to use all other apps from the same vendor without having to sign-in again. In short, single sign-on for applications belonging to the same vendor. Janssen Server supports OpenID Connect native SSO mechanism to enable SSO for mobile applications.", "title": "Native Single Sign-On"}, {"location": "janssen-server/auth-server/openid-features/native-sso/#scope-support", "text": "Janssen Server supports the device_sso scope as defined by the specification. Software vendor wanting to leverage native SSO feature should build the apps so during initial user authentication, the app would send device_sso scope in the authorization request. The presence of the device_sso scope in the authorization request would enable AS to return device_secret in the token response from the token endpoint.", "title": "Scope Support"}, {"location": "janssen-server/auth-server/openid-features/native-sso/#device-secret", "text": "device_secret is an opaque value returned to the application from the token endpoint as a response to a token exchange request. Janssen Server will return device_secret only if the code provided by the application in token exchange request has device_sso scope. Janssen Server also checks if the client has the token exchange grant type enabled. To enable the grant type, use Janssen Text-based UI(TUI) and enable token exchange grant ( urn:ietf:params:oauth:grant-type:token-exchange ). The device_token claim in the returned token response contains the device secret. Janssen Server stores the device secretes issued to a client in the corresponding session-id.", "title": "Device Secret"}, {"location": "janssen-server/auth-server/openid-features/native-sso/#processing-token-exchange-request", "text": "Janssen Server carries out the processing of token requests as per rules and checks defined in the specification .", "title": "Processing Token Exchange Request"}, {"location": "janssen-server/auth-server/openid-features/native-sso/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/prompt-parameter/", "tags": ["administration", "auth-server", "openidc", "feature", "prompt"], "text": "Prompt CREATE # prompt=create value indicates to the AS that the client desires that the user be shown the account creation page rather than the login flow. It is enabled by default. However prompt=create can be entirely disabled if set AS configuration property disablePromptCreate to true . By default for prompt=create createUser page is shown which allows to enter basic information: - display name - email - login - password On \"Create User\" button click user is created and redirected Authorization Endpoint of AS. If more or custom fields has to be shown then custom page should be added and \"CreateUser\" custom script should redirect to that custom page. public String getCreateUserPage ( Object context ) { return \"/customCreateUser\" ; } \"CreateUser\" custom script Prompt NONE # The OpenID Connect protocol supports a prompt=none parameter on the authentication request that allows applications to indicate that the authorization server must not display any user interaction (such as authentication, consent, or MFA). Janssen will either return the requested response back to the application, or return an error if the user is not already authenticated or if some type of consent or prompt is required before proceeding. Initiate Silent Authentication requests To initiate a silent authentication request, add the prompt=none parameter when you redirect a user to the /authorize endpoint of Janssen authentication API. (The individual parameters on the authentication request will vary depending on the specific needs of your app.) For example: GET https://YOUR_DOMAIN//authorize? response_type={response_type}& client_id={client_id}& scope={scope}& state={state}& ui_locales=& claims_locales=& acr_values=& redirect_uri={redirect_uri}& prompt=none Basic credential user The prompt=none parameter causes Jannsen to immediately send a result to the specified redirect_uri (callback URL) using the specified response_mode with one of two possible responses: success or error. Note: Any applicable rules will be executed as part of the silent authentication process. Successful authentication responses If the user was already logged in to Janssen and no other interactive prompts are required, Janssen will respond exactly as if the user had authenticated manually through the login page. This response is indistinguishable from a login performed directly without the prompt=none parameter. Example 1: Prompt None (Without credentials in Header) title Prompt None (Without credentials in Header) participant Browser participant IDP participant Identity participant SessionIdService participant AuthorizeRestWebServiceValidator participant AuthenticationFilterService Browser->IDP: /authorize?\\nresponse_type=... &\\nclient_id=... &\\nscope=... &\\nstate=... &\\nui_locales=... &\\nclaims_locales=... &\\nacr_values=... &\\nredirect_uri=... &\\n**prompt=none** IDP->Identity: getSessionId() Identity->IDP: return: null IDP->SessionIdService: getUser(): from sessionId SessionIdService->IDP: return: null group Client validation IDP->AuthorizeRestWebServiceValidator: validateClient(): if it's par, disabled or not found? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException end group User is null IDP->IDP: ifUserIsNull() IDP->AuthenticationFilterService: processAuthenticationFilters() AuthenticationFilterService->Browser: WebApplicationException (LOGIN_REQUIRED) end Example 2: Prompt None (Without credentials in Header) title Prompt None (With credentials in Header) participant Browser participant Janssen participant Identity participant SessionIdService participant AuthorizeRestWebServiceValidator participant ScopeChecker participant ExternalPostAuthnService participant ResponseParameters participant ExternalUpdateTokenService participant ClientService Browser->Janssen: /authorize?\\nresponse_type=... &\\nclient_id=... &\\nscope=... &\\nstate=... &\\nui_locales=... &\\nclaims_locales=... &\\nacr_values=... &\\nredirect_uri=... &\\n**prompt=none**\\n\\n**Basic credentials (user)** in Headers Janssen->Identity: getSessionId() Identity->Janssen: return: sessionId Janssen->SessionIdService: getUser(): from sessionId SessionIdService->Janssen: return: User group Update Session For ROPC: If exists session attribute grant_type ROPC Janssen->Janssen: updateSessionForROPC() Janssen->SessionIdService: updateSessionId() SessionIdService->Janssen: session attributes updated end group Client validation Janssen->AuthorizeRestWebServiceValidator: validateClient(): if it's par, disabled or not found? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException (INVALID_REQUEST, UNAUTHORIZED_CLIENT, DISABLED_CLIENT) end group ACR validation Janssen->AuthorizeRestWebServiceValidator: validateAcrs(): If the request acr list does not exist in the session attribute? or\\n Acr Changed? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException (INVALID_REQUEST) end group Max Age Validation Janssen->Janssen: validateMaxAge() Janssen->AuthorizeRestWebServiceValidator: isAuthnMaxAgeValid() AuthorizeRestWebServiceValidator->Janssen: throw new WebApplicationException(): redirectToAuthorizationPage(): if it's not valid end Janssen->ScopeChecker: checkScopesPolicy() ScopeChecker->Janssen: return: scopes group Post Authn Custom Script Janssen->ExternalPostAuthnService: checkForceReAuthentication() Janssen->ExternalPostAuthnService: checkForceAuthorization() end group if ResponseType CODE Janssen->ResponseParameters: put code end group if ResponseType TOKEN Janssen->ResponseParameters: put access_token, token_type and expires_in Janssen->ExternalUpdateTokenService: modifyAccessToken() ExternalUpdateTokenService->Janssen: return true or false end group if ResponseType ID_TOKEN Janssen->ResponseParameters: put id_token Janssen->ExternalUpdateTokenService: modifyIdToken() ExternalUpdateTokenService->Janssen: return true or false end Janssen->SessionIdService: generateAuthenticatedSessionId(): if exists sessionId SessionIdService->Janssen: return: newSessionUser Janssen->ResponseParameters: addRespnseParameterSessionId(): if enabled appConfiguration.getSessionIdRequestParameterEnabled() Janssen->ResponseParameters: addResponseParameterSid(): if enabled appConfiguration.getIncludeSidInResponse() Janssen->ResponseParameters: put session_state and state Janssen->ClientService: updateAccessTime() Janssen->Browser: /redirect_uri?with_param=...", "title": "Prompt Parameter"}, {"location": "janssen-server/auth-server/openid-features/prompt-parameter/#prompt-create", "text": "prompt=create value indicates to the AS that the client desires that the user be shown the account creation page rather than the login flow. It is enabled by default. However prompt=create can be entirely disabled if set AS configuration property disablePromptCreate to true . By default for prompt=create createUser page is shown which allows to enter basic information: - display name - email - login - password On \"Create User\" button click user is created and redirected Authorization Endpoint of AS. If more or custom fields has to be shown then custom page should be added and \"CreateUser\" custom script should redirect to that custom page. public String getCreateUserPage ( Object context ) { return \"/customCreateUser\" ; } \"CreateUser\" custom script", "title": "Prompt CREATE"}, {"location": "janssen-server/auth-server/openid-features/prompt-parameter/#prompt-none", "text": "The OpenID Connect protocol supports a prompt=none parameter on the authentication request that allows applications to indicate that the authorization server must not display any user interaction (such as authentication, consent, or MFA). Janssen will either return the requested response back to the application, or return an error if the user is not already authenticated or if some type of consent or prompt is required before proceeding. Initiate Silent Authentication requests To initiate a silent authentication request, add the prompt=none parameter when you redirect a user to the /authorize endpoint of Janssen authentication API. (The individual parameters on the authentication request will vary depending on the specific needs of your app.) For example: GET https://YOUR_DOMAIN//authorize? response_type={response_type}& client_id={client_id}& scope={scope}& state={state}& ui_locales=& claims_locales=& acr_values=& redirect_uri={redirect_uri}& prompt=none Basic credential user The prompt=none parameter causes Jannsen to immediately send a result to the specified redirect_uri (callback URL) using the specified response_mode with one of two possible responses: success or error. Note: Any applicable rules will be executed as part of the silent authentication process. Successful authentication responses If the user was already logged in to Janssen and no other interactive prompts are required, Janssen will respond exactly as if the user had authenticated manually through the login page. This response is indistinguishable from a login performed directly without the prompt=none parameter. Example 1: Prompt None (Without credentials in Header) title Prompt None (Without credentials in Header) participant Browser participant IDP participant Identity participant SessionIdService participant AuthorizeRestWebServiceValidator participant AuthenticationFilterService Browser->IDP: /authorize?\\nresponse_type=... &\\nclient_id=... &\\nscope=... &\\nstate=... &\\nui_locales=... &\\nclaims_locales=... &\\nacr_values=... &\\nredirect_uri=... &\\n**prompt=none** IDP->Identity: getSessionId() Identity->IDP: return: null IDP->SessionIdService: getUser(): from sessionId SessionIdService->IDP: return: null group Client validation IDP->AuthorizeRestWebServiceValidator: validateClient(): if it's par, disabled or not found? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException end group User is null IDP->IDP: ifUserIsNull() IDP->AuthenticationFilterService: processAuthenticationFilters() AuthenticationFilterService->Browser: WebApplicationException (LOGIN_REQUIRED) end Example 2: Prompt None (Without credentials in Header) title Prompt None (With credentials in Header) participant Browser participant Janssen participant Identity participant SessionIdService participant AuthorizeRestWebServiceValidator participant ScopeChecker participant ExternalPostAuthnService participant ResponseParameters participant ExternalUpdateTokenService participant ClientService Browser->Janssen: /authorize?\\nresponse_type=... &\\nclient_id=... &\\nscope=... &\\nstate=... &\\nui_locales=... &\\nclaims_locales=... &\\nacr_values=... &\\nredirect_uri=... &\\n**prompt=none**\\n\\n**Basic credentials (user)** in Headers Janssen->Identity: getSessionId() Identity->Janssen: return: sessionId Janssen->SessionIdService: getUser(): from sessionId SessionIdService->Janssen: return: User group Update Session For ROPC: If exists session attribute grant_type ROPC Janssen->Janssen: updateSessionForROPC() Janssen->SessionIdService: updateSessionId() SessionIdService->Janssen: session attributes updated end group Client validation Janssen->AuthorizeRestWebServiceValidator: validateClient(): if it's par, disabled or not found? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException (INVALID_REQUEST, UNAUTHORIZED_CLIENT, DISABLED_CLIENT) end group ACR validation Janssen->AuthorizeRestWebServiceValidator: validateAcrs(): If the request acr list does not exist in the session attribute? or\\n Acr Changed? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException (INVALID_REQUEST) end group Max Age Validation Janssen->Janssen: validateMaxAge() Janssen->AuthorizeRestWebServiceValidator: isAuthnMaxAgeValid() AuthorizeRestWebServiceValidator->Janssen: throw new WebApplicationException(): redirectToAuthorizationPage(): if it's not valid end Janssen->ScopeChecker: checkScopesPolicy() ScopeChecker->Janssen: return: scopes group Post Authn Custom Script Janssen->ExternalPostAuthnService: checkForceReAuthentication() Janssen->ExternalPostAuthnService: checkForceAuthorization() end group if ResponseType CODE Janssen->ResponseParameters: put code end group if ResponseType TOKEN Janssen->ResponseParameters: put access_token, token_type and expires_in Janssen->ExternalUpdateTokenService: modifyAccessToken() ExternalUpdateTokenService->Janssen: return true or false end group if ResponseType ID_TOKEN Janssen->ResponseParameters: put id_token Janssen->ExternalUpdateTokenService: modifyIdToken() ExternalUpdateTokenService->Janssen: return true or false end Janssen->SessionIdService: generateAuthenticatedSessionId(): if exists sessionId SessionIdService->Janssen: return: newSessionUser Janssen->ResponseParameters: addRespnseParameterSessionId(): if enabled appConfiguration.getSessionIdRequestParameterEnabled() Janssen->ResponseParameters: addResponseParameterSid(): if enabled appConfiguration.getIncludeSidInResponse() Janssen->ResponseParameters: put session_state and state Janssen->ClientService: updateAccessTime() Janssen->Browser: /redirect_uri?with_param=...", "title": "Prompt NONE"}, {"location": "janssen-server/auth-server/openid-features/request-objects/", "tags": ["administration", "auth-server", "openidc", "feature"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Request Objects"}, {"location": "janssen-server/auth-server/openid-features/request-objects/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/request-objects/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/request-objects/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/", "tags": ["administration", "auth-server", "openidc", "feature", "subject identifier"], "text": "Subject identifiers # Subject identifiers(defined in OpenID Connect Core SPEC ) are unique identifiers generated by Janssen Server(i.e. OpenId Provider) for an end-user. Subject identifiers are unique per Janssen Server instance and it is shared with the client (or clients) via ID token or access token. Whether the same subject identifier is used for the same end-user across multiple clients depends on the kind of subject identifier configured for a particular client. Types of Subject Identifiers # Janssen Server supports both subject identifier types, public and pairwise , as specified in OpenID Connect specification. For a particular Janssen Server deployment, the supported types are listed in the response of Janssen Server's well-known configuration endpoint is given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration The subject_types_supported claim in the response specifies the list of all the supported types. More details about both types are given in this section of specification. Public Subject Identifiers # Public subject identifiers are identifiers that the server generates and assigns to each subject. These identifiers are unique for each server deployment. All the clients that are configured to use a public type subject identifier will be supplied this same identifier for a given subject by the Janssen Server. Sharing common subject identifiers across multiple clients may enable clients to correlate data about a particular subject. If this is an unwanted situation, then the client should use pairwise subject identifiers. By default, the Janssen Server uses the subject attribute inum as the subject identifier. Customizing Subject Identifier Attribute # At the server level, the administrator specifies which subject attribute should be used as subject identifiers. This can be done by updating the value of openidSubAttribute Janssen Server property. At the client level, this can be further customized. If a client uses public type subject identifier, the client can configure the subject attribute that should be used as a subject identifier. This should be done at the client registration time. To enable client level customization, the Janssen Server property publicSubjectIdentifierPerClientEnabled should be set to true and also the desired attribute should be part of the list defined by the Janssen Server property subjectIdentifiersPerClientSupported . Both these properties can be set by the administrator using TUI . Pairwise Subject Identifiers # When a client chooses to use pairwise subject identifier, the Janssen Server generates and attaches a new identifier to all the subjects requested by the client. This identifier is consistently used for the subject-client pair and never used for any other clients configured on the Janssen Server. If multiple clients are using pairwise type subject identifiers, then the same subject will have different identifiers for each subject. Since every client has a different identifier for the same subject, the clients can't match identifiers and correlate information about a subject out of the band. Pairwise Identifier Generation # Janssen Server uses host name string from redirect URI or sector identifier, local user ID, and a salt string as initial inputs to generate pairwise identifiers. This input is then signed with the HS256 signing algorithm to generate a pairwise identifier. Sector identifier configuration influences how pairwise identifiers are calculated. See this document for more details. Properties # Janssen Server allows customization concerning subject identifiers using the properties below: subjectTypesSupported defaultSubjectType shareSubjectIdBetweenClientsWithSameSectorId openidSubAttribute publicSubjectIdentifierPerClientEnabled subjectIdentifiersPerClientSupported skipAuthorizationForOpenIdScopeAndPairwiseId pairwiseCalculationKey pairwiseCalculationSalt pairwiseIdType Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Pairwise/Public Subject Identifiers"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#subject-identifiers", "text": "Subject identifiers(defined in OpenID Connect Core SPEC ) are unique identifiers generated by Janssen Server(i.e. OpenId Provider) for an end-user. Subject identifiers are unique per Janssen Server instance and it is shared with the client (or clients) via ID token or access token. Whether the same subject identifier is used for the same end-user across multiple clients depends on the kind of subject identifier configured for a particular client.", "title": "Subject identifiers"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#types-of-subject-identifiers", "text": "Janssen Server supports both subject identifier types, public and pairwise , as specified in OpenID Connect specification. For a particular Janssen Server deployment, the supported types are listed in the response of Janssen Server's well-known configuration endpoint is given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration The subject_types_supported claim in the response specifies the list of all the supported types. More details about both types are given in this section of specification.", "title": "Types of Subject Identifiers"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#public-subject-identifiers", "text": "Public subject identifiers are identifiers that the server generates and assigns to each subject. These identifiers are unique for each server deployment. All the clients that are configured to use a public type subject identifier will be supplied this same identifier for a given subject by the Janssen Server. Sharing common subject identifiers across multiple clients may enable clients to correlate data about a particular subject. If this is an unwanted situation, then the client should use pairwise subject identifiers. By default, the Janssen Server uses the subject attribute inum as the subject identifier.", "title": "Public Subject Identifiers"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#customizing-subject-identifier-attribute", "text": "At the server level, the administrator specifies which subject attribute should be used as subject identifiers. This can be done by updating the value of openidSubAttribute Janssen Server property. At the client level, this can be further customized. If a client uses public type subject identifier, the client can configure the subject attribute that should be used as a subject identifier. This should be done at the client registration time. To enable client level customization, the Janssen Server property publicSubjectIdentifierPerClientEnabled should be set to true and also the desired attribute should be part of the list defined by the Janssen Server property subjectIdentifiersPerClientSupported . Both these properties can be set by the administrator using TUI .", "title": "Customizing Subject Identifier Attribute"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#pairwise-subject-identifiers", "text": "When a client chooses to use pairwise subject identifier, the Janssen Server generates and attaches a new identifier to all the subjects requested by the client. This identifier is consistently used for the subject-client pair and never used for any other clients configured on the Janssen Server. If multiple clients are using pairwise type subject identifiers, then the same subject will have different identifiers for each subject. Since every client has a different identifier for the same subject, the clients can't match identifiers and correlate information about a subject out of the band.", "title": "Pairwise Subject Identifiers"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#pairwise-identifier-generation", "text": "Janssen Server uses host name string from redirect URI or sector identifier, local user ID, and a salt string as initial inputs to generate pairwise identifiers. This input is then signed with the HS256 signing algorithm to generate a pairwise identifier. Sector identifier configuration influences how pairwise identifiers are calculated. See this document for more details.", "title": "Pairwise Identifier Generation"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#properties", "text": "Janssen Server allows customization concerning subject identifiers using the properties below: subjectTypesSupported defaultSubjectType shareSubjectIdBetweenClientsWithSameSectorId openidSubAttribute publicSubjectIdentifierPerClientEnabled subjectIdentifiersPerClientSupported skipAuthorizationForOpenIdScopeAndPairwiseId pairwiseCalculationKey pairwiseCalculationSalt pairwiseIdType", "title": "Properties"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/consent/customize/", "tags": ["administration", "auth-server", "openidc", "feature", "consent"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Customize"}, {"location": "janssen-server/auth-server/openid-features/consent/customize/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/consent/customize/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/consent/customize/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/consent/list-delete/", "tags": ["administration", "auth-server", "openidc", "feature", "consent"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "List/Delete Consent"}, {"location": "janssen-server/auth-server/openid-features/consent/list-delete/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/consent/list-delete/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/consent/list-delete/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/logout/back-channel/", "tags": ["administration", "auth-server", "openidc", "feature", "logout"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Back Channel"}, {"location": "janssen-server/auth-server/openid-features/logout/back-channel/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/logout/back-channel/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/logout/back-channel/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/logout/customizing-logout/", "tags": ["administration", "auth-server", "openidc", "feature", "logout"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Customizing Logout"}, {"location": "janssen-server/auth-server/openid-features/logout/customizing-logout/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/logout/customizing-logout/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/logout/customizing-logout/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/logout/forcing-logout/", "tags": ["administration", "auth-server", "openidc", "feature", "logout"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Forcing Logout on Browser Exit"}, {"location": "janssen-server/auth-server/openid-features/logout/forcing-logout/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/logout/forcing-logout/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/logout/forcing-logout/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/logout/front-channel/", "tags": ["administration", "auth-server", "openidc", "feature", "logout"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Front Channel"}, {"location": "janssen-server/auth-server/openid-features/logout/front-channel/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/logout/front-channel/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/logout/front-channel/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/user-claims/built-in-claims/", "tags": ["administration", "auth-server", "openidc", "feature", "claims", "built-in-claims"], "text": "Built-in Claims # The Janssen Server includes all standard claims defined in OpenID Connect specifications . Built-in claims defines a standard set of pre-defined claims available to use after installation for sharing of user attributes between identity providers and relying parties. The built-in user claims in Janssen are listed in below table Display Name Claim Name Description Username user_name Username of user Password user_password Password of user First Name given_name First name of user Middle Name middle_name Middle name of user Last Name family_name Last name of user Display Name name Display name of user Email email Email address of user Nickname nickname Nickname used for user CIBA Device Registration Token jans_backchannel_device_registration_tkn CIBA Device Registration Token CIBA User code jans_backchannel_usr_code CIBA User code Locale locale End-User's locale, represented as a BCP47 (RFC5646) language tag Website URL website URL of the End-User's Web page or blog IMAP Data imap_data IMAP data jansAdminUIRole jansAdminUIRole Gluu Flex Admin UI role Enrollment code jans_enrollment_code Enrollment code User Permission user_permission User permission Preferred Language preferred_language Preferred language Profile URL profile Profile URL Secret Question secret_question Secret question used to verify user identity Email Verified email_verified Is user's email verified? Birthdate birthdate Baithdate of user Time zone info zoneinfo The End-User's time zone Phone Number verified phone_number_verified Is user's phone number verified? Preferred Username preferred_username A domain issued and managed identifier for the person TransientId transient_id ... PersistentId persistent_id ... Country country User's country Secret Answer secret_answer Secret answer used to verify user identity OpenID Connect JSON formatted address address End-User's preferred postal address. The value of the address member is a JSON structure containing some or all of the members defined in OpenID Connect 1.0 Core Standard Section 5.1.1 User certificate user_certificate User certificate Organization o Organization Picture URL picture User's picture url", "title": "Built-in Claims"}, {"location": "janssen-server/auth-server/openid-features/user-claims/built-in-claims/#built-in-claims", "text": "The Janssen Server includes all standard claims defined in OpenID Connect specifications . Built-in claims defines a standard set of pre-defined claims available to use after installation for sharing of user attributes between identity providers and relying parties. The built-in user claims in Janssen are listed in below table Display Name Claim Name Description Username user_name Username of user Password user_password Password of user First Name given_name First name of user Middle Name middle_name Middle name of user Last Name family_name Last name of user Display Name name Display name of user Email email Email address of user Nickname nickname Nickname used for user CIBA Device Registration Token jans_backchannel_device_registration_tkn CIBA Device Registration Token CIBA User code jans_backchannel_usr_code CIBA User code Locale locale End-User's locale, represented as a BCP47 (RFC5646) language tag Website URL website URL of the End-User's Web page or blog IMAP Data imap_data IMAP data jansAdminUIRole jansAdminUIRole Gluu Flex Admin UI role Enrollment code jans_enrollment_code Enrollment code User Permission user_permission User permission Preferred Language preferred_language Preferred language Profile URL profile Profile URL Secret Question secret_question Secret question used to verify user identity Email Verified email_verified Is user's email verified? Birthdate birthdate Baithdate of user Time zone info zoneinfo The End-User's time zone Phone Number verified phone_number_verified Is user's phone number verified? Preferred Username preferred_username A domain issued and managed identifier for the person TransientId transient_id ... PersistentId persistent_id ... Country country User's country Secret Answer secret_answer Secret answer used to verify user identity OpenID Connect JSON formatted address address End-User's preferred postal address. The value of the address member is a JSON structure containing some or all of the members defined in OpenID Connect 1.0 Core Standard Section 5.1.1 User certificate user_certificate User certificate Organization o Organization Picture URL picture User's picture url", "title": "Built-in Claims"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/", "tags": ["administration", "auth-server", "openidc", "feature", "claims", "custom-claims"], "text": "Custom Claims # Custom claims provide the flexibility to include application-specific or user-specific information in the authentication process.Custom claims serve to enrich the information available to the relying party (RP), which is the application or service that relies on the identity provided by the OIDC provider. While standard claims provide basic user information, custom claims allow for the inclusion of domain-specific attributes or application-specific data that might be required for user personalization, authorization, or other business logic. User claims should be unique and non-null or empty. Adding a new custom user claim # MySQL persistence # Step 1: Create a custom attribute # Create a new custom attribute using Test User Interface or CURL commands , superb tools provided in Janssen. The attribute-name should be the claim-name. Step 2: Make entry of the claim in MySQL Schema # Add a column to table jansPerson in MySQL. Command will be ALTER TABLE jansPerson ADD COLUMN <claimName> <dataType> ; Example mysql> ALTER TABLE jansPerson ADD COLUMN newClaim VARCHAR(100); Choose dataType according to the following table TUI dataType SQL dataType Text VARCHAR() string value to be kept, SIZE is an integer for max string size Numeric INT Boolean SMALLINT Binary BINARY Certificate TEXT Date DATETIME(3) Numeric INT Multivalued JSON Warning If the attribute is Multivalued, dataType should be JSON regardless of what you will choose for Type in Janssen TUI. The above steps will create the custom user claim in the MySQL persistence. Once the user claim is added, it can be used in user management.", "title": "Adding Custom Claims"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/#custom-claims", "text": "Custom claims provide the flexibility to include application-specific or user-specific information in the authentication process.Custom claims serve to enrich the information available to the relying party (RP), which is the application or service that relies on the identity provided by the OIDC provider. While standard claims provide basic user information, custom claims allow for the inclusion of domain-specific attributes or application-specific data that might be required for user personalization, authorization, or other business logic. User claims should be unique and non-null or empty.", "title": "Custom Claims"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/#adding-a-new-custom-user-claim", "text": "", "title": "Adding a new custom user claim"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/#mysql-persistence", "text": "", "title": "MySQL persistence"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/#step-1-create-a-custom-attribute", "text": "Create a new custom attribute using Test User Interface or CURL commands , superb tools provided in Janssen. The attribute-name should be the claim-name.", "title": "Step 1: Create a custom attribute"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/#step-2-make-entry-of-the-claim-in-mysql-schema", "text": "Add a column to table jansPerson in MySQL. Command will be ALTER TABLE jansPerson ADD COLUMN <claimName> <dataType> ; Example mysql> ALTER TABLE jansPerson ADD COLUMN newClaim VARCHAR(100); Choose dataType according to the following table TUI dataType SQL dataType Text VARCHAR() string value to be kept, SIZE is an integer for max string size Numeric INT Boolean SMALLINT Binary BINARY Certificate TEXT Date DATETIME(3) Numeric INT Multivalued JSON Warning If the attribute is Multivalued, dataType should be JSON regardless of what you will choose for Type in Janssen TUI. The above steps will create the custom user claim in the MySQL persistence. Once the user claim is added, it can be used in user management.", "title": "Step 2: Make entry of the claim in MySQL Schema"}, {"location": "janssen-server/auth-server/session-management/idp-v-rp/", "tags": ["administration", "auth-server", "session"], "text": "IDP versus RP session # Applications generally have their own session cookie (the \"RP Session\"). This makes sense, because the RP only redirects to the IDP for authentication if it cannot find its own local cookie. If a user has a session with many RP's, achieving simultaneous logout across all sites is a challenge--something which your business leaders may not appreciate. While OpenID proposes several solutions to logout, none are ideal. Fundamentally, logout is an asynchronous challenge. A given RP may be disconnected from the network. Thus logout messages sent to RP's that are not received must be replayed. The IETF Sec Events Workgroup has been working on standards to handle logout (and other asynchronous requirements). But adoption of this architecture is not common. Another challenge of RP sessions is that they may have a different timeout for inactivity. See the Janssen Planning Guide page on Timeout Management for more details.", "title": "IDP v RP Sessions"}, {"location": "janssen-server/auth-server/session-management/idp-v-rp/#idp-versus-rp-session", "text": "Applications generally have their own session cookie (the \"RP Session\"). This makes sense, because the RP only redirects to the IDP for authentication if it cannot find its own local cookie. If a user has a session with many RP's, achieving simultaneous logout across all sites is a challenge--something which your business leaders may not appreciate. While OpenID proposes several solutions to logout, none are ideal. Fundamentally, logout is an asynchronous challenge. A given RP may be disconnected from the network. Thus logout messages sent to RP's that are not received must be replayed. The IETF Sec Events Workgroup has been working on standards to handle logout (and other asynchronous requirements). But adoption of this architecture is not common. Another challenge of RP sessions is that they may have a different timeout for inactivity. See the Janssen Planning Guide page on Timeout Management for more details.", "title": "IDP versus RP session"}, {"location": "janssen-server/auth-server/session-management/multiple-sessions-one-browser/", "tags": ["administration", "auth-server", "session", "Account Chooser"], "text": "Select Account # A person may have several accounts on a single Jans Auth Server instance. For example, it is common to have several Gmail accounts. Jans Auth Server uses two cookies to track which accounts are associated with a browser: session_id and current_sessions . Below is an example or a person with two authenticated sessions: session_id: de510ab6-b06c-4393-86d8-12a7c501aafe current_sessions: [\"de510ab6-b06c-4393-86d8-12a7c501aafe\", \"c691e83d-eb1b-41f0-b453-fab905681b5b\"] An RP can trigger Auth Server's built in Account Chooser feature by sending an OpenID Authentication Request with the parameter prompt=select_account . In this case, Auth Server renders the default page: /opt/jans/jetty/jans-auth/custom/pages/selectAccount.xhtml This page iterates current_sessions and enables the person to login as a different account, for example: You can override this page if you place a selectAccount.xhtml in custom/pages .", "title": "Multiple Sessions in One Browser"}, {"location": "janssen-server/auth-server/session-management/multiple-sessions-one-browser/#select-account", "text": "A person may have several accounts on a single Jans Auth Server instance. For example, it is common to have several Gmail accounts. Jans Auth Server uses two cookies to track which accounts are associated with a browser: session_id and current_sessions . Below is an example or a person with two authenticated sessions: session_id: de510ab6-b06c-4393-86d8-12a7c501aafe current_sessions: [\"de510ab6-b06c-4393-86d8-12a7c501aafe\", \"c691e83d-eb1b-41f0-b453-fab905681b5b\"] An RP can trigger Auth Server's built in Account Chooser feature by sending an OpenID Authentication Request with the parameter prompt=select_account . In this case, Auth Server renders the default page: /opt/jans/jetty/jans-auth/custom/pages/selectAccount.xhtml This page iterates current_sessions and enables the person to login as a different account, for example: You can override this page if you place a selectAccount.xhtml in custom/pages .", "title": "Select Account"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/", "tags": ["administration", "auth-server", "oauth", "access-token"], "text": "OAuth Access Tokens # Background # When a software client calls an OAuth protected API, an access token is presented in the HTTP Authorization header of the request. Following is an example of a bearer token: Authorization: Bearer 8pkjyj0gxhwh6ux2 OAuth access tokens come in two main types: bearer tokens and MAC tokens. Bearer tokens are the most commonly used type of access token. They are simply a string that is included in the Authorization header of an HTTP request. The client presents the token to the resource server, which can trust the token, by validating it was issued by a trusted authorization server. Bearer tokens can be sent either by value or reference. A value token is a JWT, signed by the authorization server. By calling Auth Server's [introspection endpoint], the client can trade the reference token for the plain JSON object. MAC tokens, are cryptographically signed tokens that include a nonce, timestamp, and other information to prevent replay attacks. They are typically used in situations where the client and the resource server are not able to securely share a secret. They are not commonly used and Janssen Auth Server does not support MAC tokens. There are several security considerations that both mobile developers and API developers should be aware of when working with OAuth access tokens. For mobile developers, it is important to ensure that the access token is stored securely on the device, and that it is not exposed to other apps or processes. API developers should ensure that their API is only accessible to clients that have a valid access token, and that the API properly validates the token before allowing access to the protected resource. Scopes are used in OAuth access tokens to limit the extent of access of a token, i.e. the specific resources and actions that the token is valid for. Scopes are typically defined by the API developer, and the client can request a specific scope when requesting an access token from the authorization server. This allows the API developer to fine-tune the level of access that different clients have to the API. Other security considerations for OAuth access tokens include the need to protect against replay attacks by including a nonce and timestamp in the token and using TLS for all communication between the client, the authorization server and the resource server. It is also important to rotate the access token. This can be done by using short lived tokens and refresh tokens which will allow the client to obtain a new access token without re-prompting the user for their credentials. By default, Jans Auth Server access tokens expire after 5 minutes. Access Token Schema # claim Description active true or false . iss The URI of the issuer authorization server aud The audience, used by the client to verify it is the correct recipient. During registration, the client can specify additional_audience values iat When the client was issued, in seconds, e.g. 1514797822 exp When the token expires, in seconds, e.g. 1514797942 scope A space delimited list of scopes client_id Recipient of the token nbf Not before, which insures the token is only valid within a certain time window cnf Confirmation, used for TLS client certificate bound tokens It is possible to add additional claims to an access token via the Auth Server interception scripts. The preferred script is the update token script . You can also use the introspection script . Access Token Crypto (JWT) # JWT access tokens are signed by Jans Auth Server using algorithms specified in the access_token_signing_alg_values_supported claim of the OpenID configuration endpoint response. Access tokens are signed with the standard OpenID signing key. Jans Auth Server supports TLS client certificate bound access tokens. After a successful mutual TLS client authentication, Jans Auth Server encodes the client certificate thumbprint (hash) in x5t#S256 confirmation method of the JWT or introspection JSON. Assuming the client uses the same certificate to establish a mutual TLS session with the API, the thumbprint in the access token can verify that this is the same client that obtained the access token. This feature is typically used in high security environments, as the operational cost of mutual TLS is material. Decoded JWT example { \"iss\" : \"https://server.example.com\" , \"sub\" : \"ty.webb@example.com\" , \"exp\" : 1493726400 , \"nbf\" : 1493722800 , \"cnf\" :{ \"x5t#S256\" : \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" } } Sample introspection response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"active\" : true , \"iss\" : \"https://server.example.com\" , \"sub\" : \"ty.webb@example.com\" , \"exp\" : 1493726400 , \"nbf\" : 1493722800 , \"cnf\" :{ \"x5t#S256\" : \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" } } Server and Client configurations # Access token lifetime is configurable at the server level via the accessTokenLifetime property. However, a client can override this value during client registration with the access_token_lifetime request parameter. Revoke Access Token # Access token can be revoked via Revoke Endpoint", "title": "OAuth Access Tokens"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#oauth-access-tokens", "text": "", "title": "OAuth Access Tokens"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#background", "text": "When a software client calls an OAuth protected API, an access token is presented in the HTTP Authorization header of the request. Following is an example of a bearer token: Authorization: Bearer 8pkjyj0gxhwh6ux2 OAuth access tokens come in two main types: bearer tokens and MAC tokens. Bearer tokens are the most commonly used type of access token. They are simply a string that is included in the Authorization header of an HTTP request. The client presents the token to the resource server, which can trust the token, by validating it was issued by a trusted authorization server. Bearer tokens can be sent either by value or reference. A value token is a JWT, signed by the authorization server. By calling Auth Server's [introspection endpoint], the client can trade the reference token for the plain JSON object. MAC tokens, are cryptographically signed tokens that include a nonce, timestamp, and other information to prevent replay attacks. They are typically used in situations where the client and the resource server are not able to securely share a secret. They are not commonly used and Janssen Auth Server does not support MAC tokens. There are several security considerations that both mobile developers and API developers should be aware of when working with OAuth access tokens. For mobile developers, it is important to ensure that the access token is stored securely on the device, and that it is not exposed to other apps or processes. API developers should ensure that their API is only accessible to clients that have a valid access token, and that the API properly validates the token before allowing access to the protected resource. Scopes are used in OAuth access tokens to limit the extent of access of a token, i.e. the specific resources and actions that the token is valid for. Scopes are typically defined by the API developer, and the client can request a specific scope when requesting an access token from the authorization server. This allows the API developer to fine-tune the level of access that different clients have to the API. Other security considerations for OAuth access tokens include the need to protect against replay attacks by including a nonce and timestamp in the token and using TLS for all communication between the client, the authorization server and the resource server. It is also important to rotate the access token. This can be done by using short lived tokens and refresh tokens which will allow the client to obtain a new access token without re-prompting the user for their credentials. By default, Jans Auth Server access tokens expire after 5 minutes.", "title": "Background"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#access-token-schema", "text": "claim Description active true or false . iss The URI of the issuer authorization server aud The audience, used by the client to verify it is the correct recipient. During registration, the client can specify additional_audience values iat When the client was issued, in seconds, e.g. 1514797822 exp When the token expires, in seconds, e.g. 1514797942 scope A space delimited list of scopes client_id Recipient of the token nbf Not before, which insures the token is only valid within a certain time window cnf Confirmation, used for TLS client certificate bound tokens It is possible to add additional claims to an access token via the Auth Server interception scripts. The preferred script is the update token script . You can also use the introspection script .", "title": "Access Token Schema"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#access-token-crypto-jwt", "text": "JWT access tokens are signed by Jans Auth Server using algorithms specified in the access_token_signing_alg_values_supported claim of the OpenID configuration endpoint response. Access tokens are signed with the standard OpenID signing key. Jans Auth Server supports TLS client certificate bound access tokens. After a successful mutual TLS client authentication, Jans Auth Server encodes the client certificate thumbprint (hash) in x5t#S256 confirmation method of the JWT or introspection JSON. Assuming the client uses the same certificate to establish a mutual TLS session with the API, the thumbprint in the access token can verify that this is the same client that obtained the access token. This feature is typically used in high security environments, as the operational cost of mutual TLS is material. Decoded JWT example { \"iss\" : \"https://server.example.com\" , \"sub\" : \"ty.webb@example.com\" , \"exp\" : 1493726400 , \"nbf\" : 1493722800 , \"cnf\" :{ \"x5t#S256\" : \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" } } Sample introspection response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"active\" : true , \"iss\" : \"https://server.example.com\" , \"sub\" : \"ty.webb@example.com\" , \"exp\" : 1493726400 , \"nbf\" : 1493722800 , \"cnf\" :{ \"x5t#S256\" : \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" } }", "title": "Access Token Crypto (JWT)"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#server-and-client-configurations", "text": "Access token lifetime is configurable at the server level via the accessTokenLifetime property. However, a client can override this value during client registration with the access_token_lifetime request parameter.", "title": "Server and Client configurations"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#revoke-access-token", "text": "Access token can be revoked via Revoke Endpoint", "title": "Revoke Access Token"}, {"location": "janssen-server/auth-server/tokens/oauth-refresh-tokens/", "tags": ["administration", "auth-server", "oauth", "refresh-token"], "text": "Background # Refresh tokens are an optimization that allows a client to renew an access token without having to re-authenticate. You should not issue a refresh token to untrusted clients, i.e. public clients. Server properties. # refreshTokenLifetime : Default: 14400 minutes - With this property, you can specify a longer lifetime then 5 days. Using the Jans Config API, you can set a client-specific refresh token lifetime. forceOfflineAccessScopeToEnableRefreshToken : Default: True - A good practice is for Auth Server to explicitly ask the subject to consent to the use of refresh tokens. To encourage this practice, by default, Auth Server requires that the client have the offline_access scope to issue a refresh token. persistRefreshToken : Default: True - Otherwise they are written to the cache clientRegDefaultToCodeFlowWithRefresh : Default: True - Set to False if you don't want web clients to get a refresh token. removeRefreshTokensForClientOnLogout : Default: True - Boolean value specifying whether to remove Refresh Tokens on logout. However if intention is to leave Refresh Token after logout, it's required to set it to false . skipRefreshTokenDuringRefreshing : Default: False - Boolean value specifying whether to skip refreshing tokens on refreshing. By default AS always creates new Refresh Token on refresh call to Token Endpoint. This property allows to avoid (skip) new Refresh Token creation. refreshTokenExtendLifetimeOnRotation : Default: False - Boolean value specifying whether to extend refresh tokens on rotation. By default lifetime is not extended, expiration date is set to date of previous Refresh Token. With this property it's possible to have all further Refresh Token have fixed (extended in relation to previuos Refresh Token) lifetime. checkUserPresenceOnRefreshToken : Default: False - Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check. Refresh Token Management # To revoke a token, a client can do so via the revocation endpoint (including revocation of all tokens by client_id ). online_access scope # If online_access scope is present then refresh token expires when the session ends (for example via front channel logout).", "title": "OAuth Refresh Tokens"}, {"location": "janssen-server/auth-server/tokens/oauth-refresh-tokens/#background", "text": "Refresh tokens are an optimization that allows a client to renew an access token without having to re-authenticate. You should not issue a refresh token to untrusted clients, i.e. public clients.", "title": "Background"}, {"location": "janssen-server/auth-server/tokens/oauth-refresh-tokens/#server-properties", "text": "refreshTokenLifetime : Default: 14400 minutes - With this property, you can specify a longer lifetime then 5 days. Using the Jans Config API, you can set a client-specific refresh token lifetime. forceOfflineAccessScopeToEnableRefreshToken : Default: True - A good practice is for Auth Server to explicitly ask the subject to consent to the use of refresh tokens. To encourage this practice, by default, Auth Server requires that the client have the offline_access scope to issue a refresh token. persistRefreshToken : Default: True - Otherwise they are written to the cache clientRegDefaultToCodeFlowWithRefresh : Default: True - Set to False if you don't want web clients to get a refresh token. removeRefreshTokensForClientOnLogout : Default: True - Boolean value specifying whether to remove Refresh Tokens on logout. However if intention is to leave Refresh Token after logout, it's required to set it to false . skipRefreshTokenDuringRefreshing : Default: False - Boolean value specifying whether to skip refreshing tokens on refreshing. By default AS always creates new Refresh Token on refresh call to Token Endpoint. This property allows to avoid (skip) new Refresh Token creation. refreshTokenExtendLifetimeOnRotation : Default: False - Boolean value specifying whether to extend refresh tokens on rotation. By default lifetime is not extended, expiration date is set to date of previous Refresh Token. With this property it's possible to have all further Refresh Token have fixed (extended in relation to previuos Refresh Token) lifetime. checkUserPresenceOnRefreshToken : Default: False - Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check.", "title": "Server properties."}, {"location": "janssen-server/auth-server/tokens/oauth-refresh-tokens/#refresh-token-management", "text": "To revoke a token, a client can do so via the revocation endpoint (including revocation of all tokens by client_id ).", "title": "Refresh Token Management"}, {"location": "janssen-server/auth-server/tokens/oauth-refresh-tokens/#online_access-scope", "text": "If online_access scope is present then refresh token expires when the session ends (for example via front channel logout).", "title": "online_access scope"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/", "tags": ["administration", "auth-server", "oauth", "access-token", "tx-token"], "text": "OAuth Transaction Tokens # Background # Transaction Tokens (Txn-Tokens) enable workloads in a trusted domain to ensure that user identity and authorization context of an external programmatic request, such as an API invocation, are preserved and available to all workloads that are invoked as part of processing such a request. Txn-Tokens also enable workloads within the trusted domain to optionally immutably assert to downstream workloads that they were invoked in the call chain of the request. Txn-Tokens are short-lived, signed JWTs that assert the identity of a user or a workload and assert an authorization context. The authorization context provides information expected to remain constant during the execution of a call as it passes through multiple workloads. Transaction Tokens spec Transaction Token JWT # Sample header { \"typ\" : \"N_A\" , \"alg\" : \"RS256\" , \"kid\" : \"identifier-to-key\" } Sample payload iss - a URN [RFC8141] that uniquely identifies the workload or the Txn-Token Service that created the Txn-Token. iat - the time at which the Txn-Token was created. aud - a URN [RFC8141] that uniquely identifies the audience of the Txn-Token. This MUST identify the trust domain in which the Txn-Token is used. exp - the time at which the Txn-Token expires. txn - the unique transaction identifier as defined in Section 2.2 of [RFC8417]. When used in the transaction token, it identifies the entire call chain. purp - a string defining the purpose or intent of this transaction sub - the unique identifier of the user or workload on whose behalf the call chain is being executed. The format of this claim MAY be a Subject Identifier. azd - a JSON object that contains values that remain constant in the call chain. rctx - a JSON object that describes the environmental context of the requested transaction. { \"aud\" : [ \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" , \"http://trusted.com\" ], \"rctx\" : { \"req_ip\" : \"69.151.72.123\" }, \"purp\" : \"tx_token\" , \"sub\" : \"3245675432\" , \"iss\" : \"https://yuriyz-adjusted-coyote.gluu.info\" , \"azd\" : { \"client_id\" : \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" }, \"txn\" : \"080c8f19-d9ee-4a26-852d-32e4fdc6ff6c\" , \"exp\" : 1705054542 , \"iat\" : 1705054362 } Transaction Token Obtain/Replace # Transaction Tokens can be obtained at Token Endpoint Sample request POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-adjusted-coyote.gluu.info Content-Type: application/x-www-form-urlencoded grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange&audience=http%3A%2F%2Ftrusted.com&subject_token=5fb696ac-638a-4dbf-81cd-27daeb61caf9&subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aaccess_token&requested_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Atxn_token&rctx=%7B%22req_ip%22%3A%2269.151.72.123%22%7D Sample response HTTP/ 1.1 200 Cache - Co ntr ol : n o - s t ore Co nne c t io n : Keep - Alive Co ntent - Le n g t h : 980 Co ntent - Type : applica t io n /jso n Da te : Fri , 12 Ja n 2024 10 : 12 : 40 GMT Keep - Alive : t imeou t = 5 , max= 100 Pragma : n o - cache Se t - Cookie : X - Correla t io n - Id=a 348 acce - d 9 c 1-424 a - a f 83-e4 d 75 f 7 f 3368 ; Secure; H tt pO nl y;H tt pO nl y S tr ic t - Tra ns por t - Securi t y : max - age= 31536000 ; i n cludeSubDomai ns X - Co ntent - Type - Op t io ns : n os n i ff X - Xss - Pro te c t io n : 1 ; mode=block { \"access_token\" : \"eyJraWQiOiJjb25uZWN0XzBlZGMxOTIyLTk1MjAtNDFkNi1iZGMyLTk3ZjdmYWMwMzRkMl9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOlsiZDYwZjIxYjctYjZkZC00MTQwLWIyMjgtZTZiZTA5OWJjM2NlIiwiaHR0cDovL3RydXN0ZWQuY29tIl0sInJlcV9jdHgiOnsicmVxX2lwIjoiNjkuMTUxLjcyLjEyMyJ9LCJzdWJfaWQiOiIiLCJpc3MiOiJodHRwczovL3l1cml5ei1hZGp1c3RlZC1jb3lvdGUuZ2x1dS5pbmZvIiwiYXpkIjp7ImNsaWVudF9pZCI6ImQ2MGYyMWI3LWI2ZGQtNDE0MC1iMjI4LWU2YmUwOTliYzNjZSJ9LCJ0eG4iOiIwODBjOGYxOS1kOWVlLTRhMjYtODUyZC0zMmU0ZmRjNmZmNmMiLCJleHAiOjE3MDUwNTQ1NDIsImlhdCI6MTcwNTA1NDM2Mn0.fpPFZpzxitbLw71RgO3O8uSOHJARp16H2THO4YAimJKWiczSE8-DvUAqulEW2nCNN3PRdojXWCe4ipxPSr_0ugLSFWhFKdpLmQqec_udhcV-UWiuGPLfq0XeKte60ESSvj5jgpaBNaaGS2vmFeSLdGrAx1CY2EH06OYrttOrgFFGqMhLJJ1Cpacqa0vmXnHi9gbrS-FIf2_4nNkQKMitQ-m-ec-0J02RjgkEL9zrzFwYNAoE1HEIZNFBhh7GqBejH0cXnR2tBOOz66z83SLqMTAZ-WyaMxmITHGLGLmHZOGyHdiIYME1rLXalrK58XHesMFtB-gae10Ey6w1OIgiAg\" , \"issued_token_type\" : \"urn:ietf:params:oauth:token-type:txn_token\" , \"token_type\" : \"N_A\" } Decoded transaction token JWT { \"aud\" : [ \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" , \"http://trusted.com\" ], \"rctx\" : { \"req_ip\" : \"69.151.72.123\" }, \"purp\" : \"tx_token\" , \"sub_id\" : \"\" , \"iss\" : \"https://yuriyz-adjusted-coyote.gluu.info\" , \"azd\" : { \"client_id\" : \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" }, \"txn\" : \"080c8f19-d9ee-4a26-852d-32e4fdc6ff6c\" , \"exp\" : 1705054542 , \"iat\" : 1705054362 } Replacement looks exactly the same with one different that subject_token must have previously obtained transaction token (not regular access_token ). View full obtain execution log here View full replace execution log here References # Transaction Tokens spec", "title": "OAuth Transaction Tokens"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/#oauth-transaction-tokens", "text": "", "title": "OAuth Transaction Tokens"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/#background", "text": "Transaction Tokens (Txn-Tokens) enable workloads in a trusted domain to ensure that user identity and authorization context of an external programmatic request, such as an API invocation, are preserved and available to all workloads that are invoked as part of processing such a request. Txn-Tokens also enable workloads within the trusted domain to optionally immutably assert to downstream workloads that they were invoked in the call chain of the request. Txn-Tokens are short-lived, signed JWTs that assert the identity of a user or a workload and assert an authorization context. The authorization context provides information expected to remain constant during the execution of a call as it passes through multiple workloads. Transaction Tokens spec", "title": "Background"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/#transaction-token-jwt", "text": "Sample header { \"typ\" : \"N_A\" , \"alg\" : \"RS256\" , \"kid\" : \"identifier-to-key\" } Sample payload iss - a URN [RFC8141] that uniquely identifies the workload or the Txn-Token Service that created the Txn-Token. iat - the time at which the Txn-Token was created. aud - a URN [RFC8141] that uniquely identifies the audience of the Txn-Token. This MUST identify the trust domain in which the Txn-Token is used. exp - the time at which the Txn-Token expires. txn - the unique transaction identifier as defined in Section 2.2 of [RFC8417]. When used in the transaction token, it identifies the entire call chain. purp - a string defining the purpose or intent of this transaction sub - the unique identifier of the user or workload on whose behalf the call chain is being executed. The format of this claim MAY be a Subject Identifier. azd - a JSON object that contains values that remain constant in the call chain. rctx - a JSON object that describes the environmental context of the requested transaction. { \"aud\" : [ \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" , \"http://trusted.com\" ], \"rctx\" : { \"req_ip\" : \"69.151.72.123\" }, \"purp\" : \"tx_token\" , \"sub\" : \"3245675432\" , \"iss\" : \"https://yuriyz-adjusted-coyote.gluu.info\" , \"azd\" : { \"client_id\" : \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" }, \"txn\" : \"080c8f19-d9ee-4a26-852d-32e4fdc6ff6c\" , \"exp\" : 1705054542 , \"iat\" : 1705054362 }", "title": "Transaction Token JWT"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/#transaction-token-obtainreplace", "text": "Transaction Tokens can be obtained at Token Endpoint Sample request POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-adjusted-coyote.gluu.info Content-Type: application/x-www-form-urlencoded grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange&audience=http%3A%2F%2Ftrusted.com&subject_token=5fb696ac-638a-4dbf-81cd-27daeb61caf9&subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aaccess_token&requested_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Atxn_token&rctx=%7B%22req_ip%22%3A%2269.151.72.123%22%7D Sample response HTTP/ 1.1 200 Cache - Co ntr ol : n o - s t ore Co nne c t io n : Keep - Alive Co ntent - Le n g t h : 980 Co ntent - Type : applica t io n /jso n Da te : Fri , 12 Ja n 2024 10 : 12 : 40 GMT Keep - Alive : t imeou t = 5 , max= 100 Pragma : n o - cache Se t - Cookie : X - Correla t io n - Id=a 348 acce - d 9 c 1-424 a - a f 83-e4 d 75 f 7 f 3368 ; Secure; H tt pO nl y;H tt pO nl y S tr ic t - Tra ns por t - Securi t y : max - age= 31536000 ; i n cludeSubDomai ns X - Co ntent - Type - Op t io ns : n os n i ff X - Xss - Pro te c t io n : 1 ; mode=block { \"access_token\" : \"eyJraWQiOiJjb25uZWN0XzBlZGMxOTIyLTk1MjAtNDFkNi1iZGMyLTk3ZjdmYWMwMzRkMl9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOlsiZDYwZjIxYjctYjZkZC00MTQwLWIyMjgtZTZiZTA5OWJjM2NlIiwiaHR0cDovL3RydXN0ZWQuY29tIl0sInJlcV9jdHgiOnsicmVxX2lwIjoiNjkuMTUxLjcyLjEyMyJ9LCJzdWJfaWQiOiIiLCJpc3MiOiJodHRwczovL3l1cml5ei1hZGp1c3RlZC1jb3lvdGUuZ2x1dS5pbmZvIiwiYXpkIjp7ImNsaWVudF9pZCI6ImQ2MGYyMWI3LWI2ZGQtNDE0MC1iMjI4LWU2YmUwOTliYzNjZSJ9LCJ0eG4iOiIwODBjOGYxOS1kOWVlLTRhMjYtODUyZC0zMmU0ZmRjNmZmNmMiLCJleHAiOjE3MDUwNTQ1NDIsImlhdCI6MTcwNTA1NDM2Mn0.fpPFZpzxitbLw71RgO3O8uSOHJARp16H2THO4YAimJKWiczSE8-DvUAqulEW2nCNN3PRdojXWCe4ipxPSr_0ugLSFWhFKdpLmQqec_udhcV-UWiuGPLfq0XeKte60ESSvj5jgpaBNaaGS2vmFeSLdGrAx1CY2EH06OYrttOrgFFGqMhLJJ1Cpacqa0vmXnHi9gbrS-FIf2_4nNkQKMitQ-m-ec-0J02RjgkEL9zrzFwYNAoE1HEIZNFBhh7GqBejH0cXnR2tBOOz66z83SLqMTAZ-WyaMxmITHGLGLmHZOGyHdiIYME1rLXalrK58XHesMFtB-gae10Ey6w1OIgiAg\" , \"issued_token_type\" : \"urn:ietf:params:oauth:token-type:txn_token\" , \"token_type\" : \"N_A\" } Decoded transaction token JWT { \"aud\" : [ \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" , \"http://trusted.com\" ], \"rctx\" : { \"req_ip\" : \"69.151.72.123\" }, \"purp\" : \"tx_token\" , \"sub_id\" : \"\" , \"iss\" : \"https://yuriyz-adjusted-coyote.gluu.info\" , \"azd\" : { \"client_id\" : \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" }, \"txn\" : \"080c8f19-d9ee-4a26-852d-32e4fdc6ff6c\" , \"exp\" : 1705054542 , \"iat\" : 1705054362 } Replacement looks exactly the same with one different that subject_token must have previously obtained transaction token (not regular access_token ). View full obtain execution log here View full replace execution log here", "title": "Transaction Token Obtain/Replace"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/#references", "text": "Transaction Tokens spec", "title": "References"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/", "tags": ["administration", "auth-server", "token", "id token", "customize id_token"], "text": "OpenID Connect ID Token # Defined in Section 2 of OpenID Connect Core 1.0 : The primary extension that OpenID Connect makes to OAuth 2.0 to enable End-Users to be Authenticated is the ID Token data structure. The ID Token is a security token that contains Claims about the Authentication of an End-User by an Authorization Server when using a Client, and potentially other requested Claims. The ID Token is represented as a JSON Web Token (JWT) [JWT]. The ID Token is similar to a SAML 2.0 Assertion, which must contain an Authentication statement, and may optionally contain an Attribute statement, defined in the spec as: Authentication statements: These are created by the party that successfully authenticated a user. At a minimum, they describe the particular means used to authenticate the user and the specific time at which the authentication took place. Attribute statements: These contain specific identifying attributes about the subject (for example, that user \u201cJohn Doe\u201d has \u201cGold\u201d card status). The ID Token is a standard JWT, and can use signing and encryption depending on the configuration preferences of the client. A sample payload for a Jans Auth Server id_token is below: { \"iss\": \"https://idp.example.tld\", <-- OP hostname \"aud\": \"bd0469f7-f80a-4595-bd52-df9826f0a2f4\", <-- client_id \"sub\": \"0a9ca356-6130-4032-91c6-a2dfe4e19804\", <-- in this case, a pairwise identifer \"iat\": 1672373703, <-- issued at \"auth_time\": 1672373700, <-- when user authenticated \"acr\": \"basic\", <-- how user authenticated \"amr\": [\"10\"], <-- Extra authn details \"nonce\": \"1u0y3ii\", <-- client should verify \"sid\": \"5f01565c-f2dc-4b4b-af8a-ab1578a5dbe3\", <-- session id handle \"jansOpenIDConnectVersion\": \"openidconnect-1.0\" <-- OpenID version } A great tool if you want to decode a JWT is Auth0's https://jwt.io/ . Notice that a basic ID Token, like the one above, contains details about the authentication event, not user claims. You can configure the client to \"include claims in id_token\", or you can set a Auth Server configuration property, legacyIdTokenClaims to True to set the behavior for all clients. Obtaining an ID Token # The client may obtain an ID Token in the authorization response, from the token endpoint, or both. Note, if you intend to use the Code Flow, and you don't intend to validate the c_hash or s_hash values in the ID Token returned from the authorization endpoint, don't check id_token in the response_type for the authorization endpoint, as it will waste compute and storage generating a token you don't need. Validating an ID Token # At a minimum, client developers should always validate the following: Signature of the ID token iss make sure the ID Token was issued by the OP you trust aud make sure the ID Token was issued to your client_id exp make sure the token is not expired nonce make sure the id_token correlates to your original authn request Using the ID Token as an access token for API's # Don't do this. The ID Token is an identity assertion, not an access token. It may be passed in the payload to an API, but it should not be used in lieu of an OAuth access token! Fundamentally, the id_token details how a person was authenticated, not which API's a client is authorized to call. Also, OAuth access tokens are short lived, while the expiration of an identity assertion is much longer. Customizing claims in an id_token # The UpdateTokenType can be used in the following scenarios: In addition to the default claims in an ID token ( iss , aud , exp etc), additional custom claims can be added to an ID token. You can also change the default value of a claim", "title": "OpenID id_token"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/#openid-connect-id-token", "text": "Defined in Section 2 of OpenID Connect Core 1.0 : The primary extension that OpenID Connect makes to OAuth 2.0 to enable End-Users to be Authenticated is the ID Token data structure. The ID Token is a security token that contains Claims about the Authentication of an End-User by an Authorization Server when using a Client, and potentially other requested Claims. The ID Token is represented as a JSON Web Token (JWT) [JWT]. The ID Token is similar to a SAML 2.0 Assertion, which must contain an Authentication statement, and may optionally contain an Attribute statement, defined in the spec as: Authentication statements: These are created by the party that successfully authenticated a user. At a minimum, they describe the particular means used to authenticate the user and the specific time at which the authentication took place. Attribute statements: These contain specific identifying attributes about the subject (for example, that user \u201cJohn Doe\u201d has \u201cGold\u201d card status). The ID Token is a standard JWT, and can use signing and encryption depending on the configuration preferences of the client. A sample payload for a Jans Auth Server id_token is below: { \"iss\": \"https://idp.example.tld\", <-- OP hostname \"aud\": \"bd0469f7-f80a-4595-bd52-df9826f0a2f4\", <-- client_id \"sub\": \"0a9ca356-6130-4032-91c6-a2dfe4e19804\", <-- in this case, a pairwise identifer \"iat\": 1672373703, <-- issued at \"auth_time\": 1672373700, <-- when user authenticated \"acr\": \"basic\", <-- how user authenticated \"amr\": [\"10\"], <-- Extra authn details \"nonce\": \"1u0y3ii\", <-- client should verify \"sid\": \"5f01565c-f2dc-4b4b-af8a-ab1578a5dbe3\", <-- session id handle \"jansOpenIDConnectVersion\": \"openidconnect-1.0\" <-- OpenID version } A great tool if you want to decode a JWT is Auth0's https://jwt.io/ . Notice that a basic ID Token, like the one above, contains details about the authentication event, not user claims. You can configure the client to \"include claims in id_token\", or you can set a Auth Server configuration property, legacyIdTokenClaims to True to set the behavior for all clients.", "title": "OpenID Connect ID Token"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/#obtaining-an-id-token", "text": "The client may obtain an ID Token in the authorization response, from the token endpoint, or both. Note, if you intend to use the Code Flow, and you don't intend to validate the c_hash or s_hash values in the ID Token returned from the authorization endpoint, don't check id_token in the response_type for the authorization endpoint, as it will waste compute and storage generating a token you don't need.", "title": "Obtaining an ID Token"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/#validating-an-id-token", "text": "At a minimum, client developers should always validate the following: Signature of the ID token iss make sure the ID Token was issued by the OP you trust aud make sure the ID Token was issued to your client_id exp make sure the token is not expired nonce make sure the id_token correlates to your original authn request", "title": "Validating an ID Token"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/#using-the-id-token-as-an-access-token-for-apis", "text": "Don't do this. The ID Token is an identity assertion, not an access token. It may be passed in the payload to an API, but it should not be used in lieu of an OAuth access token! Fundamentally, the id_token details how a person was authenticated, not which API's a client is authorized to call. Also, OAuth access tokens are short lived, while the expiration of an identity assertion is much longer.", "title": "Using the ID Token as an access token for API's"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/#customizing-claims-in-an-id_token", "text": "The UpdateTokenType can be used in the following scenarios: In addition to the default claims in an ID token ( iss , aud , exp etc), additional custom claims can be added to an ID token. You can also change the default value of a claim", "title": "Customizing claims in an id_token"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/", "tags": ["administration", "auth-server", "token", "userinfo-token"], "text": "Userinfo JWT # An OpenID Connect client, after obtaining an access token, can present it at the Userinfo endpoint to obtain the Userinfo JWT token. The Userinfo response is is described in OpenID Core 5.4.3 , and directs the developer to: Verify that the OP that responded was the intended OP through a TLS server certificate check If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. If the response was signed, the Client SHOULD validate the signature. Below is an example of the Userinfo claims for the default Jans Admin user: { \"sub\": \"e25c4146-ce9d-465e-9b59-b9d959bdfe3a\", \"email\": \"admin@issuer.tld\", \"given_name\": \"Admin\", \"family_name\": \"User\", \"name\": \"Default Admin User\", \"middle_name\": \"Admin\", \"nickname\": \"Admin\", \"email_verified\": true, \"inum\": \"e25c4146-ce9d-465e-9b59-b9d959bdfe3a\", \"jansAdminUIRole\": [\"api-admin\"] } Selective disclosure # Domains can limit the claims released to a client from the Userinfo endpoint by associating only the OpenID scopes required by that client. You can also define new scopes, and associate any user claims with them. Note, clients still must request the scopes they need for an access token. For example, a client may be authorize Requesting individual claims # If you want to use the claims parameter, you will have to first enable this feature in the Auth Server properties: set claimsParameterSupported=True . This is not a recommended configuration, because the claims parameter bypasses the privacy protection of the OpenID scopes construct. Dynamic Scopes / Interception Script # If you need to call an API to render scopes or scope values on the fly, you should see the Dynamic Scopes interception script. Userinfo formatter # There is a configuration property dateFormatterPatterns which can be used for format date claims. Example: {'dateFormatterPatterns': {'userinfo':'yyyy-MM-dd'}} . Language support # The default value for the configuration parameter claimsLocalesSupported is ['en'] . Currently, only the name and description supports localization. You will also need to make a proper request and provide the associated values for the claim in the database.", "title": "OpenID Userinfo Token"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#userinfo-jwt", "text": "An OpenID Connect client, after obtaining an access token, can present it at the Userinfo endpoint to obtain the Userinfo JWT token. The Userinfo response is is described in OpenID Core 5.4.3 , and directs the developer to: Verify that the OP that responded was the intended OP through a TLS server certificate check If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. If the response was signed, the Client SHOULD validate the signature. Below is an example of the Userinfo claims for the default Jans Admin user: { \"sub\": \"e25c4146-ce9d-465e-9b59-b9d959bdfe3a\", \"email\": \"admin@issuer.tld\", \"given_name\": \"Admin\", \"family_name\": \"User\", \"name\": \"Default Admin User\", \"middle_name\": \"Admin\", \"nickname\": \"Admin\", \"email_verified\": true, \"inum\": \"e25c4146-ce9d-465e-9b59-b9d959bdfe3a\", \"jansAdminUIRole\": [\"api-admin\"] }", "title": "Userinfo JWT"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#selective-disclosure", "text": "Domains can limit the claims released to a client from the Userinfo endpoint by associating only the OpenID scopes required by that client. You can also define new scopes, and associate any user claims with them. Note, clients still must request the scopes they need for an access token. For example, a client may be authorize", "title": "Selective disclosure"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#requesting-individual-claims", "text": "If you want to use the claims parameter, you will have to first enable this feature in the Auth Server properties: set claimsParameterSupported=True . This is not a recommended configuration, because the claims parameter bypasses the privacy protection of the OpenID scopes construct.", "title": "Requesting individual claims"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#dynamic-scopes-interception-script", "text": "If you need to call an API to render scopes or scope values on the fly, you should see the Dynamic Scopes interception script.", "title": "Dynamic Scopes / Interception Script"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#userinfo-formatter", "text": "There is a configuration property dateFormatterPatterns which can be used for format date claims. Example: {'dateFormatterPatterns': {'userinfo':'yyyy-MM-dd'}} .", "title": "Userinfo formatter"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#language-support", "text": "The default value for the configuration parameter claimsLocalesSupported is ['en'] . Currently, only the name and description supports localization. You will also need to make a proper request and provide the associated values for the claim in the database.", "title": "Language support"}, {"location": "janssen-server/auth-server/tokens/uma-rpt-token/", "tags": ["administration", "auth-server", "token", "rpt-token"], "text": "Background # The UMA requesting party token (RPT) is an OAuth access token associated with the UMA grant. An RPT is unique to a requesting party, client, authorization server, resource server, and resource owner. The client uses the RPT in the Authorization header of an API request. The RPT bearer token conveys that UMA policy evaluation was successful on Auth Server. The Client may also present the RPT token while making a request to Auth Server for a new RPT, for example to up-scope or down-scope a token. For more information on UMA, see the specifications: * User-Managed Access (UMA) 2.0 Grant for OAuth 2.0 Authorization * Federated Authorization for User-Managed Access (UMA) 2.0 Server properties # umaRptAsJwt Default: False - : Reference token is the default umaRptLifetime Default: 3600 seconds - : 60 minutes introspectionAccessTokenMustHaveUmaProtectionScope Default: False - : umaGrantAccessIfNoPolicies Default: False - : umaTicketLifetime Default: 3600 seconds - : 60 minutes - Returned by the Resource Server to the Client for presentation at the UMA token endpoint. The ticket is the equivalent of the code in the OAuth code flow. umaAddScopesAutomatically Default: True - : umaPctLifetime Default: 1728000 seconds - : The PCT is a pushed claim token that references a previous claims gathering flow, so you don't have to bother the subject again for this information. umaValidateClaimToken Default: False - : umaRestrictResourceToAssociatedClient Default: False - :", "title": "UMA RPT Token"}, {"location": "janssen-server/auth-server/tokens/uma-rpt-token/#background", "text": "The UMA requesting party token (RPT) is an OAuth access token associated with the UMA grant. An RPT is unique to a requesting party, client, authorization server, resource server, and resource owner. The client uses the RPT in the Authorization header of an API request. The RPT bearer token conveys that UMA policy evaluation was successful on Auth Server. The Client may also present the RPT token while making a request to Auth Server for a new RPT, for example to up-scope or down-scope a token. For more information on UMA, see the specifications: * User-Managed Access (UMA) 2.0 Grant for OAuth 2.0 Authorization * Federated Authorization for User-Managed Access (UMA) 2.0", "title": "Background"}, {"location": "janssen-server/auth-server/tokens/uma-rpt-token/#server-properties", "text": "umaRptAsJwt Default: False - : Reference token is the default umaRptLifetime Default: 3600 seconds - : 60 minutes introspectionAccessTokenMustHaveUmaProtectionScope Default: False - : umaGrantAccessIfNoPolicies Default: False - : umaTicketLifetime Default: 3600 seconds - : 60 minutes - Returned by the Resource Server to the Client for presentation at the UMA token endpoint. The ticket is the equivalent of the code in the OAuth code flow. umaAddScopesAutomatically Default: True - : umaPctLifetime Default: 1728000 seconds - : The PCT is a pushed claim token that references a previous claims gathering flow, so you don't have to bother the subject again for this information. umaValidateClaimToken Default: False - : umaRestrictResourceToAssociatedClient Default: False - :", "title": "Server properties"}, {"location": "janssen-server/auth-server/uma-features/claims-gathering-endpoint/", "tags": ["administration", "auth-server", "uma", "feature", "endpoint"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Claims Gathering Endpoint"}, {"location": "janssen-server/auth-server/uma-features/claims-gathering-endpoint/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/uma-features/claims-gathering-endpoint/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/uma-features/claims-gathering-endpoint/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/uma-features/rpt-endpoint/", "tags": ["administration", "auth-server", "uma", "feature", "endpoint"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "RPT Endpoint"}, {"location": "janssen-server/auth-server/uma-features/rpt-endpoint/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/uma-features/rpt-endpoint/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/uma-features/rpt-endpoint/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/config-guide/custom-assets-configuration/", "tags": ["administration", "configuration", "custom assets"], "text": "Custom Assets Configuration # The Janssen Server provides multiple configuration tools to configure custom assets. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using The Command Line # In the Janssen Server, you can deploy custom assets using the command line. To get the details of Janssen command line operations relevant to the custom assets, check the operations under the JansAssets task using the command below. Command jans cli --info JansAssets Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 Operation ID: get-asset-by-inum Description: Gets an asset by inum - unique identifier Parameters: inum: Asset Inum [string] Operation ID: delete-asset Description: Delete an asset Parameters: inum: Asset identifier [string] Operation ID: get-asset-by-name Description: Fetch asset by name. Parameters: name: Asset Name [string] Operation ID: get-all-assets Description: Gets all Jans assets. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for searching [string] Operation ID: get-asset-services Description: Gets asset services Operation ID: get-asset-types Description: Get valid asset types Operation ID: put-asset Description: Update existing asset Schema: AssetForm Operation ID: post-new-asset Description: Upload new asset Schema: AssetForm To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample AssetForm Get All Current Custom Assets # Use the operation ID get-all-assets to get all the currently configured custom assets on the Janssen Server. Command jans cli --operation-id get-all-assets Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 { \"start\" : 0 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 3 , \"entries\" : [ { \"dn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" , \"inum\" : \"61edc29d-45f8-4ab9-8c9a-7b39e4cbe440\" , \"fileName\" : \"p2.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:36:08\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" }, { \"dn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" , \"inum\" : \"835c7a68-57b1-4e39-8d2a-2a3963f2a92f\" , \"fileName\" : \"p1.properties\" , \"description\" : \"updated thrice Valid text description\" , \"document\" : \"cHJvcGVydGllcwo=\\r\\n\" , \"jansService\" : [ \"jans-auth\" ], \"jansEnabled\" : false , \"baseDn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" }, { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" } ] } Get Custom Asset By inum # With get-asset-by-inum operation-id, we can get any specific asset matched with inum . If we know the inum , we can simply use the below command: Command jans cli --operation-id get-asset-by-inum \\ --url-suffix inum:61edc29d-45f8-4ab9-8c9a-7b39e4cbe440 It returns the details as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" , \"inum\" : \"61edc29d-45f8-4ab9-8c9a-7b39e4cbe440\" , \"fileName\" : \"p2.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:36:08\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" } Get Custom Asset By Name # With get-asset-by-name operation-id, we can get any specific asset matched with name . If we know the name , we can simply use the below command: Command jans cli --operation-id get-asset-by-name \\ --url-suffix name:p1.properties It returns the details as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" , \"inum\" : \"835c7a68-57b1-4e39-8d2a-2a3963f2a92f\" , \"fileName\" : \"p1.properties\" , \"description\" : \"updated thrice Valid text description\" , \"document\" : \"cHJvcGVydGllcwo=\\r\\n\" , \"jansService\" : [ \"jans-auth\" ], \"jansEnabled\" : false , \"baseDn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" } ] } Get Services # Get the list of Janssen Server services that support custom assets by performing get-asset-services operation. Command jans cli --operation-id get-asset-services Sample Output 1 2 3 4 5 6 7 8 9 10 [ \"jans-auth\", \"jans-casa\", \"jans-config-api\", \"jans-fido2\", \"jans-link\", \"jans-lock\", \"jans-scim\", \"jans-keycloak-link\" ] Get Valid Asset Types # Get the asset types of your Janssen Server by performing get-asset-types operation. Command jans cli --operation-id get-asset-types Sample Output 1 2 3 4 5 6 7 8 9 10 11 [ \"properties\", \"jar\", \"xhtml\", \"js\", \"css\", \"png\", \"gif\", \"jpg\", \"jpeg\" ] Add New Custom Asset # To create a new asset, we can use post-new-asset operation id. As shown in the output for --info command, the post-new-asset operation requires data to be sent according to AssetForm schema. To see the schema, use the command below: Command jans cli --schema AssetForm For better understanding, the Janssen Server also provides a sample of data to be sent to the server. This sample conforms to the schema above. Use the command below to get the sample. Command jans cli --schema-sample AssetForm Using the schema and the example above, we have added below data to the file /tmp/add-asset.json . Example below will load p3.properties file as a custom asset to the jans-auth service. Input 1 2 3 4 5 6 7 8 9 10 11 12 { \"document\" : { \"fileName\" : \"p3.properties\" , \"description\" : \"text description\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 144 , \"jansEnabled\" : true }, \"assetFile\" : \"/tmp/p3.properties\" } Now let's post this Assert to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-new-asset \\ --data /tmp/add-asset.json Update Existing Custom Assets # Use the put-asset operation to update an existing asset. This operation uses same schema as add new asset operation. For example, assuming that there is an existing asset as show below: Existing Asset 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" } Note assetFile attribute is optional for update operation as there may be scenario where only metadata of an asset is to be updated. Now to update level of this asset to 6, create a text file with following content in it. Let's name this text file as /tmp/update-asset.json Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"document\" : { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 6 , \"jansEnabled\" : true , }, \"assetFile\" : \"/tmp/p.properties\" } Now use the command below to update the asset with new value for level. Sample Command jans cli --operation-id put-asset \\ --data /tmp/update-asset.json Upon successful execution, this command will return with updated asset values. Return values 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 6 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" } Delete Custom Asset # You can delete any custom asset by its inum value. Command jans cli --operation-id delete-asset \\ --url-suffix inum:61edc29d-45f8-4ab9-8c9a-7b39e4cbe440 Using Text-based UI # In Janssen, You can deploy custom asset using the Text-Based UI also. You can start TUI using the command below: Command jans tui Asset Screen # Navigate to Assets tab to open the Assets screen as shown in the image below. To get the list of currently added Assets, bring the control to the Search box (using the tab key), and press Enter. Type the search string to search for Asset with matching inum , or File Name or Description Use the Add Asset button to create a new asset. From the screen below, select the custom asset that needs to be uploaded and select the Janssen Server service to which the asset will be uploaded. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the custom assets. Endpoint details are published in the Swagger document .", "title": "Custom Assets Configuration"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#custom-assets-configuration", "text": "The Janssen Server provides multiple configuration tools to configure custom assets. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Custom Assets Configuration"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#using-the-command-line", "text": "In the Janssen Server, you can deploy custom assets using the command line. To get the details of Janssen command line operations relevant to the custom assets, check the operations under the JansAssets task using the command below. Command jans cli --info JansAssets Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 Operation ID: get-asset-by-inum Description: Gets an asset by inum - unique identifier Parameters: inum: Asset Inum [string] Operation ID: delete-asset Description: Delete an asset Parameters: inum: Asset identifier [string] Operation ID: get-asset-by-name Description: Fetch asset by name. Parameters: name: Asset Name [string] Operation ID: get-all-assets Description: Gets all Jans assets. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for searching [string] Operation ID: get-asset-services Description: Gets asset services Operation ID: get-asset-types Description: Get valid asset types Operation ID: put-asset Description: Update existing asset Schema: AssetForm Operation ID: post-new-asset Description: Upload new asset Schema: AssetForm To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample AssetForm", "title": "Using The Command Line"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#get-all-current-custom-assets", "text": "Use the operation ID get-all-assets to get all the currently configured custom assets on the Janssen Server. Command jans cli --operation-id get-all-assets Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 { \"start\" : 0 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 3 , \"entries\" : [ { \"dn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" , \"inum\" : \"61edc29d-45f8-4ab9-8c9a-7b39e4cbe440\" , \"fileName\" : \"p2.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:36:08\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" }, { \"dn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" , \"inum\" : \"835c7a68-57b1-4e39-8d2a-2a3963f2a92f\" , \"fileName\" : \"p1.properties\" , \"description\" : \"updated thrice Valid text description\" , \"document\" : \"cHJvcGVydGllcwo=\\r\\n\" , \"jansService\" : [ \"jans-auth\" ], \"jansEnabled\" : false , \"baseDn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" }, { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" } ] }", "title": "Get All Current Custom Assets"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#get-custom-asset-by-inum", "text": "With get-asset-by-inum operation-id, we can get any specific asset matched with inum . If we know the inum , we can simply use the below command: Command jans cli --operation-id get-asset-by-inum \\ --url-suffix inum:61edc29d-45f8-4ab9-8c9a-7b39e4cbe440 It returns the details as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" , \"inum\" : \"61edc29d-45f8-4ab9-8c9a-7b39e4cbe440\" , \"fileName\" : \"p2.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:36:08\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" }", "title": "Get Custom Asset By inum"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#get-custom-asset-by-name", "text": "With get-asset-by-name operation-id, we can get any specific asset matched with name . If we know the name , we can simply use the below command: Command jans cli --operation-id get-asset-by-name \\ --url-suffix name:p1.properties It returns the details as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" , \"inum\" : \"835c7a68-57b1-4e39-8d2a-2a3963f2a92f\" , \"fileName\" : \"p1.properties\" , \"description\" : \"updated thrice Valid text description\" , \"document\" : \"cHJvcGVydGllcwo=\\r\\n\" , \"jansService\" : [ \"jans-auth\" ], \"jansEnabled\" : false , \"baseDn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" } ] }", "title": "Get Custom Asset By Name"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#get-services", "text": "Get the list of Janssen Server services that support custom assets by performing get-asset-services operation. Command jans cli --operation-id get-asset-services Sample Output 1 2 3 4 5 6 7 8 9 10 [ \"jans-auth\", \"jans-casa\", \"jans-config-api\", \"jans-fido2\", \"jans-link\", \"jans-lock\", \"jans-scim\", \"jans-keycloak-link\" ]", "title": "Get Services"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#get-valid-asset-types", "text": "Get the asset types of your Janssen Server by performing get-asset-types operation. Command jans cli --operation-id get-asset-types Sample Output 1 2 3 4 5 6 7 8 9 10 11 [ \"properties\", \"jar\", \"xhtml\", \"js\", \"css\", \"png\", \"gif\", \"jpg\", \"jpeg\" ]", "title": "Get Valid Asset Types"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#add-new-custom-asset", "text": "To create a new asset, we can use post-new-asset operation id. As shown in the output for --info command, the post-new-asset operation requires data to be sent according to AssetForm schema. To see the schema, use the command below: Command jans cli --schema AssetForm For better understanding, the Janssen Server also provides a sample of data to be sent to the server. This sample conforms to the schema above. Use the command below to get the sample. Command jans cli --schema-sample AssetForm Using the schema and the example above, we have added below data to the file /tmp/add-asset.json . Example below will load p3.properties file as a custom asset to the jans-auth service. Input 1 2 3 4 5 6 7 8 9 10 11 12 { \"document\" : { \"fileName\" : \"p3.properties\" , \"description\" : \"text description\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 144 , \"jansEnabled\" : true }, \"assetFile\" : \"/tmp/p3.properties\" } Now let's post this Assert to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-new-asset \\ --data /tmp/add-asset.json", "title": "Add New Custom Asset"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#update-existing-custom-assets", "text": "Use the put-asset operation to update an existing asset. This operation uses same schema as add new asset operation. For example, assuming that there is an existing asset as show below: Existing Asset 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" } Note assetFile attribute is optional for update operation as there may be scenario where only metadata of an asset is to be updated. Now to update level of this asset to 6, create a text file with following content in it. Let's name this text file as /tmp/update-asset.json Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"document\" : { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 6 , \"jansEnabled\" : true , }, \"assetFile\" : \"/tmp/p.properties\" } Now use the command below to update the asset with new value for level. Sample Command jans cli --operation-id put-asset \\ --data /tmp/update-asset.json Upon successful execution, this command will return with updated asset values. Return values 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 6 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" }", "title": "Update Existing Custom Assets"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#delete-custom-asset", "text": "You can delete any custom asset by its inum value. Command jans cli --operation-id delete-asset \\ --url-suffix inum:61edc29d-45f8-4ab9-8c9a-7b39e4cbe440", "title": "Delete Custom Asset"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#using-text-based-ui", "text": "In Janssen, You can deploy custom asset using the Text-Based UI also. You can start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#asset-screen", "text": "Navigate to Assets tab to open the Assets screen as shown in the image below. To get the list of currently added Assets, bring the control to the Search box (using the tab key), and press Enter. Type the search string to search for Asset with matching inum , or File Name or Description Use the Add Asset button to create a new asset. From the screen below, select the custom asset that needs to be uploaded and select the Janssen Server service to which the asset will be uploaded.", "title": "Asset Screen"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the custom assets. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/custom-scripts-config/", "tags": ["administration", "configuration", "custom-scripts"], "text": "Custom Scripts # Prerequisite: Know how to use the Janssen CLI in command-line mode Interception scripts can be used to implement custom business logic for authentication, authorization, and more in a way that is upgrade-proof and doesn't require forking the Gluu Server code. Using Janssen CLI, we can manage custom scripts as well. Let's get the task information using below command: jans cli --info CustomScripts In return we gets each of the sub-task details: Operation ID: get-config-scripts Description: Gets a list of custom scripts. Operation ID: post-config-scripts Description: Adds a new custom script. Schema: /components/schemas/CustomScript Operation ID: put-config-scripts Description: Updates a custom script. Schema: /components/schemas/CustomScript Operation ID: get-config-scripts-by-type Description: Gets list of scripts by type. url-suffix: type Operation ID: get-config-scripts-by-inum Description: Gets a script by Inum. url-suffix: inum Operation ID: delete-config-scripts-by-inum Description: Deletes a custom script. url-suffix: inum To get sample schema type jans cli --schema <schma>, for example jans cli --schema CustomScript Let's perform each of this operation. Find list of Custom scripts # get-config-scripts operation id can be used to get a list of custom scripts of the Janssen Server. The command line is: jans cli --operation-id get-config-scripts It returns all the custom scripts of the Janssen Server. Adds a New Custom Script # If we look at the description of this operation we see it supports schema: Operation ID: post-config-scripts Description: Adds a new custom script. Schema: /components/schemas/CustomScript So, let's get the schema first: jans cli CustomScript > /tmp/cs.json { \"dn\": null, \"inum\": null, \"name\": \"string\", \"aliases\": [], \"description\": null, \"script\": \"_file /root/script.py\", \"scriptType\": \"INTROSPECTION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": { \"value1\": null, \"value2\": null, \"description\": null, \"hide\": true }, \"level\": \"integer\", \"revision\": 0, \"enabled\": false, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } We need to fill some of these properties with valid data to add this new script. { \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"_file /root/client_registration.py\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [{ \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" }], \"configurationProperties\": null, \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } We can remove dn , inum . As because these two items are auto generated with random value. Also we see aliases , moduleproperties and configurationProperties are the array type keys . So we need to put data into [] otherwise it will raise an error. We can also use null value if we need to skip any of them. For scriptType we can choose only selected type of script from the below list. Name of the type of scripts # PERSON_AUTHENTICATION, INTROSPECTION, RESOURCE_OWNER_PASSWORD_CREDENTIALS, APPLICATION_SESSION, CACHE_REFRESH, CLIENT_REGISTRATION, ID_GENERATOR, UMA_RPT_POLICY, UMA_RPT_CLAIMS, UMA_CLAIMS_GATHERING, CONSENT_GATHERING, DYNAMIC_SCOPE, SPONTANEOUS_SCOPE, END_SESSION, POST_AUTHN, SCIM, CIBA_END_USER_NOTIFICATION, PERSISTENCE_EXTENSION, IDP, UPDATE_TOKEN Programming Language # Two types of programming language available there. Those are Python and JavaScript . We can choose any of them regarding the script we need to add. Alright, let's add the script using the command line we have: jans cli --operation-id post-config-scripts --data /tmp/cs.json Getting access token for scope https://jans.io/oauth/config/scripts.write Server Response: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": null, \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } Update an existing Custom Script # put-config-scripts operation-id can be used to update any existing script on the Janssen server. Operation ID: put-config-scripts Description: Updates a custom script. Schema: /components/schemas/CustomScript As we created a custom script in the above , let's update that one. So we know the dn:inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans and inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 here. In this case, I have modified as below: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"_file /root/client_registrationj.py\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [{ \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" }], \"configurationProperties\": [{ \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true }], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } You can see, I have added configurationProperties for testing purpose only. In case you need to change the script, you can do that by changing the script path as well. jans cli --operation-id put-config-scripts --data /tmp/cs.json Getting access token for scope https://jans.io/oauth/config/scripts.write Server Response: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": [ { \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true } ], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } Get Custom Script by type # With this operation-id, we can find a specific type of scripts. It uses url-suffix to get the list of a single type scripts. Operation ID: get-config-scripts-by-type Description: Gets list of scripts by type. url-suffix: type The command line is: jans cli --operation-id get-config-scripts-by-type --url-suffix type:script-type-name For an example, let's find all the scripts of CLIENT_REGISTRATION type. So, the command line is: jans cli --operation-id get-config-scripts-by-type --url-suffix type:CLIENT_REGISTRATION It returns all the custom scripts that are related to the CLIENT_REGISTRATION type available in the Janssen Server. You will find the name of all the types here Get Custom Scripts by it's inum # In case we need to find out details configuration of any custom script, we can search by its unique inum value. Operation ID: get-config-scripts-by-inum Description: Gets a script by Inum. url-suffix: inum command line: jans cli --operation-id get-config-scripts-by-inum --url-suffix inum:inum_value For example, we can show details here that we already added in the Janssen Server and we know it's inum value is 61aef81b-b22d-42c0-89d5-b098c976a2b7 . In our case, the command line is: jans cli --operation-id get-config-scripts-by-inum --url-suffix inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 It returns the configuration of the custom script matched with the given inum value. Getting access token for scope https://jans.io/oauth/config/scripts.readonly { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": [ { \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true } ], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } How to delete Custom Script? # Well, we can delete any custom script also in deed. In that case, we need to remember the inum value of the custom script we want to delete. In the above we added , updated a custom script. We know the inum value, so let's delete this one. Command line: jans cli --operation-id delete-config-scripts-by-inum --url-suffix inum:inum_value For example, in our case; the command line is: jans cli --operation-id delete-config-scripts-by-inum --url-suffix inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 That's all for Custom Script management with CLI feature. Note If a custom script that is set as Default authentication method is disabled or deleted then the default authentication value will be removed.", "title": "Custom Scripts"}, {"location": "janssen-server/config-guide/custom-scripts-config/#custom-scripts", "text": "Prerequisite: Know how to use the Janssen CLI in command-line mode Interception scripts can be used to implement custom business logic for authentication, authorization, and more in a way that is upgrade-proof and doesn't require forking the Gluu Server code. Using Janssen CLI, we can manage custom scripts as well. Let's get the task information using below command: jans cli --info CustomScripts In return we gets each of the sub-task details: Operation ID: get-config-scripts Description: Gets a list of custom scripts. Operation ID: post-config-scripts Description: Adds a new custom script. Schema: /components/schemas/CustomScript Operation ID: put-config-scripts Description: Updates a custom script. Schema: /components/schemas/CustomScript Operation ID: get-config-scripts-by-type Description: Gets list of scripts by type. url-suffix: type Operation ID: get-config-scripts-by-inum Description: Gets a script by Inum. url-suffix: inum Operation ID: delete-config-scripts-by-inum Description: Deletes a custom script. url-suffix: inum To get sample schema type jans cli --schema <schma>, for example jans cli --schema CustomScript Let's perform each of this operation.", "title": "Custom Scripts"}, {"location": "janssen-server/config-guide/custom-scripts-config/#find-list-of-custom-scripts", "text": "get-config-scripts operation id can be used to get a list of custom scripts of the Janssen Server. The command line is: jans cli --operation-id get-config-scripts It returns all the custom scripts of the Janssen Server.", "title": "Find list of Custom scripts"}, {"location": "janssen-server/config-guide/custom-scripts-config/#adds-a-new-custom-script", "text": "If we look at the description of this operation we see it supports schema: Operation ID: post-config-scripts Description: Adds a new custom script. Schema: /components/schemas/CustomScript So, let's get the schema first: jans cli CustomScript > /tmp/cs.json { \"dn\": null, \"inum\": null, \"name\": \"string\", \"aliases\": [], \"description\": null, \"script\": \"_file /root/script.py\", \"scriptType\": \"INTROSPECTION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": { \"value1\": null, \"value2\": null, \"description\": null, \"hide\": true }, \"level\": \"integer\", \"revision\": 0, \"enabled\": false, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } We need to fill some of these properties with valid data to add this new script. { \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"_file /root/client_registration.py\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [{ \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" }], \"configurationProperties\": null, \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } We can remove dn , inum . As because these two items are auto generated with random value. Also we see aliases , moduleproperties and configurationProperties are the array type keys . So we need to put data into [] otherwise it will raise an error. We can also use null value if we need to skip any of them. For scriptType we can choose only selected type of script from the below list.", "title": "Adds a New Custom Script"}, {"location": "janssen-server/config-guide/custom-scripts-config/#name-of-the-type-of-scripts", "text": "PERSON_AUTHENTICATION, INTROSPECTION, RESOURCE_OWNER_PASSWORD_CREDENTIALS, APPLICATION_SESSION, CACHE_REFRESH, CLIENT_REGISTRATION, ID_GENERATOR, UMA_RPT_POLICY, UMA_RPT_CLAIMS, UMA_CLAIMS_GATHERING, CONSENT_GATHERING, DYNAMIC_SCOPE, SPONTANEOUS_SCOPE, END_SESSION, POST_AUTHN, SCIM, CIBA_END_USER_NOTIFICATION, PERSISTENCE_EXTENSION, IDP, UPDATE_TOKEN", "title": "Name of the type of scripts"}, {"location": "janssen-server/config-guide/custom-scripts-config/#programming-language", "text": "Two types of programming language available there. Those are Python and JavaScript . We can choose any of them regarding the script we need to add. Alright, let's add the script using the command line we have: jans cli --operation-id post-config-scripts --data /tmp/cs.json Getting access token for scope https://jans.io/oauth/config/scripts.write Server Response: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": null, \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false }", "title": "Programming Language"}, {"location": "janssen-server/config-guide/custom-scripts-config/#update-an-existing-custom-script", "text": "put-config-scripts operation-id can be used to update any existing script on the Janssen server. Operation ID: put-config-scripts Description: Updates a custom script. Schema: /components/schemas/CustomScript As we created a custom script in the above , let's update that one. So we know the dn:inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans and inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 here. In this case, I have modified as below: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"_file /root/client_registrationj.py\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [{ \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" }], \"configurationProperties\": [{ \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true }], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } You can see, I have added configurationProperties for testing purpose only. In case you need to change the script, you can do that by changing the script path as well. jans cli --operation-id put-config-scripts --data /tmp/cs.json Getting access token for scope https://jans.io/oauth/config/scripts.write Server Response: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": [ { \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true } ], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false }", "title": "Update an existing Custom Script"}, {"location": "janssen-server/config-guide/custom-scripts-config/#get-custom-script-by-type", "text": "With this operation-id, we can find a specific type of scripts. It uses url-suffix to get the list of a single type scripts. Operation ID: get-config-scripts-by-type Description: Gets list of scripts by type. url-suffix: type The command line is: jans cli --operation-id get-config-scripts-by-type --url-suffix type:script-type-name For an example, let's find all the scripts of CLIENT_REGISTRATION type. So, the command line is: jans cli --operation-id get-config-scripts-by-type --url-suffix type:CLIENT_REGISTRATION It returns all the custom scripts that are related to the CLIENT_REGISTRATION type available in the Janssen Server. You will find the name of all the types here", "title": "Get Custom Script by type"}, {"location": "janssen-server/config-guide/custom-scripts-config/#get-custom-scripts-by-its-inum", "text": "In case we need to find out details configuration of any custom script, we can search by its unique inum value. Operation ID: get-config-scripts-by-inum Description: Gets a script by Inum. url-suffix: inum command line: jans cli --operation-id get-config-scripts-by-inum --url-suffix inum:inum_value For example, we can show details here that we already added in the Janssen Server and we know it's inum value is 61aef81b-b22d-42c0-89d5-b098c976a2b7 . In our case, the command line is: jans cli --operation-id get-config-scripts-by-inum --url-suffix inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 It returns the configuration of the custom script matched with the given inum value. Getting access token for scope https://jans.io/oauth/config/scripts.readonly { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": [ { \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true } ], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false }", "title": "Get Custom Scripts by it's inum"}, {"location": "janssen-server/config-guide/custom-scripts-config/#how-to-delete-custom-script", "text": "Well, we can delete any custom script also in deed. In that case, we need to remember the inum value of the custom script we want to delete. In the above we added , updated a custom script. We know the inum value, so let's delete this one. Command line: jans cli --operation-id delete-config-scripts-by-inum --url-suffix inum:inum_value For example, in our case; the command line is: jans cli --operation-id delete-config-scripts-by-inum --url-suffix inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 That's all for Custom Script management with CLI feature. Note If a custom script that is set as Default authentication method is disabled or deleted then the default authentication value will be removed.", "title": "How to delete Custom Script?"}, {"location": "janssen-server/config-guide/link-configuration/", "tags": ["administration", "configuration", "link"], "text": "Jans Link Configuration # Details of how to configure Jans Link have been covered under Jans Link section .", "title": "Link Configuration"}, {"location": "janssen-server/config-guide/link-configuration/#jans-link-configuration", "text": "Details of how to configure Jans Link have been covered under Jans Link section .", "title": "Jans Link Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/", "tags": ["administration", "configuration", "smtp"], "text": "SMTP Configuration # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and customize the SMTP using the command line. To get the details of Janssen command line operations relevant to SMTP Configuration, you can check the operations under ConfigurationSmtp task using the command below: Command jans cli --info ConfigurationSmtp Sample Output Operation ID: get-config-smtp Description: Returns SMTP server configuration Operation ID: put-config-smtp Description: Updates SMTP server configuration Schema: SmtpConfiguration Operation ID: post-config-smtp Description: Adds SMTP server configuration Schema: SmtpConfiguration Operation ID: delete-config-smtp Description: Deletes SMTP server configuration Operation ID: test-config-smtp Description: Signing Test SMTP server configuration Schema: SmtpTest Find SMTP Server Configuration # To view the current SMTP server configuration, run the following command line: Command jans cli --operation-id get-config-smtp It will show the SMTP server configuration as below: Sample Output 1 2 3 4 5 6 7 8 9 10 { \"valid\" : false , \"port\" : 0 , \"trust_host\" : false , \"requires_authentication\" : false , \"key_store\" : \"/etc/certs/smtp-keys.pkcs12\" , \"key_store_password\" : \"kb5JITTrmCyX1LNEp8uorA==\" , \"key_store_alias\" : \"smtp_sig_ec256\" , \"signing_algorithm\" : \"SHA256withECDSA\" } Setup New SMTP Server Configuration # To add a new SMTP Server, we can use post-config-smtp operation id. As shown in the output for --info command, the post-config-smtp operation requires data to be sent according to the SmtpConfiguration schema. To see the schema, use the command below: Command jans cli --schema SmtpConfiguration The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample SmtpConfiguration Using the schema and the example above, we have added below data to the file /tmp/smtp.json . Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"valid\" : true , \"host\" : \"string\" , \"port\" : 5 , \"connect_protection\" : \"StartTls\" , \"trust_host\" : false , \"from_name\" : \"jans\" , \"from_email_address\" : \"string\" , \"requires_authentication\" : false , \"smtp_authentication_account_username\" : \"string\" , \"smtp_authentication_account_password\" : \"string\" , \"key_store\" : \"string\" , \"key_store_password\" : \"string\" , \"key_store_alias\" : \"string\" , \"signing_algorithm\" : \"string\" } To setup a new SMTP server configuration, run the following command: Command jans cli --operation-id post-config-smtp \\ --data /tmp/smtp.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"valid\" : true , \"host\" : \"string\" , \"port\" : 5 , \"connect_protection\" : \"StartTls\" , \"trust_host\" : false , \"from_name\" : \"jans\" , \"from_email_address\" : \"string\" , \"requires_authentication\" : false , \"smtp_authentication_account_username\" : \"string\" , \"smtp_authentication_account_password\" : \"CGmVqM6v4Hs=\" , \"key_store\" : \"string\" , \"key_store_password\" : \"CGmVqM6v4Hs=\" , \"key_store_alias\" : \"string\" , \"signing_algorithm\" : \"string\" } Update SMTP Server Configuration # To update the SMTP server, we can use the put-config-smtp operation id. simply change any information on /tmp/smtp.json file and run the following command: In that file, update the value false to true of the trust_host field. Command jans cli --operation-id put-config-smtp \\ --data /tmp/smtp.json It will update the information. Delete SMTP Sever Configuration # To delete the SMTP Sever, we can use the delete-config-smtp operation id. run the following command Command jans cli --operation-id delete-config-smtp Test SMTP Server Configuration # Testing SMTP Server configuration token with https://jans.io/oauth/config/smtp.write scope is required. To test the SMTP server configuration update, change any information on the /tmp/smtp.json file with test data and run the following command: Command jans cli --operation-id test-config-smtp \\ --data /tmp/smtp.json This will return status code 200 with a response as true or false based on the SMTP test result. Note: SMTP Password should be an App password and not a web login password. Using Text-based UI # Start TUI using the command below: Command jans tui SMPT Screen # Navigate to Auth Server -> SMPT to open the SMPT screen as shown in the image below. This screen shows the current SMTP server configuration. After changing the SMPT data, update the SMPT server using the Save button. Test the SMPTS server using the Test button, and the result will be displayed. The test result image is shown below. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the SMTP. Endpoint details are published in the Swagger document .", "title": "SMTP Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#smtp-configuration", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "SMTP Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the SMTP using the command line. To get the details of Janssen command line operations relevant to SMTP Configuration, you can check the operations under ConfigurationSmtp task using the command below: Command jans cli --info ConfigurationSmtp Sample Output Operation ID: get-config-smtp Description: Returns SMTP server configuration Operation ID: put-config-smtp Description: Updates SMTP server configuration Schema: SmtpConfiguration Operation ID: post-config-smtp Description: Adds SMTP server configuration Schema: SmtpConfiguration Operation ID: delete-config-smtp Description: Deletes SMTP server configuration Operation ID: test-config-smtp Description: Signing Test SMTP server configuration Schema: SmtpTest", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/smtp-configuration/#find-smtp-server-configuration", "text": "To view the current SMTP server configuration, run the following command line: Command jans cli --operation-id get-config-smtp It will show the SMTP server configuration as below: Sample Output 1 2 3 4 5 6 7 8 9 10 { \"valid\" : false , \"port\" : 0 , \"trust_host\" : false , \"requires_authentication\" : false , \"key_store\" : \"/etc/certs/smtp-keys.pkcs12\" , \"key_store_password\" : \"kb5JITTrmCyX1LNEp8uorA==\" , \"key_store_alias\" : \"smtp_sig_ec256\" , \"signing_algorithm\" : \"SHA256withECDSA\" }", "title": "Find SMTP Server Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#setup-new-smtp-server-configuration", "text": "To add a new SMTP Server, we can use post-config-smtp operation id. As shown in the output for --info command, the post-config-smtp operation requires data to be sent according to the SmtpConfiguration schema. To see the schema, use the command below: Command jans cli --schema SmtpConfiguration The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample SmtpConfiguration Using the schema and the example above, we have added below data to the file /tmp/smtp.json . Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"valid\" : true , \"host\" : \"string\" , \"port\" : 5 , \"connect_protection\" : \"StartTls\" , \"trust_host\" : false , \"from_name\" : \"jans\" , \"from_email_address\" : \"string\" , \"requires_authentication\" : false , \"smtp_authentication_account_username\" : \"string\" , \"smtp_authentication_account_password\" : \"string\" , \"key_store\" : \"string\" , \"key_store_password\" : \"string\" , \"key_store_alias\" : \"string\" , \"signing_algorithm\" : \"string\" } To setup a new SMTP server configuration, run the following command: Command jans cli --operation-id post-config-smtp \\ --data /tmp/smtp.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"valid\" : true , \"host\" : \"string\" , \"port\" : 5 , \"connect_protection\" : \"StartTls\" , \"trust_host\" : false , \"from_name\" : \"jans\" , \"from_email_address\" : \"string\" , \"requires_authentication\" : false , \"smtp_authentication_account_username\" : \"string\" , \"smtp_authentication_account_password\" : \"CGmVqM6v4Hs=\" , \"key_store\" : \"string\" , \"key_store_password\" : \"CGmVqM6v4Hs=\" , \"key_store_alias\" : \"string\" , \"signing_algorithm\" : \"string\" }", "title": "Setup New SMTP Server Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#update-smtp-server-configuration", "text": "To update the SMTP server, we can use the put-config-smtp operation id. simply change any information on /tmp/smtp.json file and run the following command: In that file, update the value false to true of the trust_host field. Command jans cli --operation-id put-config-smtp \\ --data /tmp/smtp.json It will update the information.", "title": "Update SMTP Server Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#delete-smtp-sever-configuration", "text": "To delete the SMTP Sever, we can use the delete-config-smtp operation id. run the following command Command jans cli --operation-id delete-config-smtp", "title": "Delete SMTP Sever Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#test-smtp-server-configuration", "text": "Testing SMTP Server configuration token with https://jans.io/oauth/config/smtp.write scope is required. To test the SMTP server configuration update, change any information on the /tmp/smtp.json file with test data and run the following command: Command jans cli --operation-id test-config-smtp \\ --data /tmp/smtp.json This will return status code 200 with a response as true or false based on the SMTP test result. Note: SMTP Password should be an App password and not a web login password.", "title": "Test SMTP Server Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#using-text-based-ui", "text": "Start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/smtp-configuration/#smpt-screen", "text": "Navigate to Auth Server -> SMPT to open the SMPT screen as shown in the image below. This screen shows the current SMTP server configuration. After changing the SMPT data, update the SMPT server using the Save button. Test the SMPTS server using the Test button, and the result will be displayed. The test result image is shown below.", "title": "SMPT Screen"}, {"location": "janssen-server/config-guide/smtp-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the SMTP. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/", "tags": ["administration", "configuration", "agama project"], "text": "Agama project configuration # Agama project configuration involves adding and removing Agama projects to Janssen Server along with configuring and troubleshooting these project deployments. The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the configuration steps Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the configuration steps Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the configuration steps Using Command Line # In the Janssen Server, you can deploy and customize the Agama project using the command line. To get the details of Janssen command line operations relevant to Agama projects, you can check the operations under Agama task using the command below: Command jans cli --info Agama It will show the details of the available operation-ids for Agama. Operation ID: get-agama-prj-by-name Description: Fetches deployed the Agama project based on the name. Parameters: name: Agama project name [string] Operation ID: post-agama-prj Description: Deploy an Agama project. Parameters: name: Agama project name [string] Operation ID: delete-agama-prj Description: Delete a deployed Agama project. Parameters: name: Agama project name [string] Operation ID: get-agama-prj-configs Description: Retrieve the list of configs based on name. Parameters: name: Agama project name [string] Operation ID: put-agama-prj Description: Update an Agama project. Parameters: name: Agama project name [string] Parameters: type: Description not found for this property additionalProperties: Description not found for this property Operation ID: get-agama-prj Description: Retrieve the list of projects deployed currently. Parameters: start: No description is provided for this parameter [integer] count: No description is provided for this parameter [integer] In the sections below, we will see how to configure and manage Agama projects via the command line using the above operations. List Deployed Projects # Use the get-agama-prj operation to retrieve the list of deployed Agama projects: Command jans cli --operation-id get-agama-prj The output will list Agama projects that are added to this Janssen Server deployment. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=46546e9a-fed6-34d0-ba63-b615233b2115,ou=deployments,ou=agama,o=jans\" , \"id\" : \"46546e9a-fed6-34d0-ba63-b615233b2115\" , \"createdAt\" : \"2023-08-13T14:45:27\" , \"taskActive\" : false , \"finishedAt\" : \"2023-08-13T14:45:43\" , \"details\" : { \"error\" : \"There were problems processing one or more flows\" , \"flowsError\" : { \"mmrraju.np.test.me\" : null , \"mmrraju.test2.agama\" : null , \"mmrraju.u2f.me\" : \"Syntax error: mismatched input '<EOF>' expecting {'|', 'Log', 'Trigger', 'Call', 'RRF', 'When', 'Repeat', 'Iterate over', 'Match', 'Finish', 'RFAC', ALPHANUM, QNAME, DOTEXPR, DOTIDXEXPR, WS}\\nSymbol: [@9,43:42='<EOF>',<-1>,2:23]\\nLine: 2\\nColumn: 24\" }, \"projectMetadata\" : { \"projectName\" : \"user_pass_auth\" , \"author\" : \"mmrraju\" , \"type\" : \"community\" , \"description\" : \"This is password based authentication\" , \"version\" : \"1.0.34\" , \"configs\" : null } }, \"baseDn\" : \"jansId=46546e9a-fed6-34d0-ba63-b615233b2115,ou=deployments,ou=agama,o=jans\" } ] } Endpoint Arguments # Endpoint arguments are parameters passed to an API or function to specify how and what data to retrieve or process. There are two endpoint arguments available to the get-agama-prj operation. start : Should be an integer value. It's an index value of the starting point of the list. count : Should be an integer value. Total entries number you want to display. For example, to fetch details of the project at index 1 only, use the command below. Command jans cli --operation-id get-agama-prj --endpoint-args start:1,count:1 Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 { \"start\" : 1 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" , \"id\" : \"3a0e91a4-b79b-37c2-9df7-122247e8ed9c\" , \"createdAt\" : \"2023-08-15T05:56:19\" , \"taskActive\" : false , \"finishedAt\" : \"2023-08-15T05:56:42\" , \"details\" : { \"error\" : \"Archive missing web and/or code subdirectories\" , \"flowsError\" : null , \"projectMetadata\" : { \"projectName\" : \"testAuth\" , \"configs\" : null } }, \"baseDn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" } ] } View Agama Project By Name # You can get the details of an Agama project deployed in the Janssen Server by the project name. The command line for this operation is as below: Sample Command jans cli --operation-id get-agama-prj-by-name --url-suffix = \"agama-project-name\" Example: Sample Command jans cli --operation-id get-agama-prj-by-name --url-suffix = \"testAuth\" Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 { \"dn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" , \"id\" : \"3a0e91a4-b79b-37c2-9df7-122247e8ed9c\" , \"createdAt\" : 1687247278717 , \"taskActive\" : false , \"finishedAt\" : 1687247288646 , \"assets\" : null , \"details\" : { \"folders\" : null , \"libs\" : [], \"flowsError\" : { \"imShakil.co.basicAuth\" : null }, \"error\" : null , \"projectMetadata\" : { \"projectName\" : \"testAuth\" , \"author\" : \"imShakil\" , \"type\" : \"community\" , \"description\" : \"testing authentication with janssen server\" , \"version\" : \"1.0.0\" , \"configs\" : null } }, \"baseDn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" } Post Agama Project in Janssen # You can deploy the Agama project in the Janssen Server through the command line using the post-agama-prj operation. Here the agama-project-file is an archive file that holds the bundled Agama project and follows the .gama specification. Sample Command jans cli --operation-id post-agama-prj \\ --url-suffix = \"name:project-name\" --data agama-project-file Example: Let's upload a test project Zip file. This zip file contains the artifacts of an Agama project and follows the .gama specification. Assuming that the zip file has been downloaded in the folder at path /tmp/journey.zip , the command below will upload a new Agama project with specified name in the Janssen Server. Sample Command jans cli --operation-id = post-agama-prj \\ --url-suffix = \"name:Agama Lab Journey\" --data /tmp/journey.zip Sample Output { \"message\" : \"A deployment task for project Agama Lab Journey has been queued. Use the GET endpoint to poll status\" } Now the project should be available in the list of deployed projects . Retrieve Agama Project Configuration # To retrieve the Agama project configuration, use the get-agama-prj-configs operation. Sample Command jans cli --operation-id get-agama-prj-configs \\ --url-suffix = \"name:agama-project-name\" Update Agama Project # Let's update the configuration for project that we uploaded in the section above : Take the sample project configuration and keep it under /tmp/journey-configs.json . Make a few test changes to the configuration and run the command below to update the configuration: Command jans cli --operation-id = put-agama-prj \\ --url-suffix \"name:Agama Lab Journey\" --data /tmp/journey-configs.json Sample Output 1 2 3 4 5 6 7 8 { \"io.jans.agamaLab.registration\" : true , \"io.jans.agamaLab.main\" : true , \"io.jans.agamaLab.credsEnrollment.otp\" : true , \"io.jans.agamaLab.authenticator.super_gluu\" : true , \"io.jans.agamaLab.credsEnrollment.super_gluu\" : true , \"io.jans.agamaLab.githubAuthn\" : true } Delete Agama Project # To delete an Agama project by its name, use the delete-agama-prj operation. Sample Command jans cli --operation-id delete-agama-prj --url-suffix = \"agama-project-name\" Agama Flow Configuration # AgamaConfiguration task groups operations that help understand the correctness of the deployed Agama project configuration. Command jans cli --info AgamaConfiguration Sample Output 1 2 3 4 Operation ID: agama-syntax-check Description: Determine if the text passed is valid Agama code Parameters: qname: Agama Flow name [string] Agama Flow DSL Syntax # To check if a deployed Agama project is running into Agama DSL related errors, use the agama-syntax-check operation as below: Sample Command jans cli --operation-id agama-syntax-check \\ --url-suffix qname: \"fully-qualified-flow-name\" Example : Command jans cli --operation-id agama-syntax-check --url-suffix qname: \"imShakil.co.test\" Sample Output 1 2 3 4 5 6 7 { \"error\" : \"mismatched input 'newline' expecting 'Flow'\" , \"symbol\" : \"[@0,0:-1='newline',<9>,1:0]\" , \"line\" : 1 , \"column\" : 0 , \"message\" : \"Syntax error: mismatched input 'newline' expecting 'Flow'\\nSymbol: [@0,0:-1='newline',<9>,1:0]\\nLine: 1\\nColumn: 1\" } Using Text-based UI # In Janssen, You can deploy and customize an Agama project using the Text-Based UI also. You can start TUI using the command below: Command jans tui Agama Project Screen # Navigate to Auth Server -> Agama to open the Agama projects screen as shown in the image below. To get the list of currently added projects, bring the control to Search box (using the tab key), and press Enter . Type the search string to search for projects with matching names. Add a new project using Add a New Project button. It will open a dialogue where you can either deploy a local project or deploy an Agama Lab community project as shown in the image below. If you select the first option, it'll open the explore dialogue. Using this dialogue, navigate the file system and select the .gama archive for the new project. If you select the second option, it'ill collect a list of Agama Lab community projects from GitHub and display a selection list as shown in the image below. Agama Project Help Menu # TUI provides key-press commands to open various dialogues that help manage and configure Agama projects. All the key-press commands are listed in the help menu. Press F1 to bring up the help menu as shown in the screen below. Agama Project Detail Screen # Use the appropriate key-press command from help screen to bring up the project detail screen which is shown in the image below. The project details screen shows important details about the Agama project. In case the project deployment is facing an error, this screen also shows these errors and the corresponding flows. All the flows in the project are also listed by their fully qualified names. Fully qualified names are useful when invoking flows. The project details screen also shows the JSON configuration by navigating to and pressing the View Configuration button. Agama Project Configuration Screen # Use the appropriate key-press command from help screen to bring up the Agama project configuration screen which is shown in the image below. The screen allows the export and import of the configuration. The sample configuration can serve as a template. Export it into a file, then make the necessary changes to it and import it back to correctly configure the project. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring Agama projects. Endpoint details are published in the Swagger document .", "title": "Agama Project Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-project-configuration", "text": "Agama project configuration involves adding and removing Agama projects to Janssen Server along with configuring and troubleshooting these project deployments. The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the configuration steps Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the configuration steps Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the configuration steps", "title": "Agama project configuration"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the Agama project using the command line. To get the details of Janssen command line operations relevant to Agama projects, you can check the operations under Agama task using the command below: Command jans cli --info Agama It will show the details of the available operation-ids for Agama. Operation ID: get-agama-prj-by-name Description: Fetches deployed the Agama project based on the name. Parameters: name: Agama project name [string] Operation ID: post-agama-prj Description: Deploy an Agama project. Parameters: name: Agama project name [string] Operation ID: delete-agama-prj Description: Delete a deployed Agama project. Parameters: name: Agama project name [string] Operation ID: get-agama-prj-configs Description: Retrieve the list of configs based on name. Parameters: name: Agama project name [string] Operation ID: put-agama-prj Description: Update an Agama project. Parameters: name: Agama project name [string] Parameters: type: Description not found for this property additionalProperties: Description not found for this property Operation ID: get-agama-prj Description: Retrieve the list of projects deployed currently. Parameters: start: No description is provided for this parameter [integer] count: No description is provided for this parameter [integer] In the sections below, we will see how to configure and manage Agama projects via the command line using the above operations.", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#list-deployed-projects", "text": "Use the get-agama-prj operation to retrieve the list of deployed Agama projects: Command jans cli --operation-id get-agama-prj The output will list Agama projects that are added to this Janssen Server deployment. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=46546e9a-fed6-34d0-ba63-b615233b2115,ou=deployments,ou=agama,o=jans\" , \"id\" : \"46546e9a-fed6-34d0-ba63-b615233b2115\" , \"createdAt\" : \"2023-08-13T14:45:27\" , \"taskActive\" : false , \"finishedAt\" : \"2023-08-13T14:45:43\" , \"details\" : { \"error\" : \"There were problems processing one or more flows\" , \"flowsError\" : { \"mmrraju.np.test.me\" : null , \"mmrraju.test2.agama\" : null , \"mmrraju.u2f.me\" : \"Syntax error: mismatched input '<EOF>' expecting {'|', 'Log', 'Trigger', 'Call', 'RRF', 'When', 'Repeat', 'Iterate over', 'Match', 'Finish', 'RFAC', ALPHANUM, QNAME, DOTEXPR, DOTIDXEXPR, WS}\\nSymbol: [@9,43:42='<EOF>',<-1>,2:23]\\nLine: 2\\nColumn: 24\" }, \"projectMetadata\" : { \"projectName\" : \"user_pass_auth\" , \"author\" : \"mmrraju\" , \"type\" : \"community\" , \"description\" : \"This is password based authentication\" , \"version\" : \"1.0.34\" , \"configs\" : null } }, \"baseDn\" : \"jansId=46546e9a-fed6-34d0-ba63-b615233b2115,ou=deployments,ou=agama,o=jans\" } ] }", "title": "List Deployed Projects"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#endpoint-arguments", "text": "Endpoint arguments are parameters passed to an API or function to specify how and what data to retrieve or process. There are two endpoint arguments available to the get-agama-prj operation. start : Should be an integer value. It's an index value of the starting point of the list. count : Should be an integer value. Total entries number you want to display. For example, to fetch details of the project at index 1 only, use the command below. Command jans cli --operation-id get-agama-prj --endpoint-args start:1,count:1 Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 { \"start\" : 1 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" , \"id\" : \"3a0e91a4-b79b-37c2-9df7-122247e8ed9c\" , \"createdAt\" : \"2023-08-15T05:56:19\" , \"taskActive\" : false , \"finishedAt\" : \"2023-08-15T05:56:42\" , \"details\" : { \"error\" : \"Archive missing web and/or code subdirectories\" , \"flowsError\" : null , \"projectMetadata\" : { \"projectName\" : \"testAuth\" , \"configs\" : null } }, \"baseDn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" } ] }", "title": "Endpoint Arguments"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#view-agama-project-by-name", "text": "You can get the details of an Agama project deployed in the Janssen Server by the project name. The command line for this operation is as below: Sample Command jans cli --operation-id get-agama-prj-by-name --url-suffix = \"agama-project-name\" Example: Sample Command jans cli --operation-id get-agama-prj-by-name --url-suffix = \"testAuth\" Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 { \"dn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" , \"id\" : \"3a0e91a4-b79b-37c2-9df7-122247e8ed9c\" , \"createdAt\" : 1687247278717 , \"taskActive\" : false , \"finishedAt\" : 1687247288646 , \"assets\" : null , \"details\" : { \"folders\" : null , \"libs\" : [], \"flowsError\" : { \"imShakil.co.basicAuth\" : null }, \"error\" : null , \"projectMetadata\" : { \"projectName\" : \"testAuth\" , \"author\" : \"imShakil\" , \"type\" : \"community\" , \"description\" : \"testing authentication with janssen server\" , \"version\" : \"1.0.0\" , \"configs\" : null } }, \"baseDn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" }", "title": "View Agama Project By Name"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#post-agama-project-in-janssen", "text": "You can deploy the Agama project in the Janssen Server through the command line using the post-agama-prj operation. Here the agama-project-file is an archive file that holds the bundled Agama project and follows the .gama specification. Sample Command jans cli --operation-id post-agama-prj \\ --url-suffix = \"name:project-name\" --data agama-project-file Example: Let's upload a test project Zip file. This zip file contains the artifacts of an Agama project and follows the .gama specification. Assuming that the zip file has been downloaded in the folder at path /tmp/journey.zip , the command below will upload a new Agama project with specified name in the Janssen Server. Sample Command jans cli --operation-id = post-agama-prj \\ --url-suffix = \"name:Agama Lab Journey\" --data /tmp/journey.zip Sample Output { \"message\" : \"A deployment task for project Agama Lab Journey has been queued. Use the GET endpoint to poll status\" } Now the project should be available in the list of deployed projects .", "title": "Post Agama Project in Janssen"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#retrieve-agama-project-configuration", "text": "To retrieve the Agama project configuration, use the get-agama-prj-configs operation. Sample Command jans cli --operation-id get-agama-prj-configs \\ --url-suffix = \"name:agama-project-name\"", "title": "Retrieve Agama Project Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#update-agama-project", "text": "Let's update the configuration for project that we uploaded in the section above : Take the sample project configuration and keep it under /tmp/journey-configs.json . Make a few test changes to the configuration and run the command below to update the configuration: Command jans cli --operation-id = put-agama-prj \\ --url-suffix \"name:Agama Lab Journey\" --data /tmp/journey-configs.json Sample Output 1 2 3 4 5 6 7 8 { \"io.jans.agamaLab.registration\" : true , \"io.jans.agamaLab.main\" : true , \"io.jans.agamaLab.credsEnrollment.otp\" : true , \"io.jans.agamaLab.authenticator.super_gluu\" : true , \"io.jans.agamaLab.credsEnrollment.super_gluu\" : true , \"io.jans.agamaLab.githubAuthn\" : true }", "title": "Update Agama Project"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#delete-agama-project", "text": "To delete an Agama project by its name, use the delete-agama-prj operation. Sample Command jans cli --operation-id delete-agama-prj --url-suffix = \"agama-project-name\"", "title": "Delete Agama Project"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-flow-configuration", "text": "AgamaConfiguration task groups operations that help understand the correctness of the deployed Agama project configuration. Command jans cli --info AgamaConfiguration Sample Output 1 2 3 4 Operation ID: agama-syntax-check Description: Determine if the text passed is valid Agama code Parameters: qname: Agama Flow name [string]", "title": "Agama Flow Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-flow-dsl-syntax", "text": "To check if a deployed Agama project is running into Agama DSL related errors, use the agama-syntax-check operation as below: Sample Command jans cli --operation-id agama-syntax-check \\ --url-suffix qname: \"fully-qualified-flow-name\" Example : Command jans cli --operation-id agama-syntax-check --url-suffix qname: \"imShakil.co.test\" Sample Output 1 2 3 4 5 6 7 { \"error\" : \"mismatched input 'newline' expecting 'Flow'\" , \"symbol\" : \"[@0,0:-1='newline',<9>,1:0]\" , \"line\" : 1 , \"column\" : 0 , \"message\" : \"Syntax error: mismatched input 'newline' expecting 'Flow'\\nSymbol: [@0,0:-1='newline',<9>,1:0]\\nLine: 1\\nColumn: 1\" }", "title": "Agama Flow DSL Syntax"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#using-text-based-ui", "text": "In Janssen, You can deploy and customize an Agama project using the Text-Based UI also. You can start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-project-screen", "text": "Navigate to Auth Server -> Agama to open the Agama projects screen as shown in the image below. To get the list of currently added projects, bring the control to Search box (using the tab key), and press Enter . Type the search string to search for projects with matching names. Add a new project using Add a New Project button. It will open a dialogue where you can either deploy a local project or deploy an Agama Lab community project as shown in the image below. If you select the first option, it'll open the explore dialogue. Using this dialogue, navigate the file system and select the .gama archive for the new project. If you select the second option, it'ill collect a list of Agama Lab community projects from GitHub and display a selection list as shown in the image below.", "title": "Agama Project Screen"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-project-help-menu", "text": "TUI provides key-press commands to open various dialogues that help manage and configure Agama projects. All the key-press commands are listed in the help menu. Press F1 to bring up the help menu as shown in the screen below.", "title": "Agama Project Help Menu"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-project-detail-screen", "text": "Use the appropriate key-press command from help screen to bring up the project detail screen which is shown in the image below. The project details screen shows important details about the Agama project. In case the project deployment is facing an error, this screen also shows these errors and the corresponding flows. All the flows in the project are also listed by their fully qualified names. Fully qualified names are useful when invoking flows. The project details screen also shows the JSON configuration by navigating to and pressing the View Configuration button.", "title": "Agama Project Detail Screen"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-project-configuration-screen", "text": "Use the appropriate key-press command from help screen to bring up the Agama project configuration screen which is shown in the image below. The screen allows the export and import of the configuration. The sample configuration can serve as a template. Export it into a file, then make the necessary changes to it and import it back to correctly configure the project.", "title": "Agama Project Configuration Screen"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring Agama projects. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/", "tags": ["administration", "configuration", "attributes"], "text": "Attribute # First thing, let's get the information for Attribute : jans cli --info Attribute In return, we get a list of Operations ID as below: Operation ID: get-attributes Description: Gets a list of Gluu attributes. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-attributes Description: Updates an existing attribute Schema: JansAttribute Operation ID: post-attributes Description: Adds a new attribute Schema: JansAttribute Operation ID: get-attributes-by-inum Description: Gets an attribute based on inum Parameters: inum: Attribute Id [string] Operation ID: delete-attributes-by-inum Description: Deletes an attribute based on inum Parameters: inum: Attribute Id [string] Operation ID: patch-attributes-by-inum Description: Partially modify a JansAttribute Parameters: inum: Attribute Id [string] Schema: Array of PatchRequest To get sample schema type jans cli --schema <schma>, for example jans cli --schema PatchRequest We have discussed here about each of this operations ID with few examples to understand how these really works. Table of Contents # Attribute Get Attributes Creating an Attribute Updating an Attribute Get Attribute by inum Delete Attributes Patch Attributes Get Attributes # Prerequisite: Know how to use the Janssen CLI in command-line mode As we know, Attributes are individual pieces of user data, like uid or email , that are required by applications in order to identify a user and grant access to protect resources. The user attributes that are available in your Janssen Server can be found by using this operation-ID. If we look at the description below: Operation ID: get-attributes Description: Gets a list of Gluu attributes. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] To get all the attributes without any arguments, run the following command: jans cli --operation-id get-attributes To get attributes with passing the arguments, let's retrieve randomly limit:5: jans cli --operation-id get-attributes --endpoint-args limit:1 It will return only one attribute details randomly: Getting access token for scope https://jans.io/oauth/config/attributes.readonly Calling with params limit=1 { \"start\": 0, \"totalEntriesCount\": 71, \"entriesCount\": 1, \"entries\": [ { \"dn\": \"inum=29DA,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"29DA\", \"name\": \"inum\", \"displayName\": \"Inum\", \"description\": \"XRI i-number, persistent non-reassignable identifier\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"inum\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:inum\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.117\", \"urn\": \"urn:jans:dir:attribute-def:inum\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": false, \"whitePagesCanView\": false, \"baseDn\": \"inum=29DA,ou=attributes,o=jans\" } ] } To get attributes with pattern & status : jans cli --operation-id get-attributes --endpoint-args limit:3,pattern:profile,status:ACTIVE In return, we get a list of attribute that are matched with the given pattern and status : Please wait while retrieving data ... { \"start\": 0, \"totalEntriesCount\": 2, \"entriesCount\": 2, \"entries\": [ { \"dn\": \"inum=64A0,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"64A0\", \"name\": \"profile\", \"displayName\": \"Profile URL\", \"description\": \"URL of the End-User's profile page. The contents of this Web page SHOULD be about the End-User.\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"user\", \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"profile\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:profile\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.321\", \"urn\": \"http://openid.net/specs/openid-connect-core-1_0.html/StandardClaims/profile\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": true, \"whitePagesCanView\": false, \"baseDn\": \"inum=64A0,ou=attributes,o=jans\" }, { \"dn\": \"inum=EC3A,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"EC3A\", \"name\": \"picture\", \"displayName\": \"Picture URL\", \"description\": \"URL of the End-User's profile picture\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"user\", \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"picture\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:picture\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.322\", \"urn\": \"http://openid.net/specs/openid-connect-core-1_0.html/StandardClaims/picture\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": true, \"whitePagesCanView\": false, \"baseDn\": \"inum=EC3A,ou=attributes,o=jans\" } ] } Creating an Attribute # To create SSO for certain applications, you may need to add custom attributes to your Janssen Server. Custom attributes can be added by using this operation-ID. It has a schema file where it's defined: the properties it needs to be filled to create a new custom attribute. Operation ID: post-attributes Description: Adds a new attribute Schema: JansAttribute Before adding a new attribute, let's get sample schema : jans cli --schema JansAttribute > /tmp/attribute.json It will return as below: { \"dn\" : \"string\" , \"selected\" : false , \"inum\" : \"string\" , \"sourceAttribute\" : \"string\" , \"nameIdType\" : \"string\" , \"name\" : \"string\" , \"displayName\" : \"string\" , \"description\" : \"string\" , \"origin\" : \"string\" , \"dataType\" : \"certificate\" , \"editType\" : [ \"manager\" ], \"viewType\" : [ \"user\" ], \"usageType\" : [ \"openid\" ], \"claimName\" : \"string\" , \"seeAlso\" : \"string\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"string\" , \"saml2Uri\" : \"string\" , \"urn\" : \"string\" , \"scimCustomAttr\" : true , \"oxMultiValuedAttribute\" : true , \"jansHideOnDiscovery\" : true , \"custom\" : false , \"attributeValidation\" : { \"minLength\" : { \"type\" : \"integer\" , \"format\" : \"int32\" }, \"maxLength\" : { \"type\" : \"integer\" , \"format\" : \"int32\" }, \"regexp\" : { \"type\" : \"string\" } }, \"tooltip\" : \"string\" , \"whitePagesCanView\" : false , \"adminCanView\" : true , \"userCanAccess\" : false , \"userCanView\" : true , \"adminCanAccess\" : false , \"adminCanEdit\" : false , \"userCanEdit\" : true , \"baseDn\" : \"string\" } Modify it to update attribute name , display name , view type : nano /tmp/attribute.json Now, let's add this attribute using post-attributes : jans cli --operation-id post-attributes --data /tmp/attribute.json It will create a new attribute into the Attribute list with updated inum & dn : { \"dn\" : \"inum=0272b98e-0ead-43e9-94eb-4af9548af97d,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"0272b98e-0ead-43e9-94eb-4af9548af97d\" , \"nameIdType\" : \"string\" , \"name\" : \"testAttribute\" , \"displayName\" : \"testAttribute\" , \"description\" : \"testAttribute\" , \"dataType\" : \"certificate\" , \"editType\" : [ \"manager\" ], \"viewType\" : [ \"user\" ], \"usageType\" : [ \"openid\" ], \"status\" : \"inactive\" , \"scimCustomAttr\" : true , \"oxMultiValuedAttribute\" : true , \"jansHideOnDiscovery\" : true , \"custom\" : false , \"tooltip\" : \"string\" , \"adminCanAccess\" : false , \"adminCanView\" : false , \"adminCanEdit\" : false , \"userCanAccess\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"whitePagesCanView\" : false , \"baseDn\" : \"inum=0272b98e-0ead-43e9-94eb-4af9548af97d,ou=attributes,o=jans\" } Updating an Attribute # This operation-id can be used to update an existing attribute information. The Janssen Server administrator can make changes to attributes, such as changing their status to active/inactive by using this operation-ID. Let's look at the schema: jans cli --schema JansAttribute > /tmp/attrib.json You must see the similar schema while performed in post-attributes operation. To update an existing attribute, we have to ensure following properties in the schema file. In our case, I have modified the schema file as below: { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": true, \"name\": \"testAttribute\", \"display_name\": \"testAttribute\", \"description\": \"testing put-attribute\", \"data_type\": \"STRING\", \"status\": \"ACTIVE\", \"edit_type\": [\"ADMIN\", \"OWNER\"], \"view_type\": [\"ADMIN\", \"OWNER\", \"USER\"] } Now if we run the below command line: jans cli --operation-id put-attributes --data /tmp/attrb.json Getting access token for scope https://jans.io/oauth/config/attributes.write Server Response: { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": false, \"name\": \"testAttribute\", \"displayName\": \"testAttribute\", \"description\": \"testing put-attribute\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": null, \"editType\": [ \"ADMIN\", \"OWNER\" ], \"viewType\": [ \"ADMIN\", \"OWNER\", \"USER\" ], \"usageType\": null, \"claimName\": null, \"seeAlso\": null, \"saml1Uri\": null, \"saml2Uri\": null, \"urn\": null, \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null } It just replace the previous value with new one. Get Attribute by inum # As we know, There are a lot of attributes available in the Janssen Server including custom attributes as well. You may want to know details information for a single attribute uniquely identified by inum . Getting an attribute information by using its inum is pretty simple. jans cli --operation-id get-attributes-by-inum --url-suffix inum:attribute-iunm-value It will show all details information of the selected Attribute as below example. jans cli --operation-id get-attributes-by-inum --url-suffix inum:b691f2ab-a7db-4725-b85b-9961575b441f Getting access token for scope https://jans.io/oauth/config/attributes.readonly { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": false, \"name\": \"testAttribute\", \"displayName\": \"testAttribute\", \"description\": \"testing put-attribute\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": null, \"editType\": [ \"ADMIN\", \"OWNER\" ], \"viewType\": [ \"ADMIN\", \"OWNER\", \"USER\" ], \"usageType\": null, \"claimName\": null, \"seeAlso\": null, \"saml1Uri\": null, \"saml2Uri\": null, \"urn\": null, \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null } Delete Attributes # For any reason, If it needs to delete any attribute, you can do that simply using its inum value. See below example, just change the inum value with one that you want to delete. jans cli --operation-id delete-attributes-by-inum --url-suffix inum:b691f2ab-a7db-4725-b85b-9961575b441f Patch Attributes # This operation can also used for updating an existing attribute by using its inum value. Operation ID: patch-attributes-by-inum Description: Partially modify a JansAttribute. url-suffix: inum Schema: Array of PatchRequest If we look at the description, we see that there is a schema file. Let's get the schema file with below command: jans cli --schema PatchRequest > /tmp/patch.json # cat /tmp/patch.json { \"op\": \"add\", \"path\": \"string\", \"value\": {} } Let's modify this schema file to change the status of an attribute as below: In the above image, added two tasks. To know more about how we can modify this schema file to perform a specific task, follow this link: patch-request-schema Let's update an attribute by its inum value. In our case, inum : 6EEB. Before patching the selected attribute, you can check its properties using get-attributes-by-inum operation. Before patching the attribute, its properties are: { \"dn\": \"inum=6EEB,ou=attributes,o=jans\", \"inum\": \"6EEB\", \"selected\": false, \"name\": \"l\", \"displayName\": \"City\", \"description\": \"City\", \"dataType\": \"STRING\", \"status\": \"INACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": \"jansCustomPerson\", \"editType\": [ \"USER\", \"ADMIN\" ], \"viewType\": [ \"USER\", \"ADMIN\" ], \"usageType\": null, \"claimName\": \"locality\", \"seeAlso\": null, \"saml1Uri\": \"urn:mace:dir:attribute-def:l\", \"saml2Uri\": \"urn:oid:2.5.4.7\", \"urn\": \"urn:mace:dir:attribute-def:l\", \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null } According to the schema file, There should be two changes, status and jansHideOnDiscovery . Let's perform the operation: jans cli --operation-id patch-attributes-by-inum --url-suffix inum:6EEB --data /tmp/patch.json The updated attribute looks like: Getting access token for scope https://jans.io/oauth/config/attributes.write Server Response: { \"dn\": \"inum=6EEB,ou=attributes,o=jans\", \"inum\": \"6EEB\", \"selected\": false, \"name\": \"l\", \"displayName\": \"City\", \"description\": \"City\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": \"jansCustomPerson\", \"editType\": [ \"USER\", \"ADMIN\" ], \"viewType\": [ \"USER\", \"ADMIN\" ], \"usageType\": null, \"claimName\": \"locality\", \"seeAlso\": null, \"saml1Uri\": \"urn:mace:dir:attribute-def:l\", \"saml2Uri\": \"urn:oid:2.5.4.7\", \"urn\": \"urn:mace:dir:attribute-def:l\", \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": true } As you see, there are two changes.", "title": "Attribute"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#attribute", "text": "First thing, let's get the information for Attribute : jans cli --info Attribute In return, we get a list of Operations ID as below: Operation ID: get-attributes Description: Gets a list of Gluu attributes. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-attributes Description: Updates an existing attribute Schema: JansAttribute Operation ID: post-attributes Description: Adds a new attribute Schema: JansAttribute Operation ID: get-attributes-by-inum Description: Gets an attribute based on inum Parameters: inum: Attribute Id [string] Operation ID: delete-attributes-by-inum Description: Deletes an attribute based on inum Parameters: inum: Attribute Id [string] Operation ID: patch-attributes-by-inum Description: Partially modify a JansAttribute Parameters: inum: Attribute Id [string] Schema: Array of PatchRequest To get sample schema type jans cli --schema <schma>, for example jans cli --schema PatchRequest We have discussed here about each of this operations ID with few examples to understand how these really works.", "title": "Attribute"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#table-of-contents", "text": "Attribute Get Attributes Creating an Attribute Updating an Attribute Get Attribute by inum Delete Attributes Patch Attributes", "title": "Table of Contents"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#get-attributes", "text": "Prerequisite: Know how to use the Janssen CLI in command-line mode As we know, Attributes are individual pieces of user data, like uid or email , that are required by applications in order to identify a user and grant access to protect resources. The user attributes that are available in your Janssen Server can be found by using this operation-ID. If we look at the description below: Operation ID: get-attributes Description: Gets a list of Gluu attributes. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] To get all the attributes without any arguments, run the following command: jans cli --operation-id get-attributes To get attributes with passing the arguments, let's retrieve randomly limit:5: jans cli --operation-id get-attributes --endpoint-args limit:1 It will return only one attribute details randomly: Getting access token for scope https://jans.io/oauth/config/attributes.readonly Calling with params limit=1 { \"start\": 0, \"totalEntriesCount\": 71, \"entriesCount\": 1, \"entries\": [ { \"dn\": \"inum=29DA,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"29DA\", \"name\": \"inum\", \"displayName\": \"Inum\", \"description\": \"XRI i-number, persistent non-reassignable identifier\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"inum\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:inum\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.117\", \"urn\": \"urn:jans:dir:attribute-def:inum\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": false, \"whitePagesCanView\": false, \"baseDn\": \"inum=29DA,ou=attributes,o=jans\" } ] } To get attributes with pattern & status : jans cli --operation-id get-attributes --endpoint-args limit:3,pattern:profile,status:ACTIVE In return, we get a list of attribute that are matched with the given pattern and status : Please wait while retrieving data ... { \"start\": 0, \"totalEntriesCount\": 2, \"entriesCount\": 2, \"entries\": [ { \"dn\": \"inum=64A0,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"64A0\", \"name\": \"profile\", \"displayName\": \"Profile URL\", \"description\": \"URL of the End-User's profile page. The contents of this Web page SHOULD be about the End-User.\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"user\", \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"profile\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:profile\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.321\", \"urn\": \"http://openid.net/specs/openid-connect-core-1_0.html/StandardClaims/profile\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": true, \"whitePagesCanView\": false, \"baseDn\": \"inum=64A0,ou=attributes,o=jans\" }, { \"dn\": \"inum=EC3A,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"EC3A\", \"name\": \"picture\", \"displayName\": \"Picture URL\", \"description\": \"URL of the End-User's profile picture\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"user\", \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"picture\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:picture\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.322\", \"urn\": \"http://openid.net/specs/openid-connect-core-1_0.html/StandardClaims/picture\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": true, \"whitePagesCanView\": false, \"baseDn\": \"inum=EC3A,ou=attributes,o=jans\" } ] }", "title": "Get Attributes"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#creating-an-attribute", "text": "To create SSO for certain applications, you may need to add custom attributes to your Janssen Server. Custom attributes can be added by using this operation-ID. It has a schema file where it's defined: the properties it needs to be filled to create a new custom attribute. Operation ID: post-attributes Description: Adds a new attribute Schema: JansAttribute Before adding a new attribute, let's get sample schema : jans cli --schema JansAttribute > /tmp/attribute.json It will return as below: { \"dn\" : \"string\" , \"selected\" : false , \"inum\" : \"string\" , \"sourceAttribute\" : \"string\" , \"nameIdType\" : \"string\" , \"name\" : \"string\" , \"displayName\" : \"string\" , \"description\" : \"string\" , \"origin\" : \"string\" , \"dataType\" : \"certificate\" , \"editType\" : [ \"manager\" ], \"viewType\" : [ \"user\" ], \"usageType\" : [ \"openid\" ], \"claimName\" : \"string\" , \"seeAlso\" : \"string\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"string\" , \"saml2Uri\" : \"string\" , \"urn\" : \"string\" , \"scimCustomAttr\" : true , \"oxMultiValuedAttribute\" : true , \"jansHideOnDiscovery\" : true , \"custom\" : false , \"attributeValidation\" : { \"minLength\" : { \"type\" : \"integer\" , \"format\" : \"int32\" }, \"maxLength\" : { \"type\" : \"integer\" , \"format\" : \"int32\" }, \"regexp\" : { \"type\" : \"string\" } }, \"tooltip\" : \"string\" , \"whitePagesCanView\" : false , \"adminCanView\" : true , \"userCanAccess\" : false , \"userCanView\" : true , \"adminCanAccess\" : false , \"adminCanEdit\" : false , \"userCanEdit\" : true , \"baseDn\" : \"string\" } Modify it to update attribute name , display name , view type : nano /tmp/attribute.json Now, let's add this attribute using post-attributes : jans cli --operation-id post-attributes --data /tmp/attribute.json It will create a new attribute into the Attribute list with updated inum & dn : { \"dn\" : \"inum=0272b98e-0ead-43e9-94eb-4af9548af97d,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"0272b98e-0ead-43e9-94eb-4af9548af97d\" , \"nameIdType\" : \"string\" , \"name\" : \"testAttribute\" , \"displayName\" : \"testAttribute\" , \"description\" : \"testAttribute\" , \"dataType\" : \"certificate\" , \"editType\" : [ \"manager\" ], \"viewType\" : [ \"user\" ], \"usageType\" : [ \"openid\" ], \"status\" : \"inactive\" , \"scimCustomAttr\" : true , \"oxMultiValuedAttribute\" : true , \"jansHideOnDiscovery\" : true , \"custom\" : false , \"tooltip\" : \"string\" , \"adminCanAccess\" : false , \"adminCanView\" : false , \"adminCanEdit\" : false , \"userCanAccess\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"whitePagesCanView\" : false , \"baseDn\" : \"inum=0272b98e-0ead-43e9-94eb-4af9548af97d,ou=attributes,o=jans\" }", "title": "Creating an Attribute"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#updating-an-attribute", "text": "This operation-id can be used to update an existing attribute information. The Janssen Server administrator can make changes to attributes, such as changing their status to active/inactive by using this operation-ID. Let's look at the schema: jans cli --schema JansAttribute > /tmp/attrib.json You must see the similar schema while performed in post-attributes operation. To update an existing attribute, we have to ensure following properties in the schema file. In our case, I have modified the schema file as below: { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": true, \"name\": \"testAttribute\", \"display_name\": \"testAttribute\", \"description\": \"testing put-attribute\", \"data_type\": \"STRING\", \"status\": \"ACTIVE\", \"edit_type\": [\"ADMIN\", \"OWNER\"], \"view_type\": [\"ADMIN\", \"OWNER\", \"USER\"] } Now if we run the below command line: jans cli --operation-id put-attributes --data /tmp/attrb.json Getting access token for scope https://jans.io/oauth/config/attributes.write Server Response: { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": false, \"name\": \"testAttribute\", \"displayName\": \"testAttribute\", \"description\": \"testing put-attribute\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": null, \"editType\": [ \"ADMIN\", \"OWNER\" ], \"viewType\": [ \"ADMIN\", \"OWNER\", \"USER\" ], \"usageType\": null, \"claimName\": null, \"seeAlso\": null, \"saml1Uri\": null, \"saml2Uri\": null, \"urn\": null, \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null } It just replace the previous value with new one.", "title": "Updating an Attribute"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#get-attribute-by-inum", "text": "As we know, There are a lot of attributes available in the Janssen Server including custom attributes as well. You may want to know details information for a single attribute uniquely identified by inum . Getting an attribute information by using its inum is pretty simple. jans cli --operation-id get-attributes-by-inum --url-suffix inum:attribute-iunm-value It will show all details information of the selected Attribute as below example. jans cli --operation-id get-attributes-by-inum --url-suffix inum:b691f2ab-a7db-4725-b85b-9961575b441f Getting access token for scope https://jans.io/oauth/config/attributes.readonly { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": false, \"name\": \"testAttribute\", \"displayName\": \"testAttribute\", \"description\": \"testing put-attribute\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": null, \"editType\": [ \"ADMIN\", \"OWNER\" ], \"viewType\": [ \"ADMIN\", \"OWNER\", \"USER\" ], \"usageType\": null, \"claimName\": null, \"seeAlso\": null, \"saml1Uri\": null, \"saml2Uri\": null, \"urn\": null, \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null }", "title": "Get Attribute by inum"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#delete-attributes", "text": "For any reason, If it needs to delete any attribute, you can do that simply using its inum value. See below example, just change the inum value with one that you want to delete. jans cli --operation-id delete-attributes-by-inum --url-suffix inum:b691f2ab-a7db-4725-b85b-9961575b441f", "title": "Delete Attributes"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#patch-attributes", "text": "This operation can also used for updating an existing attribute by using its inum value. Operation ID: patch-attributes-by-inum Description: Partially modify a JansAttribute. url-suffix: inum Schema: Array of PatchRequest If we look at the description, we see that there is a schema file. Let's get the schema file with below command: jans cli --schema PatchRequest > /tmp/patch.json # cat /tmp/patch.json { \"op\": \"add\", \"path\": \"string\", \"value\": {} } Let's modify this schema file to change the status of an attribute as below: In the above image, added two tasks. To know more about how we can modify this schema file to perform a specific task, follow this link: patch-request-schema Let's update an attribute by its inum value. In our case, inum : 6EEB. Before patching the selected attribute, you can check its properties using get-attributes-by-inum operation. Before patching the attribute, its properties are: { \"dn\": \"inum=6EEB,ou=attributes,o=jans\", \"inum\": \"6EEB\", \"selected\": false, \"name\": \"l\", \"displayName\": \"City\", \"description\": \"City\", \"dataType\": \"STRING\", \"status\": \"INACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": \"jansCustomPerson\", \"editType\": [ \"USER\", \"ADMIN\" ], \"viewType\": [ \"USER\", \"ADMIN\" ], \"usageType\": null, \"claimName\": \"locality\", \"seeAlso\": null, \"saml1Uri\": \"urn:mace:dir:attribute-def:l\", \"saml2Uri\": \"urn:oid:2.5.4.7\", \"urn\": \"urn:mace:dir:attribute-def:l\", \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null } According to the schema file, There should be two changes, status and jansHideOnDiscovery . Let's perform the operation: jans cli --operation-id patch-attributes-by-inum --url-suffix inum:6EEB --data /tmp/patch.json The updated attribute looks like: Getting access token for scope https://jans.io/oauth/config/attributes.write Server Response: { \"dn\": \"inum=6EEB,ou=attributes,o=jans\", \"inum\": \"6EEB\", \"selected\": false, \"name\": \"l\", \"displayName\": \"City\", \"description\": \"City\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": \"jansCustomPerson\", \"editType\": [ \"USER\", \"ADMIN\" ], \"viewType\": [ \"USER\", \"ADMIN\" ], \"usageType\": null, \"claimName\": \"locality\", \"seeAlso\": null, \"saml1Uri\": \"urn:mace:dir:attribute-def:l\", \"saml2Uri\": \"urn:oid:2.5.4.7\", \"urn\": \"urn:mace:dir:attribute-def:l\", \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": true } As you see, there are two changes.", "title": "Patch Attributes"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/", "tags": ["administration", "configuration", "default authentication", "ACR", "authentication method"], "text": "Authentication Method Configuration # The Janssen Server allows administrators to set and manage the default authentication method for the authentication server. The Janssen Server provides multiple configuration tools to perform these tasks. Note Only one of the available authentication methods can be set as the default. While setting the Default authentication method, the Janssen Server checks if the same authentication is available and active. See script documentation to know how to enable/disable authentication methods using custom scripts. If the script is not active then the following error notification is returned by API. { \"code\": \"400\", \"message\": \"INVALID_ACR\", \"description\": \"Authentication script {acr} is not active\" } Also, to understand how Janssen Server picks the authentication method in the absence of the default authentication method, refer to ACR documentation Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # Operations to manage the default authentication method are grouped under the DefaultAuthenticationMethod task. To get information about those operations use the command below. Command jans cli --info DefaultAuthenticationMethod Output Operation ID: get-acrs Description: Gets default authentication method. Operation ID: put-acrs Description: Updates default authentication method. Schema: AuthenticationMethod To get sample schema type jans cli --schema <schma>, for example jans cli --schema /components/schemas/AuthenticationMethod Find Current Authentication Method # To get the current default authentication method use the command below. Command jans cli --operation-id get-acrs Sample Output { \"defaultAcr\" : \"simple_password_auth\" } Update Default Authentication Method # Let's update the Default Authentication Method using the Janssen CLI command line. To perform the put-acrs operation, we have to use its schema. To get its schema: Command jans cli --schema AuthenticationMethod > /tmp/patch-default-auth.json The schema can now be found in the patch-default-auth.json file. For your information, you can obtain the format of the AuthenticationMethod schema by running the aforementioned command without a file. Schema Format defaultAcr string you can also use the following command for AuthenticationMethod schema example. Command jans cli --schema-sample AuthenticationMethod Schema Example { \"defaultAcr\" : \"string\" } We need to modify the patch-default-auth.json file. We have seen that our default authentication method is simple_password_auth . We are going to update it with passport_saml authentication method. input { \"defaultAcr\" : \"passport_saml\" } Now let's trigger the operation using the above file. Command jans cli --operation-id put-acrs --data /tmp/patch-default-auth.json It will show the updated result. Sample Output { \"defaultAcr\" : \"passport_saml\" } Using Text-based UI # In Janssen, You can manage the default authentication method using the Text-Based UI also. You can start TUI using the command below: Command jans tui Find Current Default Authentication Method # Navigate to Auth Server -> Authn to open the Authn screen as shown in the image below. In Default ACR sub-tab, available authentication methods are listed as radio buttons. To update the default authentication method, bring the tab focus to the authentication method, and navigate to the new default method with Up and Down keys. To choose hit Space key. Navigate to Save button and hit Enter key Basic Authentication Method # This tab displays the basic, builtin, authentication method as shown in the image below. You can set basic as the default authentication method by selecting Default Authn Method , navigate to Save button and hit Enter key LDAP Servers As Authentication Method # In this tab you can add and modify LDAP Servers are to be used as the default authentication method. See below image To add a new LDAP server, navigate to Add Source LDAP Server button and hit Enter . A popup screen will be displayed as shown in the image below. Fill in the fields provided in the popup. Before saving LDAP server, it is recommended to test it by navigating Test button and hitting Enter . If the test is successful, chose Save button and hit Enter . If you want the current edited LDAP server as the default authentication method, select Default Authn Method before saving. Authentication Methods Enabled By Scripts # All enabled Person Authentication scripts are listed in this tab as below To edit Level and/or Properties of the authentication script, navigate to the script in the list by hitting tab key and hit Enter . You will see a popup like in the image below If the script you want to use as the default authentication method is not in the list, you should enable the script by navigating Scripts in the main tab. Find the script you want to enable and hit Enter , you will get a popup where you can select Enabled checkbox and Save it as shown in the image below: Configure Aliases For Authencation Methods # Authentication aliases are listed in this tab. You can modify aliases by navigating to the list and hitting Enter . If you want to add a new alias, choose Add Alias button and hit Enter Authentication Methods Enabled by Agama Flows # If you deployed an Agama project, ACR values for the project are displayed in this tab as shown below: Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Default Authentication Method. Endpoint details are published in the Swagger document .", "title": "Authentication Method Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#authentication-method-configuration", "text": "The Janssen Server allows administrators to set and manage the default authentication method for the authentication server. The Janssen Server provides multiple configuration tools to perform these tasks. Note Only one of the available authentication methods can be set as the default. While setting the Default authentication method, the Janssen Server checks if the same authentication is available and active. See script documentation to know how to enable/disable authentication methods using custom scripts. If the script is not active then the following error notification is returned by API. { \"code\": \"400\", \"message\": \"INVALID_ACR\", \"description\": \"Authentication script {acr} is not active\" } Also, to understand how Janssen Server picks the authentication method in the absence of the default authentication method, refer to ACR documentation Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Authentication Method Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#using-command-line", "text": "Operations to manage the default authentication method are grouped under the DefaultAuthenticationMethod task. To get information about those operations use the command below. Command jans cli --info DefaultAuthenticationMethod Output Operation ID: get-acrs Description: Gets default authentication method. Operation ID: put-acrs Description: Updates default authentication method. Schema: AuthenticationMethod To get sample schema type jans cli --schema <schma>, for example jans cli --schema /components/schemas/AuthenticationMethod", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#find-current-authentication-method", "text": "To get the current default authentication method use the command below. Command jans cli --operation-id get-acrs Sample Output { \"defaultAcr\" : \"simple_password_auth\" }", "title": "Find Current Authentication Method"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#update-default-authentication-method", "text": "Let's update the Default Authentication Method using the Janssen CLI command line. To perform the put-acrs operation, we have to use its schema. To get its schema: Command jans cli --schema AuthenticationMethod > /tmp/patch-default-auth.json The schema can now be found in the patch-default-auth.json file. For your information, you can obtain the format of the AuthenticationMethod schema by running the aforementioned command without a file. Schema Format defaultAcr string you can also use the following command for AuthenticationMethod schema example. Command jans cli --schema-sample AuthenticationMethod Schema Example { \"defaultAcr\" : \"string\" } We need to modify the patch-default-auth.json file. We have seen that our default authentication method is simple_password_auth . We are going to update it with passport_saml authentication method. input { \"defaultAcr\" : \"passport_saml\" } Now let's trigger the operation using the above file. Command jans cli --operation-id put-acrs --data /tmp/patch-default-auth.json It will show the updated result. Sample Output { \"defaultAcr\" : \"passport_saml\" }", "title": "Update Default Authentication Method"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#using-text-based-ui", "text": "In Janssen, You can manage the default authentication method using the Text-Based UI also. You can start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#find-current-default-authentication-method", "text": "Navigate to Auth Server -> Authn to open the Authn screen as shown in the image below. In Default ACR sub-tab, available authentication methods are listed as radio buttons. To update the default authentication method, bring the tab focus to the authentication method, and navigate to the new default method with Up and Down keys. To choose hit Space key. Navigate to Save button and hit Enter key", "title": "Find Current Default Authentication Method"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#basic-authentication-method", "text": "This tab displays the basic, builtin, authentication method as shown in the image below. You can set basic as the default authentication method by selecting Default Authn Method , navigate to Save button and hit Enter key", "title": "Basic Authentication Method"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#ldap-servers-as-authentication-method", "text": "In this tab you can add and modify LDAP Servers are to be used as the default authentication method. See below image To add a new LDAP server, navigate to Add Source LDAP Server button and hit Enter . A popup screen will be displayed as shown in the image below. Fill in the fields provided in the popup. Before saving LDAP server, it is recommended to test it by navigating Test button and hitting Enter . If the test is successful, chose Save button and hit Enter . If you want the current edited LDAP server as the default authentication method, select Default Authn Method before saving.", "title": "LDAP Servers As Authentication Method"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#authentication-methods-enabled-by-scripts", "text": "All enabled Person Authentication scripts are listed in this tab as below To edit Level and/or Properties of the authentication script, navigate to the script in the list by hitting tab key and hit Enter . You will see a popup like in the image below If the script you want to use as the default authentication method is not in the list, you should enable the script by navigating Scripts in the main tab. Find the script you want to enable and hit Enter , you will get a popup where you can select Enabled checkbox and Save it as shown in the image below:", "title": "Authentication Methods Enabled By Scripts"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#configure-aliases-for-authencation-methods", "text": "Authentication aliases are listed in this tab. You can modify aliases by navigating to the list and hitting Enter . If you want to add a new alias, choose Add Alias button and hit Enter", "title": "Configure Aliases For Authencation Methods"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#authentication-methods-enabled-by-agama-flows", "text": "If you deployed an Agama project, ACR values for the project are displayed in this tab as shown below:", "title": "Authentication Methods Enabled by Agama Flows"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Default Authentication Method. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/", "tags": ["administration", "configuration", "cache"], "text": "Cache Configuration # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Cache configuration is not possible in Text-based UI. Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # To get the details of Janssen command line operations relevant to the cache configuration, you can check the operations under CacheConfiguration using the command below: Command jans cli --info CacheConfiguration It prints below two operations: Output Operation ID: get-config-cache Description: Returns cache configuration. Operation ID: patch-config-cache Description: Patch cache configuration Schema: Array of JsonPatch To get sample schema type jans cli --schema <schema>, for example jans cli --schema JsonPatch Get Cache Configuration # You can get the current Cache Configuration of your Janssen Server by performing this operation. Command jans cli --operation-id get-config-cache It will show the Cache configuration details. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { \"cacheProviderType\" : \"NATIVE_PERSISTENCE\" , \"memcachedConfiguration\" : { \"servers\" : \"localhost:11211\" , \"maxOperationQueueLength\" : 100000 , \"bufferSize\" : 32768 , \"defaultPutExpiration\" : 60 , \"connectionFactoryType\" : \"DEFAULT\" }, \"inMemoryConfiguration\" : { \"defaultPutExpiration\" : 60 }, \"redisConfiguration\" : { \"redisProviderType\" : \"STANDALONE\" , \"servers\" : \"localhost:6379\" , \"defaultPutExpiration\" : 60 , \"useSSL\" : false , \"maxIdleConnections\" : 10 , \"maxTotalConnections\" : 500 , \"connectionTimeout\" : 3000 , \"soTimeout\" : 3000 , \"maxRetryAttempts\" : 5 }, \"nativePersistenceConfiguration\" : { \"defaultPutExpiration\" : 60 , \"defaultCleanupBatchSize\" : 10000 , \"deleteExpiredOnGetRequest\" : false , \"disableAttemptUpdateBeforeInsert\" : false } } Patch Cache Configuration # You may need to update Cache configuration, In that case patch-config-cache can be used to modify the cache configuration. Operation ID: patch-config-cache Description: Patch cache configuration Schema: Array of JsonPatch To get sample schema type jans cli --schema <schema>, for example jans cli --schema JsonPatch The patch-config-cache operation uses the JSON Patch schema to describe the configuration change. Refer here to know more about schema. For instance, to perform a replace operation at memcachedConfiguration/bufferSize and change it from 32768 to 32788 , the JSON Patch data would look like below: Input [ { \"op\" : \"replace\" , \"path\" : \"memcachedConfiguration/bufferSize\" , \"value\" : \"32788\" } ] Store the above JSON Patch data in a file, for instance, /tmp/patch-cache.json Using the above file, perform the operation as below: Sample Command jans cli --operation-id patch-config-cache --data /tmp/patch-cache.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { \"cacheProviderType\" : \"NATIVE_PERSISTENCE\" , \"memcachedConfiguration\" : { \"servers\" : \"localhost:11211\" , \"maxOperationQueueLength\" : 100000 , \"bufferSize\" : 32788 , \"defaultPutExpiration\" : 60 , \"connectionFactoryType\" : \"DEFAULT\" }, \"inMemoryConfiguration\" : { \"defaultPutExpiration\" : 60 }, \"redisConfiguration\" : { \"redisProviderType\" : \"STANDALONE\" , \"servers\" : \"localhost:6379\" , \"defaultPutExpiration\" : 60 , \"useSSL\" : false , \"maxIdleConnections\" : 10 , \"maxTotalConnections\" : 500 , \"connectionTimeout\" : 3000 , \"soTimeout\" : 3000 , \"maxRetryAttempts\" : 5 }, \"nativePersistenceConfiguration\" : { \"defaultPutExpiration\" : 60 , \"defaultCleanupBatchSize\" : 10000 , \"deleteExpiredOnGetRequest\" : false , \"disableAttemptUpdateBeforeInsert\" : false } } Quick Patch Operation # In case you need to do a quick patch operation, you can do that also. For example, let's say we would like to replace defaultPutExpiration value from nativePersistenceConfiguration . We can do that simply by the following command line: Command jans cli --operation-id patch-config-cache \\ --patch-replace nativePersistenceConfiguration/defaultPutExpiration:90 It will change the value with the given one. There are few options to do such quick patch operations. Please check them out from here . Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring Cache. Endpoint details are published in the Swagger document .", "title": "Cache Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#cache-configuration", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Cache configuration is not possible in Text-based UI. Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Cache Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#using-command-line", "text": "To get the details of Janssen command line operations relevant to the cache configuration, you can check the operations under CacheConfiguration using the command below: Command jans cli --info CacheConfiguration It prints below two operations: Output Operation ID: get-config-cache Description: Returns cache configuration. Operation ID: patch-config-cache Description: Patch cache configuration Schema: Array of JsonPatch To get sample schema type jans cli --schema <schema>, for example jans cli --schema JsonPatch", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#get-cache-configuration", "text": "You can get the current Cache Configuration of your Janssen Server by performing this operation. Command jans cli --operation-id get-config-cache It will show the Cache configuration details. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { \"cacheProviderType\" : \"NATIVE_PERSISTENCE\" , \"memcachedConfiguration\" : { \"servers\" : \"localhost:11211\" , \"maxOperationQueueLength\" : 100000 , \"bufferSize\" : 32768 , \"defaultPutExpiration\" : 60 , \"connectionFactoryType\" : \"DEFAULT\" }, \"inMemoryConfiguration\" : { \"defaultPutExpiration\" : 60 }, \"redisConfiguration\" : { \"redisProviderType\" : \"STANDALONE\" , \"servers\" : \"localhost:6379\" , \"defaultPutExpiration\" : 60 , \"useSSL\" : false , \"maxIdleConnections\" : 10 , \"maxTotalConnections\" : 500 , \"connectionTimeout\" : 3000 , \"soTimeout\" : 3000 , \"maxRetryAttempts\" : 5 }, \"nativePersistenceConfiguration\" : { \"defaultPutExpiration\" : 60 , \"defaultCleanupBatchSize\" : 10000 , \"deleteExpiredOnGetRequest\" : false , \"disableAttemptUpdateBeforeInsert\" : false } }", "title": "Get Cache Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#patch-cache-configuration", "text": "You may need to update Cache configuration, In that case patch-config-cache can be used to modify the cache configuration. Operation ID: patch-config-cache Description: Patch cache configuration Schema: Array of JsonPatch To get sample schema type jans cli --schema <schema>, for example jans cli --schema JsonPatch The patch-config-cache operation uses the JSON Patch schema to describe the configuration change. Refer here to know more about schema. For instance, to perform a replace operation at memcachedConfiguration/bufferSize and change it from 32768 to 32788 , the JSON Patch data would look like below: Input [ { \"op\" : \"replace\" , \"path\" : \"memcachedConfiguration/bufferSize\" , \"value\" : \"32788\" } ] Store the above JSON Patch data in a file, for instance, /tmp/patch-cache.json Using the above file, perform the operation as below: Sample Command jans cli --operation-id patch-config-cache --data /tmp/patch-cache.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { \"cacheProviderType\" : \"NATIVE_PERSISTENCE\" , \"memcachedConfiguration\" : { \"servers\" : \"localhost:11211\" , \"maxOperationQueueLength\" : 100000 , \"bufferSize\" : 32788 , \"defaultPutExpiration\" : 60 , \"connectionFactoryType\" : \"DEFAULT\" }, \"inMemoryConfiguration\" : { \"defaultPutExpiration\" : 60 }, \"redisConfiguration\" : { \"redisProviderType\" : \"STANDALONE\" , \"servers\" : \"localhost:6379\" , \"defaultPutExpiration\" : 60 , \"useSSL\" : false , \"maxIdleConnections\" : 10 , \"maxTotalConnections\" : 500 , \"connectionTimeout\" : 3000 , \"soTimeout\" : 3000 , \"maxRetryAttempts\" : 5 }, \"nativePersistenceConfiguration\" : { \"defaultPutExpiration\" : 60 , \"defaultCleanupBatchSize\" : 10000 , \"deleteExpiredOnGetRequest\" : false , \"disableAttemptUpdateBeforeInsert\" : false } }", "title": "Patch Cache Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#quick-patch-operation", "text": "In case you need to do a quick patch operation, you can do that also. For example, let's say we would like to replace defaultPutExpiration value from nativePersistenceConfiguration . We can do that simply by the following command line: Command jans cli --operation-id patch-config-cache \\ --patch-replace nativePersistenceConfiguration/defaultPutExpiration:90 It will change the value with the given one. There are few options to do such quick patch operations. Please check them out from here .", "title": "Quick Patch Operation"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring Cache. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/", "tags": ["administration", "configuration", "jans-auth-server"], "text": "Janssen Authorization Server # Prerequisite: Know how to use the Janssen CLI in command-line mode To get info about Jans Authorization Server operations: jans cli --info ConfigurationProperties Operation ID: get-properties Description: Gets all Jans authorization server configuration properties. Operation ID: patch-properties Description: Partially modifies Jans authorization server AppConfiguration properties. Schema: Array of JsonPatch Operation ID: get-properties-persistence Description: Returns persistence type configured for Jans authorization server. To get sample schema type jans cli --schema <schma>, for example jans cli --schema JsonPatch Jans Authorization server has two operations id to get/modify its properties. Table of Contents # Janssen Authorization Server Table of Contents Get All Jans Auth Server Configuration Properties Partially Modify Jans Auth Server Configuration Properties Get Persistence type for Jans Auth Get All Jans Auth Server Configuration Properties # It returns all the information of the Jans Authorization server. jans cli --operation-id get-properties ``` You will get output like below ```json { \"issuer\": \"https://example.jans.io\", \"baseEndpoint\": \"https://example.jans.io/jans-auth/restv1\", \"authorizationEndpoint\": \"https://example.jans.io/jans-auth/restv1/authorize\", \"authorizationChallengeEndpoint\":\"https://example.jans.io/jans-auth/restv1/authorize-challenge\", \"tokenEndpoint\": \"https://example.jans.io/jans-auth/restv1/token\", \"tokenRevocationEndpoint\": \"https://example.jans.io/jans-auth/restv1/revoke\", \"userInfoEndpoint\": \"https://example.jans.io/jans-auth/restv1/userinfo\", \"clientInfoEndpoint\": \"https://example.jans.io/jans-auth/restv1/clientinfo\", \"checkSessionIFrame\": \"https://example.jans.io/jans-auth/opiframe.htm\", \"endSessionEndpoint\": \"https://example.jans.io/jans-auth/restv1/end_session\", \"jwksUri\": \"https://example.jans.io/jans-auth/restv1/jwks\", \"registrationEndpoint\": \"https://example.jans.io/jans-auth/restv1/register\", \"openIdDiscoveryEndpoint\": \"https://example.jans.io/.well-known/webfinger\", \"openIdConfigurationEndpoint\": \"https://example.jans.io/.well-known/openid-configuration\", \"idGenerationEndpoint\": \"https://example.jans.io/jans-auth/restv1/id\", \"introspectionEndpoint\": \"https://example.jans.io/jans-auth/restv1/introspection\", \"parEndpoint\": \"https://example.jans.io/jans-auth/restv1/par\", \"requirePar\": false, \"deviceAuthzEndpoint\": \"https://example.jans.io/jans-auth/restv1/device_authorization\", \"requireRequestObjectEncryption\": false, \"requirePkce\": false, \"allowAllValueForRevokeEndpoint\": false, \"sectorIdentifierCacheLifetimeInMinutes\": 1440, \"umaConfigurationEndpoint\": \"https://example.jans.io/jans-auth/restv1/uma2-configuration\", \"umaRptAsJwt\": false, \"umaRptLifetime\": 3600, \"umaTicketLifetime\": 3600, \"umaPctLifetime\": 1728000, \"umaResourceLifetime\": 1728000, \"umaAddScopesAutomatically\": true, \"umaValidateClaimToken\": false, \"umaGrantAccessIfNoPolicies\": false, \"umaRestrictResourceToAssociatedClient\": false, \"statTimerIntervalInSeconds\": 0, \"statAuthorizationScope\": \"jans_stat\", \"allowSpontaneousScopes\": false, \"spontaneousScopeLifetime\": 86400, \"openidSubAttribute\": \"inum\", \"publicSubjectIdentifierPerClientEnabled\": true, \"subjectIdentifiersPerClientSupported\": [ \"mail\", \"uid\" ], \"responseTypesSupported\": [ [ \"code\", \"id_token\" ], [ \"code\", \"token\" ], [ \"code\" ], [ \"token\", \"id_token\" ], [ \"token\" ], [ \"code\", \"token\", \"id_token\" ], [ \"id_token\" ] ], \"responseModesSupported\": [ \"form_post.jwt\", \"form_post\", \"fragment\", \"query.jwt\", \"fragment.jwt\", \"jwt\", \"query\" ], \"grantTypesSupported\": [ \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"implicit\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"urn:ietf:params:oauth:grant-type:device_code\", \"client_credentials\", \"refresh_token\", \"authorization_code\", \"password\", \"tx_token\" ], \"subjectTypesSupported\": [ \"public\", \"pairwise\" ], \"defaultSubjectType\": \"pairwise\", \"authorizationSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorizationEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"authorizationEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"userInfoSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"userInfoEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"userInfoEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"idTokenSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"idTokenEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"idTokenEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"accessTokenSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"forceSignedRequestObject\": false, \"requestObjectSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"requestObjectEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"requestObjectEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"tokenEndpointAuthMethodsSupported\": [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tokenEndpointAuthSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"displayValuesSupported\": [ \"page\", \"popup\" ], \"claimTypesSupported\": [ \"normal\" ], \"jwksAlgorithmsSupported\": [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"PS256\", \"PS384\", \"PS512\", \"RSA1_5\", \"RSA-OAEP\" ], \"serviceDocumentation\": \"http://jans.org/docs\", \"claimsLocalesSupported\": [ \"en\" ], \"idTokenTokenBindingCnfValuesSupported\": [ \"tbh\" ], \"uiLocalesSupported\": [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"claimsParameterSupported\": false, \"requestParameterSupported\": true, \"requestUriParameterSupported\": true, \"requestUriHashVerificationEnabled\": false, \"requireRequestUriRegistration\": false, \"requestUriBlockList\": [ \"localhost\", \"127.0.0.1\" ], \"opPolicyUri\": \"https://example.jans.io/opPolicy\", \"opTosUri\": \"https://example.jans.io/tos\", \"authorizationCodeLifetime\": 60, \"refreshTokenLifetime\": 14400, \"txTokenLifetime\": 180, \"idTokenLifetime\": 3600, \"idTokenFilterClaimsBasedOnAccessToken\": false, \"accessTokenLifetime\": 300, \"cleanServiceInterval\": 60, \"cleanServiceBatchChunkSize\": 10000, \"keyRegenerationEnabled\": true, \"keyRegenerationInterval\": 48, \"defaultSignatureAlgorithm\": \"RS256\", \"jansOpenIdConnectVersion\": \"openidconnect-1.0\", \"jansId\": \"https://example.jans.io/oxid/service/jans/inum\", \"dynamicRegistrationExpirationTime\": -1, \"dynamicRegistrationPersistClientAuthorizations\": true, \"trustedClientEnabled\": true, \"skipAuthorizationForOpenIdScopeAndPairwiseId\": false, \"dynamicRegistrationScopesParamEnabled\": true, \"dynamicRegistrationPasswordGrantTypeEnabled\": false, \"personCustomObjectClassList\": [ \"jansCustomPerson\", \"jansPerson\" ], \"persistIdToken\": false, \"persistRefreshToken\": true, \"allowPostLogoutRedirectWithoutValidation\": false, \"invalidateSessionCookiesAfterAuthorizationFlow\": false, \"returnClientSecretOnRead\": true, \"rotateClientRegistrationAccessTokenOnUsage\": false, \"rejectJwtWithNoneAlg\": true, \"expirationNotificatorEnabled\": false, \"useNestedJwtDuringEncryption\": true, \"expirationNotificatorMapSizeLimit\": 100000, \"expirationNotificatorIntervalInSeconds\": 600, \"redirectUrisRegexEnabled\": true, \"useHighestLevelScriptIfAcrScriptNotFound\": false, \"authenticationFiltersEnabled\": false, \"clientAuthenticationFiltersEnabled\": false, \"clientRegDefaultToCodeFlowWithRefresh\": true, \"grantTypesAndResponseTypesAutofixEnabled\": false, \"authenticationFilters\": [ { \"filter\": \"(&(mail=*{0}*)(inum={1}))\", \"bind\": false, \"baseDn\": \"ou=people,o=jans\" }, { \"filter\": \"uid={0}\", \"bind\": true, \"bindPasswordAttribute\": \"pwd\", \"baseDn\": \"ou=people,o=jans\" } ], \"clientAuthenticationFilters\": [ { \"filter\": \"myCustomAttr1={0}\", \"baseDn\": \"ou=clients,o=jans\" } ], \"corsConfigurationFilters\": [ { \"filterName\": \"CorsFilter\", \"corsEnabled\": true, \"corsAllowedOrigins\": \"*\", \"corsAllowedMethods\": \"GET,POST,HEAD,OPTIONS\", \"corsAllowedHeaders\": \"Origin,Authorization,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers\", \"corsSupportCredentials\": true, \"corsLoggingEnabled\": false, \"corsPreflightMaxAge\": 1800, \"corsRequestDecorate\": true } ], \"sessionIdUnusedLifetime\": 86400, \"sessionIdUnauthenticatedUnusedLifetime\": 7200, \"sessionIdPersistOnPromptNone\": true, \"sessionIdRequestParameterEnabled\": false, \"changeSessionIdOnAuthentication\": true, \"sessionIdPersistInCache\": false, \"includeSidInResponse\": false, \"disablePromptLogin\": false, \"disablePromptConsent\": false, \"sessionIdLifetime\": 86400, \"sessionIdCookieLifetime\": 86400, \"configurationUpdateInterval\": 3600, \"enableClientGrantTypeUpdate\": true, \"grantTypesSupportedByDynamicRegistration\": [ \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"implicit\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"urn:ietf:params:oauth:grant-type:device_code\", \"client_credentials\", \"refresh_token\", \"authorization_code\", \"tx_token\" ], \"metricReporterInterval\": 300, \"metricReporterKeepDataDays\": 15, \"pairwiseIdType\": \"algorithmic\", \"pairwiseCalculationKey\": \"9jwJNNXd9mMua666QDhfEKGcR\", \"pairwiseCalculationSalt\": \"aUn2q1HDtsUXtmTNovNeN1QTk\", \"shareSubjectIdBetweenClientsWithSameSectorId\": true, \"webKeysStorage\": \"keystore\", \"dnName\": \"CN=Jans Auth CA Certificates\", \"keyStoreFile\": \"/etc/certs/jans-auth-keys.pkcs12\", \"keyStoreSecret\": \"S63ogThoRsEf\", \"keySelectionStrategy\": \"OLDER\", \"keySignWithSameKeyButDiffAlg\": false, \"introspectionAccessTokenMustHaveUmaProtectionScope\": false, \"introspectionAccessTokenMustHaveIntrospectionScope\": false, \"introspectionSkipAuthorization\": false, \"endSessionWithAccessToken\": false, \"clientWhiteList\": [ \"*\" ], \"clientBlackList\": [ \"*.attacker.com/*\" ], \"legacyIdTokenClaims\": false, \"customHeadersWithAuthorizationResponse\": true, \"frontChannelLogoutSessionSupported\": true, \"loggingLevel\": \"INFO\", \"loggingLayout\": \"text\", \"updateUserLastLogonTime\": false, \"updateClientAccessTime\": false, \"logClientIdOnClientAuthentication\": true, \"logClientNameOnClientAuthentication\": false, \"disableJdkLogger\": true, \"authorizationRequestCustomAllowedParameters\": [ { \"paramName\": \"customParam3\", \"returnInResponse\": false }, { \"paramName\": \"customParam4\", \"returnInResponse\": true }, { \"paramName\": \"customParam5\", \"returnInResponse\": true }, { \"paramName\": \"customParam1\", \"returnInResponse\": false }, { \"paramName\": \"customParam2\", \"returnInResponse\": false } ], \"openidScopeBackwardCompatibility\": false, \"disableU2fEndpoint\": false, \"rotateDeviceSecret\": false, \"returnDeviceSecretFromAuthzEndpoint\": false, \"dcrSignatureValidationEnabled\": false, \"dcrAuthorizationWithClientCredentials\": false, \"dcrAuthorizationWithMTLS\": false, \"useLocalCache\": true, \"fapiCompatibility\": false, \"forceIdTokenHintPresence\": false, \"rejectEndSessionIfIdTokenExpired\": false, \"allowEndSessionWithUnmatchedSid\": false, \"forceOfflineAccessScopeToEnableRefreshToken\": true, \"errorReasonEnabled\": false, \"removeRefreshTokensForClientOnLogout\": true, \"skipRefreshTokenDuringRefreshing\": false, \"refreshTokenExtendLifetimeOnRotation\": false, \"checkUserPresenceOnRefreshToken\": false, \"consentGatheringScriptBackwardCompatibility\": false, \"introspectionScriptBackwardCompatibility\": false, \"introspectionResponseScopesBackwardCompatibility\": false, \"softwareStatementValidationType\": \"script\", \"authenticationProtectionConfiguration\": { \"attemptExpiration\": 15, \"maximumAllowedAttemptsWithoutDelay\": 4, \"delayTime\": 2, \"bruteForceProtectionEnabled\": false }, \"errorHandlingMethod\": \"remote\", \"keepAuthenticatorAttributesOnAcrChange\": false, \"deviceAuthzRequestExpiresIn\": 1800, \"deviceAuthzTokenPollInterval\": 5, \"deviceAuthzResponseTypeToProcessAuthz\": \"code\", \"backchannelRedirectUri\": \"https://example.jans.io/jans-auth/ciba/home.htm\", \"backchannelAuthenticationEndpoint\": \"https://example.jans.io/jans-auth/restv1/bc-authorize\", \"backchannelDeviceRegistrationEndpoint\": \"https://example.jans.io/jans-auth/restv1/bc-deviceRegistration\", \"backchannelTokenDeliveryModesSupported\": [ \"poll\", \"ping\", \"push\" ], \"backchannelUserCodeParameterSupported\": false, \"backchannelBindingMessagePattern\": \"^[a-zA-Z0-9]{4,8}$\", \"backchannelAuthenticationResponseExpiresIn\": 3600, \"backchannelAuthenticationResponseInterval\": 2, \"backchannelLoginHintClaims\": [ \"inum\", \"uid\", \"mail\" ], \"cibaEndUserNotificationConfig\": {}, \"backchannelRequestsProcessorJobIntervalSec\": 5, \"backchannelRequestsProcessorJobChunkSize\": 100, \"cibaGrantLifeExtraTimeSec\": 180, \"cibaMaxExpirationTimeAllowedSec\": 1800, \"dpopSigningAlgValuesSupported\": [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"dpopTimeframe\": 5, \"dpopJtiCacheTime\": 3600, \"allowIdTokenWithoutImplicitGrantType\": false, \"discoveryCacheLifetimeInMinutes\": 60, \"discoveryDenyKeys\": [ \"id_generation_endpoint\", \"auth_level_mapping\", \"scope_to_claims_mapping\", \"op_policy_uri\" ], \"httpLoggingEnabled\": false, \"agamaConfiguration\": { \"enabled\": false, \"rootDir\": \"/opt/jans/jetty/jans-auth/agama\", \"templatesPath\": \"/ftl\", \"scriptsPath\": \"/scripts\", \"serializerType\": \"KRYO\", \"maxItemsLoggedInCollections\": 9, \"pageMismatchErrorPage\": \"mismatch.ftlh\", \"interruptionErrorPage\": \"timeout.ftlh\", \"crashErrorPage\": \"crash.ftlh\", \"finishedFlowPage\": \"finished.ftlh\", \"bridgeScriptPage\": \"agama.xhtml\", \"defaultResponseHeaders\": { \"Cache-Control\": \"max-age=0, no-store\" } }, \"ssaConfiguration\": { \"ssaEndpoint\": \"https://example.jans.io/jans-auth/restv1/ssa\", \"ssaSigningAlg\": \"RS256\", \"ssaExpirationInDays\": 30 }, \"blockWebviewAuthorizationEnabled\": false, \"dateFormatterPatterns\": { \"birthdate\": \"yyyy-MM-dd\" }, \"httpLoggingResponseBodyContent\": false, \"fapi\": false, \"allResponseTypesSupported\": [ \"code\", \"id_token\", \"token\" ] } Partially Modify Jans Auth Server Configuration Properties # Operation ID: patch-properties Description: Partially modifies Jans authorization server AppConfiguration properties. Schema: Array of /components/schemas/PatchRequest To get sample shema type jans cli --schema <schma>, for example jans cli --schema /components/schemas/PatchRequest Let's look at the schema first: jans cli --schema /components/schemas/PatchRequest > /tmp/patch-jans-auth.json It will create a .json file in /tmp with schema. Let's modify this schema: nano /tmp/patch-jans-auth.json This schema has three properties; op , path & value . Let's perform a replace operation at cibaEnabled to change it from false to true . So, the .json file will look like this: [ { \"op\": \"replace\", \"path\": \"cibaEnabled\", \"value\": true } ] Don't forget to use square brackets ( [] ). Otherwise, it won't work. Now, let's do the operation. jans cli --operation-id patch-properties --data /tmp/patch-jans-auth.json If you run the following command line, you must see that cibaEnabled is true : Get Persistence type for Jans Auth Configuration # You can get the persistence details for jans auth server. jans cli --operation-id get-properties-persistence Default persistence type is MySQL . Please wait while retrieving data ... { \"persistenceType\": \"sql\" }", "title": "Auth Server Property Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/#janssen-authorization-server", "text": "Prerequisite: Know how to use the Janssen CLI in command-line mode To get info about Jans Authorization Server operations: jans cli --info ConfigurationProperties Operation ID: get-properties Description: Gets all Jans authorization server configuration properties. Operation ID: patch-properties Description: Partially modifies Jans authorization server AppConfiguration properties. Schema: Array of JsonPatch Operation ID: get-properties-persistence Description: Returns persistence type configured for Jans authorization server. To get sample schema type jans cli --schema <schma>, for example jans cli --schema JsonPatch Jans Authorization server has two operations id to get/modify its properties.", "title": "Janssen Authorization Server"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/#table-of-contents", "text": "Janssen Authorization Server Table of Contents Get All Jans Auth Server Configuration Properties Partially Modify Jans Auth Server Configuration Properties Get Persistence type for Jans Auth", "title": "Table of Contents"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/#get-all-jans-auth-server-configuration-properties", "text": "It returns all the information of the Jans Authorization server. jans cli --operation-id get-properties ``` You will get output like below ```json { \"issuer\": \"https://example.jans.io\", \"baseEndpoint\": \"https://example.jans.io/jans-auth/restv1\", \"authorizationEndpoint\": \"https://example.jans.io/jans-auth/restv1/authorize\", \"authorizationChallengeEndpoint\":\"https://example.jans.io/jans-auth/restv1/authorize-challenge\", \"tokenEndpoint\": \"https://example.jans.io/jans-auth/restv1/token\", \"tokenRevocationEndpoint\": \"https://example.jans.io/jans-auth/restv1/revoke\", \"userInfoEndpoint\": \"https://example.jans.io/jans-auth/restv1/userinfo\", \"clientInfoEndpoint\": \"https://example.jans.io/jans-auth/restv1/clientinfo\", \"checkSessionIFrame\": \"https://example.jans.io/jans-auth/opiframe.htm\", \"endSessionEndpoint\": \"https://example.jans.io/jans-auth/restv1/end_session\", \"jwksUri\": \"https://example.jans.io/jans-auth/restv1/jwks\", \"registrationEndpoint\": \"https://example.jans.io/jans-auth/restv1/register\", \"openIdDiscoveryEndpoint\": \"https://example.jans.io/.well-known/webfinger\", \"openIdConfigurationEndpoint\": \"https://example.jans.io/.well-known/openid-configuration\", \"idGenerationEndpoint\": \"https://example.jans.io/jans-auth/restv1/id\", \"introspectionEndpoint\": \"https://example.jans.io/jans-auth/restv1/introspection\", \"parEndpoint\": \"https://example.jans.io/jans-auth/restv1/par\", \"requirePar\": false, \"deviceAuthzEndpoint\": \"https://example.jans.io/jans-auth/restv1/device_authorization\", \"requireRequestObjectEncryption\": false, \"requirePkce\": false, \"allowAllValueForRevokeEndpoint\": false, \"sectorIdentifierCacheLifetimeInMinutes\": 1440, \"umaConfigurationEndpoint\": \"https://example.jans.io/jans-auth/restv1/uma2-configuration\", \"umaRptAsJwt\": false, \"umaRptLifetime\": 3600, \"umaTicketLifetime\": 3600, \"umaPctLifetime\": 1728000, \"umaResourceLifetime\": 1728000, \"umaAddScopesAutomatically\": true, \"umaValidateClaimToken\": false, \"umaGrantAccessIfNoPolicies\": false, \"umaRestrictResourceToAssociatedClient\": false, \"statTimerIntervalInSeconds\": 0, \"statAuthorizationScope\": \"jans_stat\", \"allowSpontaneousScopes\": false, \"spontaneousScopeLifetime\": 86400, \"openidSubAttribute\": \"inum\", \"publicSubjectIdentifierPerClientEnabled\": true, \"subjectIdentifiersPerClientSupported\": [ \"mail\", \"uid\" ], \"responseTypesSupported\": [ [ \"code\", \"id_token\" ], [ \"code\", \"token\" ], [ \"code\" ], [ \"token\", \"id_token\" ], [ \"token\" ], [ \"code\", \"token\", \"id_token\" ], [ \"id_token\" ] ], \"responseModesSupported\": [ \"form_post.jwt\", \"form_post\", \"fragment\", \"query.jwt\", \"fragment.jwt\", \"jwt\", \"query\" ], \"grantTypesSupported\": [ \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"implicit\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"urn:ietf:params:oauth:grant-type:device_code\", \"client_credentials\", \"refresh_token\", \"authorization_code\", \"password\", \"tx_token\" ], \"subjectTypesSupported\": [ \"public\", \"pairwise\" ], \"defaultSubjectType\": \"pairwise\", \"authorizationSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorizationEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"authorizationEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"userInfoSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"userInfoEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"userInfoEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"idTokenSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"idTokenEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"idTokenEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"accessTokenSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"forceSignedRequestObject\": false, \"requestObjectSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"requestObjectEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"requestObjectEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"tokenEndpointAuthMethodsSupported\": [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tokenEndpointAuthSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"displayValuesSupported\": [ \"page\", \"popup\" ], \"claimTypesSupported\": [ \"normal\" ], \"jwksAlgorithmsSupported\": [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"PS256\", \"PS384\", \"PS512\", \"RSA1_5\", \"RSA-OAEP\" ], \"serviceDocumentation\": \"http://jans.org/docs\", \"claimsLocalesSupported\": [ \"en\" ], \"idTokenTokenBindingCnfValuesSupported\": [ \"tbh\" ], \"uiLocalesSupported\": [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"claimsParameterSupported\": false, \"requestParameterSupported\": true, \"requestUriParameterSupported\": true, \"requestUriHashVerificationEnabled\": false, \"requireRequestUriRegistration\": false, \"requestUriBlockList\": [ \"localhost\", \"127.0.0.1\" ], \"opPolicyUri\": \"https://example.jans.io/opPolicy\", \"opTosUri\": \"https://example.jans.io/tos\", \"authorizationCodeLifetime\": 60, \"refreshTokenLifetime\": 14400, \"txTokenLifetime\": 180, \"idTokenLifetime\": 3600, \"idTokenFilterClaimsBasedOnAccessToken\": false, \"accessTokenLifetime\": 300, \"cleanServiceInterval\": 60, \"cleanServiceBatchChunkSize\": 10000, \"keyRegenerationEnabled\": true, \"keyRegenerationInterval\": 48, \"defaultSignatureAlgorithm\": \"RS256\", \"jansOpenIdConnectVersion\": \"openidconnect-1.0\", \"jansId\": \"https://example.jans.io/oxid/service/jans/inum\", \"dynamicRegistrationExpirationTime\": -1, \"dynamicRegistrationPersistClientAuthorizations\": true, \"trustedClientEnabled\": true, \"skipAuthorizationForOpenIdScopeAndPairwiseId\": false, \"dynamicRegistrationScopesParamEnabled\": true, \"dynamicRegistrationPasswordGrantTypeEnabled\": false, \"personCustomObjectClassList\": [ \"jansCustomPerson\", \"jansPerson\" ], \"persistIdToken\": false, \"persistRefreshToken\": true, \"allowPostLogoutRedirectWithoutValidation\": false, \"invalidateSessionCookiesAfterAuthorizationFlow\": false, \"returnClientSecretOnRead\": true, \"rotateClientRegistrationAccessTokenOnUsage\": false, \"rejectJwtWithNoneAlg\": true, \"expirationNotificatorEnabled\": false, \"useNestedJwtDuringEncryption\": true, \"expirationNotificatorMapSizeLimit\": 100000, \"expirationNotificatorIntervalInSeconds\": 600, \"redirectUrisRegexEnabled\": true, \"useHighestLevelScriptIfAcrScriptNotFound\": false, \"authenticationFiltersEnabled\": false, \"clientAuthenticationFiltersEnabled\": false, \"clientRegDefaultToCodeFlowWithRefresh\": true, \"grantTypesAndResponseTypesAutofixEnabled\": false, \"authenticationFilters\": [ { \"filter\": \"(&(mail=*{0}*)(inum={1}))\", \"bind\": false, \"baseDn\": \"ou=people,o=jans\" }, { \"filter\": \"uid={0}\", \"bind\": true, \"bindPasswordAttribute\": \"pwd\", \"baseDn\": \"ou=people,o=jans\" } ], \"clientAuthenticationFilters\": [ { \"filter\": \"myCustomAttr1={0}\", \"baseDn\": \"ou=clients,o=jans\" } ], \"corsConfigurationFilters\": [ { \"filterName\": \"CorsFilter\", \"corsEnabled\": true, \"corsAllowedOrigins\": \"*\", \"corsAllowedMethods\": \"GET,POST,HEAD,OPTIONS\", \"corsAllowedHeaders\": \"Origin,Authorization,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers\", \"corsSupportCredentials\": true, \"corsLoggingEnabled\": false, \"corsPreflightMaxAge\": 1800, \"corsRequestDecorate\": true } ], \"sessionIdUnusedLifetime\": 86400, \"sessionIdUnauthenticatedUnusedLifetime\": 7200, \"sessionIdPersistOnPromptNone\": true, \"sessionIdRequestParameterEnabled\": false, \"changeSessionIdOnAuthentication\": true, \"sessionIdPersistInCache\": false, \"includeSidInResponse\": false, \"disablePromptLogin\": false, \"disablePromptConsent\": false, \"sessionIdLifetime\": 86400, \"sessionIdCookieLifetime\": 86400, \"configurationUpdateInterval\": 3600, \"enableClientGrantTypeUpdate\": true, \"grantTypesSupportedByDynamicRegistration\": [ \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"implicit\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"urn:ietf:params:oauth:grant-type:device_code\", \"client_credentials\", \"refresh_token\", \"authorization_code\", \"tx_token\" ], \"metricReporterInterval\": 300, \"metricReporterKeepDataDays\": 15, \"pairwiseIdType\": \"algorithmic\", \"pairwiseCalculationKey\": \"9jwJNNXd9mMua666QDhfEKGcR\", \"pairwiseCalculationSalt\": \"aUn2q1HDtsUXtmTNovNeN1QTk\", \"shareSubjectIdBetweenClientsWithSameSectorId\": true, \"webKeysStorage\": \"keystore\", \"dnName\": \"CN=Jans Auth CA Certificates\", \"keyStoreFile\": \"/etc/certs/jans-auth-keys.pkcs12\", \"keyStoreSecret\": \"S63ogThoRsEf\", \"keySelectionStrategy\": \"OLDER\", \"keySignWithSameKeyButDiffAlg\": false, \"introspectionAccessTokenMustHaveUmaProtectionScope\": false, \"introspectionAccessTokenMustHaveIntrospectionScope\": false, \"introspectionSkipAuthorization\": false, \"endSessionWithAccessToken\": false, \"clientWhiteList\": [ \"*\" ], \"clientBlackList\": [ \"*.attacker.com/*\" ], \"legacyIdTokenClaims\": false, \"customHeadersWithAuthorizationResponse\": true, \"frontChannelLogoutSessionSupported\": true, \"loggingLevel\": \"INFO\", \"loggingLayout\": \"text\", \"updateUserLastLogonTime\": false, \"updateClientAccessTime\": false, \"logClientIdOnClientAuthentication\": true, \"logClientNameOnClientAuthentication\": false, \"disableJdkLogger\": true, \"authorizationRequestCustomAllowedParameters\": [ { \"paramName\": \"customParam3\", \"returnInResponse\": false }, { \"paramName\": \"customParam4\", \"returnInResponse\": true }, { \"paramName\": \"customParam5\", \"returnInResponse\": true }, { \"paramName\": \"customParam1\", \"returnInResponse\": false }, { \"paramName\": \"customParam2\", \"returnInResponse\": false } ], \"openidScopeBackwardCompatibility\": false, \"disableU2fEndpoint\": false, \"rotateDeviceSecret\": false, \"returnDeviceSecretFromAuthzEndpoint\": false, \"dcrSignatureValidationEnabled\": false, \"dcrAuthorizationWithClientCredentials\": false, \"dcrAuthorizationWithMTLS\": false, \"useLocalCache\": true, \"fapiCompatibility\": false, \"forceIdTokenHintPresence\": false, \"rejectEndSessionIfIdTokenExpired\": false, \"allowEndSessionWithUnmatchedSid\": false, \"forceOfflineAccessScopeToEnableRefreshToken\": true, \"errorReasonEnabled\": false, \"removeRefreshTokensForClientOnLogout\": true, \"skipRefreshTokenDuringRefreshing\": false, \"refreshTokenExtendLifetimeOnRotation\": false, \"checkUserPresenceOnRefreshToken\": false, \"consentGatheringScriptBackwardCompatibility\": false, \"introspectionScriptBackwardCompatibility\": false, \"introspectionResponseScopesBackwardCompatibility\": false, \"softwareStatementValidationType\": \"script\", \"authenticationProtectionConfiguration\": { \"attemptExpiration\": 15, \"maximumAllowedAttemptsWithoutDelay\": 4, \"delayTime\": 2, \"bruteForceProtectionEnabled\": false }, \"errorHandlingMethod\": \"remote\", \"keepAuthenticatorAttributesOnAcrChange\": false, \"deviceAuthzRequestExpiresIn\": 1800, \"deviceAuthzTokenPollInterval\": 5, \"deviceAuthzResponseTypeToProcessAuthz\": \"code\", \"backchannelRedirectUri\": \"https://example.jans.io/jans-auth/ciba/home.htm\", \"backchannelAuthenticationEndpoint\": \"https://example.jans.io/jans-auth/restv1/bc-authorize\", \"backchannelDeviceRegistrationEndpoint\": \"https://example.jans.io/jans-auth/restv1/bc-deviceRegistration\", \"backchannelTokenDeliveryModesSupported\": [ \"poll\", \"ping\", \"push\" ], \"backchannelUserCodeParameterSupported\": false, \"backchannelBindingMessagePattern\": \"^[a-zA-Z0-9]{4,8}$\", \"backchannelAuthenticationResponseExpiresIn\": 3600, \"backchannelAuthenticationResponseInterval\": 2, \"backchannelLoginHintClaims\": [ \"inum\", \"uid\", \"mail\" ], \"cibaEndUserNotificationConfig\": {}, \"backchannelRequestsProcessorJobIntervalSec\": 5, \"backchannelRequestsProcessorJobChunkSize\": 100, \"cibaGrantLifeExtraTimeSec\": 180, \"cibaMaxExpirationTimeAllowedSec\": 1800, \"dpopSigningAlgValuesSupported\": [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"dpopTimeframe\": 5, \"dpopJtiCacheTime\": 3600, \"allowIdTokenWithoutImplicitGrantType\": false, \"discoveryCacheLifetimeInMinutes\": 60, \"discoveryDenyKeys\": [ \"id_generation_endpoint\", \"auth_level_mapping\", \"scope_to_claims_mapping\", \"op_policy_uri\" ], \"httpLoggingEnabled\": false, \"agamaConfiguration\": { \"enabled\": false, \"rootDir\": \"/opt/jans/jetty/jans-auth/agama\", \"templatesPath\": \"/ftl\", \"scriptsPath\": \"/scripts\", \"serializerType\": \"KRYO\", \"maxItemsLoggedInCollections\": 9, \"pageMismatchErrorPage\": \"mismatch.ftlh\", \"interruptionErrorPage\": \"timeout.ftlh\", \"crashErrorPage\": \"crash.ftlh\", \"finishedFlowPage\": \"finished.ftlh\", \"bridgeScriptPage\": \"agama.xhtml\", \"defaultResponseHeaders\": { \"Cache-Control\": \"max-age=0, no-store\" } }, \"ssaConfiguration\": { \"ssaEndpoint\": \"https://example.jans.io/jans-auth/restv1/ssa\", \"ssaSigningAlg\": \"RS256\", \"ssaExpirationInDays\": 30 }, \"blockWebviewAuthorizationEnabled\": false, \"dateFormatterPatterns\": { \"birthdate\": \"yyyy-MM-dd\" }, \"httpLoggingResponseBodyContent\": false, \"fapi\": false, \"allResponseTypesSupported\": [ \"code\", \"id_token\", \"token\" ] }", "title": "Get All Jans Auth Server Configuration Properties"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/#partially-modify-jans-auth-server-configuration-properties", "text": "Operation ID: patch-properties Description: Partially modifies Jans authorization server AppConfiguration properties. Schema: Array of /components/schemas/PatchRequest To get sample shema type jans cli --schema <schma>, for example jans cli --schema /components/schemas/PatchRequest Let's look at the schema first: jans cli --schema /components/schemas/PatchRequest > /tmp/patch-jans-auth.json It will create a .json file in /tmp with schema. Let's modify this schema: nano /tmp/patch-jans-auth.json This schema has three properties; op , path & value . Let's perform a replace operation at cibaEnabled to change it from false to true . So, the .json file will look like this: [ { \"op\": \"replace\", \"path\": \"cibaEnabled\", \"value\": true } ] Don't forget to use square brackets ( [] ). Otherwise, it won't work. Now, let's do the operation. jans cli --operation-id patch-properties --data /tmp/patch-jans-auth.json If you run the following command line, you must see that cibaEnabled is true :", "title": "Partially Modify Jans Auth Server Configuration Properties"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/#get-persistence-type-for-jans-auth-configuration", "text": "You can get the persistence details for jans auth server. jans cli --operation-id get-properties-persistence Default persistence type is MySQL . Please wait while retrieving data ... { \"persistenceType\": \"sql\" }", "title": "Get Persistence type for Jans Auth Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/", "tags": ["administration", "configuration", "JWK", "json web keys", "JWKS"], "text": "JSON Web Key (JWK) # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and manage the JSON Web keys using the command Line. To get the details of Janssen command line operations relevant to JSON Web Key, you can check the operations under ConfigurationJwkJsonWebKeyJwk task using the command below: Command jans cli --info ConfigurationJwkJsonWebKeyJwk Sample Output Operation ID: get-jwk-by-kid Description: Get a JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Operation ID: delete-config-jwk-kid Description: Delete a JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Operation ID: patch-config-jwk-kid Description: Patch a specific JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Schema: Array of JsonPatch Operation ID: get-config-jwks Description: Gets list of JSON Web Key (JWK) used by server Operation ID: put-config-jwks Description: Replaces JSON Web Keys Schema: WebKeysConfiguration Operation ID: patch-config-jwks Description: Patches JSON Web Keys Schema: Array of JsonPatch Operation ID: post-config-jwks-key Description: Configuration \u2013 JWK - JSON Web Key (JWK) Schema: JSONWebKey To get sample schema type jans cli --schema <schema>, for example jans cli --schema JSONWebKey Get Configurations list of JWKs # We can get list of all configurations of the jwk configuration using a command like this: Command jans cli --operation-id get-config-jwks It will return all the jwk configuration information as below: Sample Output { \"keys\" : [ { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-384\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_fed19dd0-7139-4ed8-ad43-43322b7eeaea_sig_rs384\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAKLBm5p06uGv/lXT4tKLgjsS5kosfHb1rgO50fdLAFRoMA0GCSqGSIb3DQEBDAUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkIt6G/MDIyfp1uTERxFYoY1nGuq3FhZG7xdPYi7eHoyM+PAbq+8rKeIRcJWJi37TazbqqLViGbejaD6rRxOihzoMPo1LtBuqGGw8m6fI1UJlvnt1NHd+du3Q6065WufL+nXn2Osmg962TF+gSvExgxr+HFeAgjP/kyG99dzSv4mUFbikegK8Dql1K36fZ427vDQ7mGRrR1vBsbMPqW5d9huXhl+iy11AOtYNNcfRDu47Hzae5Srzp32si36+Da/dEwntuMXnK7BwxDp/BGoOuWLPFoVctH6PDoIYzXUiTbj+XiQ8zFgPydt+x/2ZEGyq61Ewebjkpj9b0g+yHk/2aQIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQEMBQADggEBAHnfO3jItuXdSr5Js3kj/7kI1OElwcU4fco53ThSilbtq6FBOk5GzonaZOHFQayzjo3Qp5qe/uShSknFQ+sjEmhGTVPiQFssNTXxEnEw1WrTvEc/09I9oTNg9jitppn1z4/QT/wP0X3erRIjBQvFe4ov1wL/atjs5Mg8KRHqGttze5xN1pY3r0hrUiIxYiA7F5DUigGD4hYGGXKXymr0SgEoMZQx9Duxn8wxtX5l3fcC0FA53vn/4ZDd/ikhQRqTyz/C7ffHsVcOxnlWd3pm37+W9swGhkb9EaKRg2gJOdA5+Vw62tJA4Gp8WOIeMrRiXvtn2AVks5nyG7oiWt0ldYk=\" ], \"name\" : \"Connect RS384 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS384\" , \"n\" : \"kIt6G_MDIyfp1uTERxFYoY1nGuq3FhZG7xdPYi7eHoyM-PAbq-8rKeIRcJWJi37TazbqqLViGbejaD6rRxOihzoMPo1LtBuqGGw8m6fI1UJlvnt1NHd-du3Q6065WufL-nXn2Osmg962TF-gSvExgxr-HFeAgjP_kyG99dzSv4mUFbikegK8Dql1K36fZ427vDQ7mGRrR1vBsbMPqW5d9huXhl-iy11AOtYNNcfRDu47Hzae5Srzp32si36-Da_dEwntuMXnK7BwxDp_BGoOuWLPFoVctH6PDoIYzXUiTbj-XiQ8zFgPydt-x_2ZEGyq61Ewebjkpj9b0g-yHk_2aQ\" } ] Adds new JSON Web key (JWK) # To add a new key, we can use post-config-jwks-key operation id. As shown in the output for --info command, the post-config-jwks-key operation requires data to be sent according to JSONWebKey schema. To see the schema, use the command below: Command jans cli --schema JSONWebKey The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample JSONWebKey Using the schema and the example above, we have added below key data to the file /tmp/jwk.json . Input \"name\" : \"Connect RSA-OAEP Encryption Key 2\" , \"descr\" : \"Encryption Key 2: Elliptic Curve Diffie-Hellman Ephemeral Static key agreement using Concat KDF\" , \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"crv\" : \"\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ] , \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" , \"x\" : null, \"y\" : null Now let's post this key to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-config-jwks-key --data /tmp/jwk.json Replace JSON Web Key Set # To replace the current JWKS configuration, use the put-config-jwks operation. This operation replaces the current set of JWK with the provided set. Operation ID: put-config-jwks Description: Replaces JSON Web Keys Schema: WebKeysConfiguration To get the schema file: Command jans cli --schema WebKeysConfiguration As suggested in the schema, we have to provide an array of keys in a json file containing key-value pairs. The properties in the key are defined by the JWK specification RFC 7517 , and for algorithm-specific properties, in RFC 7518 . Properties # name Description kid It's a unique identifier for the key configuration. kty It's used to define the type of the specific cryptographic algorithms use This parameter identifies the intended use of the public key. sig for signature and enc for encryption alg The specific algorithm used with the key crv exp The exponent for the RSA public key. x5c The x5c parameter contains a chain of one or more PKIX certificates RFC5280 n The modulus for the RSA public key . e The \"e\" (exponent) parameter contains the exponent value for the RSA public key . It is represented as a Base64urlUInt-encoded value. x The \"x\" (x coordinate) parameter contains the x coordinate for the Elliptic Curve point . y The \"y\" (y coordinate) parameter contains the y coordinate for the Elliptic Curve point . Let's update the json file to create a new key configuration. Input Key { \"keys\" : [{ \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"crv\" : \"\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" , \"x\" : null , \"y\" : null }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ /ja nssen - server/co nf ig - guide/au t h - server - co nf ig/jso n - web - key - co nf ig \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" } ] } Now let's put the new keys into the Janssen server. Command jans cli --operation-id put-config-jwks --data /tmp/path-jwk.json Please remember that this operation replaces all JWKs in the Janssen server with new ones. So, in this case, if you want to keep old JWKs, you have to put them as well in the input file. Output Sample { \"keys\" : [ { \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"enc\" , \"key_ops_type\" : [], \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"exp\" : 1622245655163 , \"alg\" : \"RSA-OAEP\" , \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" } ] } Now use the Get Configurations list of JWKs to confirm the replacement. Get a JSON Web Key Based on kid # With get-jwk-by-kid operation-id, we can get any specific jwk matched with kid . If we know the kid , we can simply use the below command: Command jans cli --operation-id get-jwk/janssen-server/config-guide/auth-server-config/json-web-key-config-by-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 It returns the details as below: Sample Output { \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" } Patch JSON Web Key (JWK) by kid # Using patch-config-jwks operation, we can modify JSON Web Keys partially for its properties. Operation ID: patch-config-jwks Description: Patches JSON Web Keys Schema: Array of JsonPatch To use this operation, specify the id of the key that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property use from enc to sig . Input [ { \"op\" : \"replace\" , \"path\" : \"use\" , \"value\" : \"sig\" } ] Now let's do the operation with the command line. Command jans cli --operation-id patch-config-jwk-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 --data /tmp/schema.json Updated Json Web Key: Key { \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"sig\" , \"alg\" : \"RSA-OAEP\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" } We see it has replaced the value of the use property from enc to sig . Please read about patch method , You can get some idea of how this patch method works to modify particular properties of any task. Delete Json Web Key using kid # It's pretty simple to delete json web key using its kid . The command line is: Command jans cli --operation-id delete-config-jwk-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 It will delete the jwk if it matches with the given kid . Using Text-based UI # In Janssen, you can view the JSON web keys using the Text-Based UI also. You can start TUI using the command below: Command jans tui JSON Web Key (JWK) Screen # Navigate to Auth Server -> Keys to open the JSON Web Key screen as shown in the image below. After clicking on Get keys , You can view Key's list on this page. You cannot perform any operations in text-based UI. Only you can perform operations using the command line. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Json Web key. Endpoint details are published in the Swagger document .", "title": "JSON Web Key"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#json-web-key-jwk", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "JSON Web Key (JWK)"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#using-command-line", "text": "In the Janssen Server, you can deploy and manage the JSON Web keys using the command Line. To get the details of Janssen command line operations relevant to JSON Web Key, you can check the operations under ConfigurationJwkJsonWebKeyJwk task using the command below: Command jans cli --info ConfigurationJwkJsonWebKeyJwk Sample Output Operation ID: get-jwk-by-kid Description: Get a JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Operation ID: delete-config-jwk-kid Description: Delete a JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Operation ID: patch-config-jwk-kid Description: Patch a specific JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Schema: Array of JsonPatch Operation ID: get-config-jwks Description: Gets list of JSON Web Key (JWK) used by server Operation ID: put-config-jwks Description: Replaces JSON Web Keys Schema: WebKeysConfiguration Operation ID: patch-config-jwks Description: Patches JSON Web Keys Schema: Array of JsonPatch Operation ID: post-config-jwks-key Description: Configuration \u2013 JWK - JSON Web Key (JWK) Schema: JSONWebKey To get sample schema type jans cli --schema <schema>, for example jans cli --schema JSONWebKey", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#get-configurations-list-of-jwks", "text": "We can get list of all configurations of the jwk configuration using a command like this: Command jans cli --operation-id get-config-jwks It will return all the jwk configuration information as below: Sample Output { \"keys\" : [ { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-384\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_fed19dd0-7139-4ed8-ad43-43322b7eeaea_sig_rs384\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAKLBm5p06uGv/lXT4tKLgjsS5kosfHb1rgO50fdLAFRoMA0GCSqGSIb3DQEBDAUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkIt6G/MDIyfp1uTERxFYoY1nGuq3FhZG7xdPYi7eHoyM+PAbq+8rKeIRcJWJi37TazbqqLViGbejaD6rRxOihzoMPo1LtBuqGGw8m6fI1UJlvnt1NHd+du3Q6065WufL+nXn2Osmg962TF+gSvExgxr+HFeAgjP/kyG99dzSv4mUFbikegK8Dql1K36fZ427vDQ7mGRrR1vBsbMPqW5d9huXhl+iy11AOtYNNcfRDu47Hzae5Srzp32si36+Da/dEwntuMXnK7BwxDp/BGoOuWLPFoVctH6PDoIYzXUiTbj+XiQ8zFgPydt+x/2ZEGyq61Ewebjkpj9b0g+yHk/2aQIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQEMBQADggEBAHnfO3jItuXdSr5Js3kj/7kI1OElwcU4fco53ThSilbtq6FBOk5GzonaZOHFQayzjo3Qp5qe/uShSknFQ+sjEmhGTVPiQFssNTXxEnEw1WrTvEc/09I9oTNg9jitppn1z4/QT/wP0X3erRIjBQvFe4ov1wL/atjs5Mg8KRHqGttze5xN1pY3r0hrUiIxYiA7F5DUigGD4hYGGXKXymr0SgEoMZQx9Duxn8wxtX5l3fcC0FA53vn/4ZDd/ikhQRqTyz/C7ffHsVcOxnlWd3pm37+W9swGhkb9EaKRg2gJOdA5+Vw62tJA4Gp8WOIeMrRiXvtn2AVks5nyG7oiWt0ldYk=\" ], \"name\" : \"Connect RS384 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS384\" , \"n\" : \"kIt6G_MDIyfp1uTERxFYoY1nGuq3FhZG7xdPYi7eHoyM-PAbq-8rKeIRcJWJi37TazbqqLViGbejaD6rRxOihzoMPo1LtBuqGGw8m6fI1UJlvnt1NHd-du3Q6065WufL-nXn2Osmg962TF-gSvExgxr-HFeAgjP_kyG99dzSv4mUFbikegK8Dql1K36fZ427vDQ7mGRrR1vBsbMPqW5d9huXhl-iy11AOtYNNcfRDu47Hzae5Srzp32si36-Da_dEwntuMXnK7BwxDp_BGoOuWLPFoVctH6PDoIYzXUiTbj-XiQ8zFgPydt-x_2ZEGyq61Ewebjkpj9b0g-yHk_2aQ\" } ]", "title": "Get Configurations list of JWKs"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#adds-new-json-web-key-jwk", "text": "To add a new key, we can use post-config-jwks-key operation id. As shown in the output for --info command, the post-config-jwks-key operation requires data to be sent according to JSONWebKey schema. To see the schema, use the command below: Command jans cli --schema JSONWebKey The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample JSONWebKey Using the schema and the example above, we have added below key data to the file /tmp/jwk.json . Input \"name\" : \"Connect RSA-OAEP Encryption Key 2\" , \"descr\" : \"Encryption Key 2: Elliptic Curve Diffie-Hellman Ephemeral Static key agreement using Concat KDF\" , \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"crv\" : \"\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ] , \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" , \"x\" : null, \"y\" : null Now let's post this key to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-config-jwks-key --data /tmp/jwk.json", "title": "Adds new JSON Web key (JWK)"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#replace-json-web-key-set", "text": "To replace the current JWKS configuration, use the put-config-jwks operation. This operation replaces the current set of JWK with the provided set. Operation ID: put-config-jwks Description: Replaces JSON Web Keys Schema: WebKeysConfiguration To get the schema file: Command jans cli --schema WebKeysConfiguration As suggested in the schema, we have to provide an array of keys in a json file containing key-value pairs. The properties in the key are defined by the JWK specification RFC 7517 , and for algorithm-specific properties, in RFC 7518 .", "title": "Replace JSON Web Key Set"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#properties", "text": "name Description kid It's a unique identifier for the key configuration. kty It's used to define the type of the specific cryptographic algorithms use This parameter identifies the intended use of the public key. sig for signature and enc for encryption alg The specific algorithm used with the key crv exp The exponent for the RSA public key. x5c The x5c parameter contains a chain of one or more PKIX certificates RFC5280 n The modulus for the RSA public key . e The \"e\" (exponent) parameter contains the exponent value for the RSA public key . It is represented as a Base64urlUInt-encoded value. x The \"x\" (x coordinate) parameter contains the x coordinate for the Elliptic Curve point . y The \"y\" (y coordinate) parameter contains the y coordinate for the Elliptic Curve point . Let's update the json file to create a new key configuration. Input Key { \"keys\" : [{ \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"crv\" : \"\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" , \"x\" : null , \"y\" : null }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ /ja nssen - server/co nf ig - guide/au t h - server - co nf ig/jso n - web - key - co nf ig \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" } ] } Now let's put the new keys into the Janssen server. Command jans cli --operation-id put-config-jwks --data /tmp/path-jwk.json Please remember that this operation replaces all JWKs in the Janssen server with new ones. So, in this case, if you want to keep old JWKs, you have to put them as well in the input file. Output Sample { \"keys\" : [ { \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"enc\" , \"key_ops_type\" : [], \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"exp\" : 1622245655163 , \"alg\" : \"RSA-OAEP\" , \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" } ] } Now use the Get Configurations list of JWKs to confirm the replacement.", "title": "Properties"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#get-a-json-web-key-based-on-kid", "text": "With get-jwk-by-kid operation-id, we can get any specific jwk matched with kid . If we know the kid , we can simply use the below command: Command jans cli --operation-id get-jwk/janssen-server/config-guide/auth-server-config/json-web-key-config-by-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 It returns the details as below: Sample Output { \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" }", "title": "Get a JSON Web Key Based on kid"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#patch-json-web-key-jwk-by-kid", "text": "Using patch-config-jwks operation, we can modify JSON Web Keys partially for its properties. Operation ID: patch-config-jwks Description: Patches JSON Web Keys Schema: Array of JsonPatch To use this operation, specify the id of the key that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property use from enc to sig . Input [ { \"op\" : \"replace\" , \"path\" : \"use\" , \"value\" : \"sig\" } ] Now let's do the operation with the command line. Command jans cli --operation-id patch-config-jwk-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 --data /tmp/schema.json Updated Json Web Key: Key { \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"sig\" , \"alg\" : \"RSA-OAEP\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" } We see it has replaced the value of the use property from enc to sig . Please read about patch method , You can get some idea of how this patch method works to modify particular properties of any task.", "title": "Patch JSON Web Key (JWK) by kid"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#delete-json-web-key-using-kid", "text": "It's pretty simple to delete json web key using its kid . The command line is: Command jans cli --operation-id delete-config-jwk-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 It will delete the jwk if it matches with the given kid .", "title": "Delete Json Web Key using kid"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#using-text-based-ui", "text": "In Janssen, you can view the JSON web keys using the Text-Based UI also. You can start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#json-web-key-jwk-screen", "text": "Navigate to Auth Server -> Keys to open the JSON Web Key screen as shown in the image below. After clicking on Get keys , You can view Key's list on this page. You cannot perform any operations in text-based UI. Only you can perform operations using the command line.", "title": "JSON Web Key (JWK) Screen"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Json Web key. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/", "tags": ["administration", "configuration", "logging"], "text": "Log Management # Logging for Janssen Server modules is managed at the individual module level. Meaning there is no single switch or configuration that will enable or disable logs for all modules. Each module can be individually configured and can be configured differently when it comes to logging. Log Configuration For jans-auth # Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using-text-based-ui Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and customize the Logging Configuration using the command line. To get the details of Janssen command line operations relevant to Logging configuration, you can check the operations under ConfigurationLogging task using the command below: Command jans cli --info ConfigurationLogging Sample Output Operation ID: get-config-logging Description: Returns Jans Authorization Server logging settings Operation ID: put-config-logging Description: Updates Jans Authorization Server logging settings Schema: Logging To get sample schema type jans cli --schema <schema>, for example jans cli --schema Logging Find Logging Configuration # Command jans cli --operation-id get-config-logging Sample Output 1 2 3 4 5 6 7 8 9 10 11 { \"loggingLevel\" : \"DEBUG\" , \"loggingLayout\" : \"string\" , \"httpLoggingEnabled\" : true , \"disableJdkLogger\" : true , \"enabledOAuthAuditLogging\" : true , \"externalLoggerConfiguration\" : \"string\" , \"httpLoggingExcludePaths\" : [ \"string\" ] } Update Logging Configuration # To update the configuration follow the steps below. Get the current logging configuration and store it in a file for editing. The following command will retrieve the current logging configuration and store it in a file. Command jans cli -no-color --operation-id get-config-logging > /tmp/log-config.json Update the configuration with desired value in the file while keeping other properties and values unchanged. Updates must adhere to the Logging schema as mentioned here . The schema details can be retrieved using the command below. The schema defines what values and datatypes are acceptable for each property value. Command jans cli --schema Logging Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-config-logging --data /tmp/log-config.json Upon successful execution of the update, the Janssen Server responds with updated configuration. Using-text-based-ui # Start TUI using the command below: Command jans tui Logging Configuration for Auth Server # Navigate to Auth Server -> Logging to open the Logging screen as shown in the image below to change the logging properties configuration. Logging Configuration for FIDO # Navigate to FIDO to open the Logging screen as shown in the image below to change the logging properties configuration. Logging Configuration for SCIM # Navigate to SCIM to open the Logging screen as shown in the image below to change the logging properties configuration. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring logging. Endpoint details are published in the Swagger document . Default Log Location # On a VM installation, logs for jans-auth module are generated at /opt/jans/jetty/jans-auth/logs/ . Similarly, logs for FIDO2 and SCIM modules are generated under /opt/jans/jetty/jans-fido2/logs/ and /opt/jans/jetty/jans-scim/logs/ respectively. Cloud-Native Deployments # Logging configuration for a cloud-native deployment is detailed here", "title": "Logging"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#log-management", "text": "Logging for Janssen Server modules is managed at the individual module level. Meaning there is no single switch or configuration that will enable or disable logs for all modules. Each module can be individually configured and can be configured differently when it comes to logging.", "title": "Log Management"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#log-configuration-for-jans-auth", "text": "Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using-text-based-ui Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Log Configuration For jans-auth"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the Logging Configuration using the command line. To get the details of Janssen command line operations relevant to Logging configuration, you can check the operations under ConfigurationLogging task using the command below: Command jans cli --info ConfigurationLogging Sample Output Operation ID: get-config-logging Description: Returns Jans Authorization Server logging settings Operation ID: put-config-logging Description: Updates Jans Authorization Server logging settings Schema: Logging To get sample schema type jans cli --schema <schema>, for example jans cli --schema Logging", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#find-logging-configuration", "text": "Command jans cli --operation-id get-config-logging Sample Output 1 2 3 4 5 6 7 8 9 10 11 { \"loggingLevel\" : \"DEBUG\" , \"loggingLayout\" : \"string\" , \"httpLoggingEnabled\" : true , \"disableJdkLogger\" : true , \"enabledOAuthAuditLogging\" : true , \"externalLoggerConfiguration\" : \"string\" , \"httpLoggingExcludePaths\" : [ \"string\" ] }", "title": "Find Logging Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#update-logging-configuration", "text": "To update the configuration follow the steps below. Get the current logging configuration and store it in a file for editing. The following command will retrieve the current logging configuration and store it in a file. Command jans cli -no-color --operation-id get-config-logging > /tmp/log-config.json Update the configuration with desired value in the file while keeping other properties and values unchanged. Updates must adhere to the Logging schema as mentioned here . The schema details can be retrieved using the command below. The schema defines what values and datatypes are acceptable for each property value. Command jans cli --schema Logging Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-config-logging --data /tmp/log-config.json Upon successful execution of the update, the Janssen Server responds with updated configuration.", "title": "Update Logging Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#using-text-based-ui", "text": "Start TUI using the command below: Command jans tui", "title": "Using-text-based-ui"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#logging-configuration-for-auth-server", "text": "Navigate to Auth Server -> Logging to open the Logging screen as shown in the image below to change the logging properties configuration.", "title": "Logging Configuration for Auth Server"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#logging-configuration-for-fido", "text": "Navigate to FIDO to open the Logging screen as shown in the image below to change the logging properties configuration.", "title": "Logging Configuration for FIDO"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#logging-configuration-for-scim", "text": "Navigate to SCIM to open the Logging screen as shown in the image below to change the logging properties configuration.", "title": "Logging Configuration for SCIM"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring logging. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#default-log-location", "text": "On a VM installation, logs for jans-auth module are generated at /opt/jans/jetty/jans-auth/logs/ . Similarly, logs for FIDO2 and SCIM modules are generated under /opt/jans/jetty/jans-fido2/logs/ and /opt/jans/jetty/jans-scim/logs/ respectively.", "title": "Default Log Location"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#cloud-native-deployments", "text": "Logging configuration for a cloud-native deployment is detailed here", "title": "Cloud-Native Deployments"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/", "tags": ["administration", "configuration", "scopes"], "text": "OAuth Scopes # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the configuration steps Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and customize the OAuth scopes using the command line. To get the details of Janssen command line operations relevant to OAuth Scope, you can check the operations under the OauthScopes task using the command below. Command jans cli --info OauthScopes Sample Output Operation ID: get-oauth-scopes Description: Gets list of Scopes Parameters: type: Scope type [string] limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] withAssociatedClients: Boolean fag to indicate if clients associated with the scope are to be returned [boolean] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-scopes Description: Update Scope Schema: Scope Operation ID: post-oauth-scopes Description: Create Scope Schema: Scope Operation ID: get-oauth-scopes-by-inum Description: Get Scope by Inum Parameters: inum: Scope identifier [string] withAssociatedClients: No description is provided for this parameter [boolean] Operation ID: delete-oauth-scopes-by-inum Description: Delete Scope Parameters: inum: Scope identifier [string] Operation ID: patch-oauth-scopes-by-id Description: Patch Scope Parameters: inum: Scope identifier [string] Schema: Array of JsonPatch Operation ID: get-scope-by-creator Description: Get Scope by creatorId Parameters: creatorId: Id of the scope creator. If creator is client then client_id if user then user_id [string] Operation ID: get-scope-by-type Description: Get Scope by type Parameters: type: Type of the scope [string] To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch Find/View OAuth Scopes # Use the operation ID get-oauth-scopes to find and view the current scopes. Let's retrieve 3 scopes that contain view in the description and openid as the Type. Command jans cli --operation-id get-oauth-scopes \\ --endpoint-args limit:3,pattern:view,type:openid Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 { \"start\": 0, \"totalEntriesCount\": 7, \"entriesCount\": 3, \"entries\": [ { \"dn\": \"inum=10B2,ou=scopes,o=jans\", \"inum\": \"10B2\", \"displayName\": \"view_username\", \"id\": \"user_name\", \"description\": \"View your local username in the Janssen Server.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=42E0,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=10B2,ou=scopes,o=jans\" }, { \"dn\": \"inum=341A,ou=scopes,o=jans\", \"inum\": \"341A\", \"displayName\": \"view_client\", \"id\": \"clientinfo\", \"description\": \"View the client info.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=2B29,ou=attributes,o=jans\", \"inum=29DA,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=341A,ou=scopes,o=jans\" }, { \"dn\": \"inum=43F1,ou=scopes,o=jans\", \"inum\": \"43F1\", \"displayName\": \"view_profile\", \"id\": \"profile\", \"description\": \"View your basic profile info.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=2B29,ou=attributes,o=jans\", \"inum=0C85,ou=attributes,o=jans\", \"inum=B4B0,ou=attributes,o=jans\", \"inum=A0E8,ou=attributes,o=jans\", \"inum=5EC6,ou=attributes,o=jans\", \"inum=B52A,ou=attributes,o=jans\", \"inum=64A0,ou=attributes,o=jans\", \"inum=EC3A,ou=attributes,o=jans\", \"inum=3B47,ou=attributes,o=jans\", \"inum=3692,ou=attributes,o=jans\", \"inum=98FC,ou=attributes,o=jans\", \"inum=A901,ou=attributes,o=jans\", \"inum=36D9,ou=attributes,o=jans\", \"inum=BE64,ou=attributes,o=jans\", \"inum=6493,ou=attributes,o=jans\", \"inum=4CF1,ou=attributes,o=jans\", \"inum=29DA,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=43F1,ou=scopes,o=jans\" } ] } Create an OAuth Scope # To create a new scope, we can use post-oauth-scopes operation id. As shown in the output for --info command, the post-oauth-scopes operation requires data to be sent according to Scope schema. To see the schema, use the command below: Command jans cli --schema Scope For better understanding, the Janssen Server also provides an sample of data to be sent to the server. This sample conforms to the schema above. Use the command below to get the sample. Command jans cli --schema-sample Scope Using the schema and the example above, we have added below key data to the file /tmp/scope.json Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { \"dn\" : null , \"id\" : \"TestScopeID\" , \"inum\" : null , \"displayName\" : \"TestScope\" , \"description\" : \"Test Scope created by jans-cli\" , \"iconUrl\" : null , \"authorizationPolicies\" : [], \"defaultScope\" : true , \"scopeType\" : \"openid\" , \"claims\" : [], \"umaType\" : false , \"umaAuthorizationPolicies\" : [], \"attributes\" : { \"spontaneousClientId\" : null , \"spontaneousClientScopes\" : [], \"showInConfigurationEndpoint\" : true } } Now let's post this scope to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-scopes \\ --data /tmp/scope.json Update Existing OAuth Scopes # To update the configuration follow the steps below. Get the existing OAuth Scope and store it into a file for editing. The following command will retrieve the existing OAuth Scope in the schema file. Sample Command jans cli -no-color --operation-id get-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 > /tmp/scopdata.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Scope schema as mentioned here . We have changed only the scopeType to dynamic in existing OAuth Scope. Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-scopes --data /tmp/scope.json This will updated the existing oauth scopes matched with inum value. Patch OAuth Scopes by inum # Let's update iconUrl with patch method. So we need a schema for the patch method. Remember when we queried info for the task OAuthScopes it printed: Operation ID: patch-oauth-scopes-by-id Description: Patch Scope Parameters: inum: Scope identifier [string] Schema: Array of JsonPatch The patch-oauth-scopes-by-id operation uses the JSON Patch schema to describe the configuration change. Refer here to know more about schema. Command jans cli --schema JsonPatch > /tmp/patch.json For instance, to perform a replace operation at iconUrl and change it from null to https://www.jans.io/icon.png , the JSON Patch data would look like below: Input [ { \"op\" : \"replace\" , \"path\" : \"iconUrl\" , \"value\" : \"https://www.jans.io/icon.png\" } ] Store the above JSON Patch data in a file, for instance, /tmp/patch.json Let's do the operation: Command jans cli --operation-id patch-oauth-scopes-by-id \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 --data /tmp/patch.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"dn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" , \"inum\" : \"8eb2b0c0-d1d9-453d-8364-e2809ce857f2\" , \"displayName\" : \"TestScope\" , \"id\" : \"TestScopeID\" , \"iconUrl\" : \"https://www.jans.io/icon.png\" , \"description\" : \"Test Scope created by jans-cli\" , \"scopeType\" : \"dynamic\" , \"defaultScope\" : true , \"attributes\" : { \"showInConfigurationEndpoint\" : true }, \"creationDate\" : \"2024-06-25T08:44:08\" , \"umaType\" : false , \"baseDn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" } Find OAuth Scopes by inum # In case We know the inum value of an OAuth Scope, We can get the details of that scope. Operation ID: get-oauth-scopes-by-inum Description: Get Scope by Inum Parameters: inum: Scope identifier [string] withAssociatedClients: No description is provided for this parameter [boolean] We can use the url-suffix for the inum value. Sample Command jans cli --operation-id get-oauth-scopes-by-inum --url-suffix inum:value For example: Command jans cli --operation-id get-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 It returns the details of the scope matched with the inum value. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"dn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" , \"inum\" : \"8eb2b0c0-d1d9-453d-8364-e2809ce857f2\" , \"displayName\" : \"TestScope\" , \"id\" : \"TestScopeID\" , \"iconUrl\" : \"https://www.jans.io/icon.png\" , \"description\" : \"Test Scope created by jans-cli\" , \"scopeType\" : \"dynamic\" , \"defaultScope\" : true , \"attributes\" : { \"showInConfigurationEndpoint\" : true }, \"creationDate\" : \"2024-06-25T08:44:08\" , \"umaType\" : false , \"baseDn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" } Delete OAuth Scopes by inum # You can delete any OAuth Scopes by its inum value. Command jans cli --operation-id delete-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 Just change the inum value to your own according to which one you want to delete. Using Text-based UI # You can start TUI using the command below: Command jans tui Scope Screen # Navigate to Auth Server -> Scopes to open the scope screen as shown in the image below. To get the list of currently added Scope, bring the control to Search box (using the tab key), and press Enter. Type the search string to search for Scope with matching id and inum . Add Scope screen # Use the Add Scope button to create a new scope. You can create several types of scopes in the screen below, such as oauth , OpenID , dynamic , and uma , with the correct data. For example, below is the picture availability scope data. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OAuth Scope. Endpoint details are published in the Swagger document .", "title": "OAuth Scope Management"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#oauth-scopes", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the configuration steps Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "OAuth Scopes"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the OAuth scopes using the command line. To get the details of Janssen command line operations relevant to OAuth Scope, you can check the operations under the OauthScopes task using the command below. Command jans cli --info OauthScopes Sample Output Operation ID: get-oauth-scopes Description: Gets list of Scopes Parameters: type: Scope type [string] limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] withAssociatedClients: Boolean fag to indicate if clients associated with the scope are to be returned [boolean] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-scopes Description: Update Scope Schema: Scope Operation ID: post-oauth-scopes Description: Create Scope Schema: Scope Operation ID: get-oauth-scopes-by-inum Description: Get Scope by Inum Parameters: inum: Scope identifier [string] withAssociatedClients: No description is provided for this parameter [boolean] Operation ID: delete-oauth-scopes-by-inum Description: Delete Scope Parameters: inum: Scope identifier [string] Operation ID: patch-oauth-scopes-by-id Description: Patch Scope Parameters: inum: Scope identifier [string] Schema: Array of JsonPatch Operation ID: get-scope-by-creator Description: Get Scope by creatorId Parameters: creatorId: Id of the scope creator. If creator is client then client_id if user then user_id [string] Operation ID: get-scope-by-type Description: Get Scope by type Parameters: type: Type of the scope [string] To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#findview-oauth-scopes", "text": "Use the operation ID get-oauth-scopes to find and view the current scopes. Let's retrieve 3 scopes that contain view in the description and openid as the Type. Command jans cli --operation-id get-oauth-scopes \\ --endpoint-args limit:3,pattern:view,type:openid Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 { \"start\": 0, \"totalEntriesCount\": 7, \"entriesCount\": 3, \"entries\": [ { \"dn\": \"inum=10B2,ou=scopes,o=jans\", \"inum\": \"10B2\", \"displayName\": \"view_username\", \"id\": \"user_name\", \"description\": \"View your local username in the Janssen Server.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=42E0,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=10B2,ou=scopes,o=jans\" }, { \"dn\": \"inum=341A,ou=scopes,o=jans\", \"inum\": \"341A\", \"displayName\": \"view_client\", \"id\": \"clientinfo\", \"description\": \"View the client info.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=2B29,ou=attributes,o=jans\", \"inum=29DA,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=341A,ou=scopes,o=jans\" }, { \"dn\": \"inum=43F1,ou=scopes,o=jans\", \"inum\": \"43F1\", \"displayName\": \"view_profile\", \"id\": \"profile\", \"description\": \"View your basic profile info.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=2B29,ou=attributes,o=jans\", \"inum=0C85,ou=attributes,o=jans\", \"inum=B4B0,ou=attributes,o=jans\", \"inum=A0E8,ou=attributes,o=jans\", \"inum=5EC6,ou=attributes,o=jans\", \"inum=B52A,ou=attributes,o=jans\", \"inum=64A0,ou=attributes,o=jans\", \"inum=EC3A,ou=attributes,o=jans\", \"inum=3B47,ou=attributes,o=jans\", \"inum=3692,ou=attributes,o=jans\", \"inum=98FC,ou=attributes,o=jans\", \"inum=A901,ou=attributes,o=jans\", \"inum=36D9,ou=attributes,o=jans\", \"inum=BE64,ou=attributes,o=jans\", \"inum=6493,ou=attributes,o=jans\", \"inum=4CF1,ou=attributes,o=jans\", \"inum=29DA,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=43F1,ou=scopes,o=jans\" } ] }", "title": "Find/View OAuth Scopes"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#create-an-oauth-scope", "text": "To create a new scope, we can use post-oauth-scopes operation id. As shown in the output for --info command, the post-oauth-scopes operation requires data to be sent according to Scope schema. To see the schema, use the command below: Command jans cli --schema Scope For better understanding, the Janssen Server also provides an sample of data to be sent to the server. This sample conforms to the schema above. Use the command below to get the sample. Command jans cli --schema-sample Scope Using the schema and the example above, we have added below key data to the file /tmp/scope.json Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { \"dn\" : null , \"id\" : \"TestScopeID\" , \"inum\" : null , \"displayName\" : \"TestScope\" , \"description\" : \"Test Scope created by jans-cli\" , \"iconUrl\" : null , \"authorizationPolicies\" : [], \"defaultScope\" : true , \"scopeType\" : \"openid\" , \"claims\" : [], \"umaType\" : false , \"umaAuthorizationPolicies\" : [], \"attributes\" : { \"spontaneousClientId\" : null , \"spontaneousClientScopes\" : [], \"showInConfigurationEndpoint\" : true } } Now let's post this scope to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-scopes \\ --data /tmp/scope.json", "title": "Create an OAuth Scope"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#update-existing-oauth-scopes", "text": "To update the configuration follow the steps below. Get the existing OAuth Scope and store it into a file for editing. The following command will retrieve the existing OAuth Scope in the schema file. Sample Command jans cli -no-color --operation-id get-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 > /tmp/scopdata.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Scope schema as mentioned here . We have changed only the scopeType to dynamic in existing OAuth Scope. Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-scopes --data /tmp/scope.json This will updated the existing oauth scopes matched with inum value.", "title": "Update Existing OAuth Scopes"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#patch-oauth-scopes-by-inum", "text": "Let's update iconUrl with patch method. So we need a schema for the patch method. Remember when we queried info for the task OAuthScopes it printed: Operation ID: patch-oauth-scopes-by-id Description: Patch Scope Parameters: inum: Scope identifier [string] Schema: Array of JsonPatch The patch-oauth-scopes-by-id operation uses the JSON Patch schema to describe the configuration change. Refer here to know more about schema. Command jans cli --schema JsonPatch > /tmp/patch.json For instance, to perform a replace operation at iconUrl and change it from null to https://www.jans.io/icon.png , the JSON Patch data would look like below: Input [ { \"op\" : \"replace\" , \"path\" : \"iconUrl\" , \"value\" : \"https://www.jans.io/icon.png\" } ] Store the above JSON Patch data in a file, for instance, /tmp/patch.json Let's do the operation: Command jans cli --operation-id patch-oauth-scopes-by-id \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 --data /tmp/patch.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"dn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" , \"inum\" : \"8eb2b0c0-d1d9-453d-8364-e2809ce857f2\" , \"displayName\" : \"TestScope\" , \"id\" : \"TestScopeID\" , \"iconUrl\" : \"https://www.jans.io/icon.png\" , \"description\" : \"Test Scope created by jans-cli\" , \"scopeType\" : \"dynamic\" , \"defaultScope\" : true , \"attributes\" : { \"showInConfigurationEndpoint\" : true }, \"creationDate\" : \"2024-06-25T08:44:08\" , \"umaType\" : false , \"baseDn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" }", "title": "Patch OAuth Scopes by inum"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#find-oauth-scopes-by-inum", "text": "In case We know the inum value of an OAuth Scope, We can get the details of that scope. Operation ID: get-oauth-scopes-by-inum Description: Get Scope by Inum Parameters: inum: Scope identifier [string] withAssociatedClients: No description is provided for this parameter [boolean] We can use the url-suffix for the inum value. Sample Command jans cli --operation-id get-oauth-scopes-by-inum --url-suffix inum:value For example: Command jans cli --operation-id get-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 It returns the details of the scope matched with the inum value. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"dn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" , \"inum\" : \"8eb2b0c0-d1d9-453d-8364-e2809ce857f2\" , \"displayName\" : \"TestScope\" , \"id\" : \"TestScopeID\" , \"iconUrl\" : \"https://www.jans.io/icon.png\" , \"description\" : \"Test Scope created by jans-cli\" , \"scopeType\" : \"dynamic\" , \"defaultScope\" : true , \"attributes\" : { \"showInConfigurationEndpoint\" : true }, \"creationDate\" : \"2024-06-25T08:44:08\" , \"umaType\" : false , \"baseDn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" }", "title": "Find OAuth Scopes by inum"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#delete-oauth-scopes-by-inum", "text": "You can delete any OAuth Scopes by its inum value. Command jans cli --operation-id delete-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 Just change the inum value to your own according to which one you want to delete.", "title": "Delete OAuth Scopes by inum"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#using-text-based-ui", "text": "You can start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#scope-screen", "text": "Navigate to Auth Server -> Scopes to open the scope screen as shown in the image below. To get the list of currently added Scope, bring the control to Search box (using the tab key), and press Enter. Type the search string to search for Scope with matching id and inum .", "title": "Scope Screen"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#add-scope-screen", "text": "Use the Add Scope button to create a new scope. You can create several types of scopes in the screen below, such as oauth , OpenID , dynamic , and uma , with the correct data. For example, below is the picture availability scope data.", "title": "Add Scope screen"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OAuth Scope. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/", "tags": ["administration", "configuration", "uma"], "text": "UMA Resources # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line UMA Resource is not possible in Text-based UI. The UMA Resource does not have a REST API. Using Command Line # In the Janssen Server, you can deploy and customize the UMA Resources using the command line. To get the details of Janssen command line operations relevant to UMA Resource, you can check the operations under the OauthUmaResources task using the command below. Command jans cli --info OauthUmaResources Sample Output Operation ID: get-oauth-uma-resources Description: Gets list of UMA resources Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-uma-resources Description: Updates an UMA resource Schema: UmaResource Operation ID: post-oauth-uma-resources Description: Creates an UMA resource Schema: UmaResource Operation ID: get-oauth-uma-resources-by-id Description: Gets an UMA resource by ID Parameters: id: Resource description ID [string] Operation ID: delete-oauth-uma-resources-by-id Description: Deletes an UMA resource Parameters: id: Resource description ID [string] Operation ID: patch-oauth-uma-resources-by-id Description: Patch UMA resource Parameters: id: Resource description ID [string] Schema: Array of JsonPatch Operation ID: get-oauth-uma-resources-by-clientid Description: Fetch uma resources by client id Parameters: clientId: Client ID [string] To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch Get List of UMA Resources # To find the existing UMA Resources, let's run the following command: get-oauth-uma-resources operation is used to search UMA Resources. To get a list of UMA resources: Command jans cli --operation-id get-oauth-uma-resources Sample Output { \"start\" : 0 , \"totalEntriesCount\" : 2 , \"entriesCount\" : 2 , \"entries\" : [ { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true }, { \"dn\" : \"jansId=c0204b2a-4047-4c2b-86a8-a088e2ee54de,ou=resources,ou=uma,o=jans\" , \"id\" : \"c0204b2a-4047-4c2b-86a8-a088e2ee54de\" , \"name\" : \"Jans Cofig Api Uma Resource\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"deletable\" : true } ] } To search using multiple arguments, you can change pattern that you want to find: jans cli --operation-id get-oauth-uma-resources \\ --endpoint-args limit:1,pattern: \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true } ] } Get Oauth UMA Resource by ID # With get-oauth-uma-resources-by-id operation-id, we can get any specific uma Resource matched with ID . If we know the ID , we can simply use the below command: Command jans cli --operation-id get-oauth-uma-resources-by-id \\ --url-suffix id:361e1db0-19b4-4d83-9cb8-616dda8292b7 Sample Output { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true } Patch OAuth UMA Resource by ID # Using patch-oauth-uma-resources-by-id operation, we can modify UMA Resource partially for its properties. Operation ID: patch-oauth-uma-resources-by-id Description: Patch UMA resource Parameters: id: Resource description ID [string] Schema: Array of JsonPatch To use this operation, specify the id of the Uma that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property name from uma resource to UMA . Input [ { \"op\" : \"replace\" , \"path\" : \"name\" , \"value\" : \"UMA\" } ] Now let's do the operation with the command line. Command jans cli --operation-id patch-oauth-uma-resources-by-id \\ --url-suffix id:c0204b2a-4047-4c2b-86a8-a088e2ee54de --data /tmp/patch-uma.json Sample Output { \"dn\" : \"jansId=c0204b2a-4047-4c2b-86a8-a088e2ee54de,ou=resources,ou=uma,o=jans\" , \"id\" : \"c0204b2a-4047-4c2b-86a8-a088e2ee54de\" , \"name\" : \"UMA\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"deletable\" : true } We see it has replaced the value of the name property from Jans Cofig Api Uma Resource to UMA . Please read about patch method , You can get some idea of how this patch method works to modify particular properties of any task. Adds new Uma Resource # To add a new Uma Resource, we can use post-oauth-uma-resources operation id. As shown in the output for --info command, the post-oauth-uma-resources operation requires data to be sent according to UmaResource schema. To see the schema, use the command below: Command jans cli --schema UmaResource The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample UmaResource Using the schema and the example above, we have added below data to the file /tmp/uma.json . Input { \"name\" : \"Jans Cofig Api Uma\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : null , \"scopeExpression\" : null , \"clients\" : [ \"inum=b294adfd-b825-4e7f-9815-55d744002315,ou=clients,o=jans\" ], \"resources\" : [ \"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\" ], \"rev\" : \"1\" , \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"type\" : null , \"creationDate\" : null , \"expirationDate\" : null , \"deletable\" : true } Now let's post this uma to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-uma-resources --data /tmp/uma.json Updates an UMA resource # To update the uma resource follow the steps below. Get Oauth UMA Resource by ID and store it into a file for editing. The following command will retrieve the existing Uma resource in the schema file. Sample Command jans cli -no-color --operation-id get-oauth-uma-resources-by-id \\ --url-suffix id:c70c3b5c-d543-4dec-923c-4035bdce52bb > /tmp/update-uma.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the UmaResource schema as mentioned here . We have changed only the true to false for deletable in existing uma resource. Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-uma-resources --data /tmp/update-uma.json This will updated the existing uma resource matched with id. Get Oauth UMA Resource by Client id # With get-oauth-uma-resources-by-clientid operation-id, we can get any specific uma Resource matched with clientid . If we know the clientid , we can simply use the below command: Command jans cli --operation-id get-oauth-uma-resources-by-clientid \\ --url-suffix client id:361e1db0-19b4-4d83-9cb8-616dda8292b7 Sample Output { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true } Delete Uma Resource by id # You can delete any Uma Resource by its id value. Command jans cli --operation-id delete-oauth-uma-resources-by-id \\ --url-suffix id:c0204b2a-4047-4c2b-86a8-a088e2ee54de Just change the id to your own according to which one you want to delete.", "title": "UMA Management"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#uma-resources", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line UMA Resource is not possible in Text-based UI. The UMA Resource does not have a REST API.", "title": "UMA Resources"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the UMA Resources using the command line. To get the details of Janssen command line operations relevant to UMA Resource, you can check the operations under the OauthUmaResources task using the command below. Command jans cli --info OauthUmaResources Sample Output Operation ID: get-oauth-uma-resources Description: Gets list of UMA resources Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-uma-resources Description: Updates an UMA resource Schema: UmaResource Operation ID: post-oauth-uma-resources Description: Creates an UMA resource Schema: UmaResource Operation ID: get-oauth-uma-resources-by-id Description: Gets an UMA resource by ID Parameters: id: Resource description ID [string] Operation ID: delete-oauth-uma-resources-by-id Description: Deletes an UMA resource Parameters: id: Resource description ID [string] Operation ID: patch-oauth-uma-resources-by-id Description: Patch UMA resource Parameters: id: Resource description ID [string] Schema: Array of JsonPatch Operation ID: get-oauth-uma-resources-by-clientid Description: Fetch uma resources by client id Parameters: clientId: Client ID [string] To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#get-list-of-uma-resources", "text": "To find the existing UMA Resources, let's run the following command: get-oauth-uma-resources operation is used to search UMA Resources. To get a list of UMA resources: Command jans cli --operation-id get-oauth-uma-resources Sample Output { \"start\" : 0 , \"totalEntriesCount\" : 2 , \"entriesCount\" : 2 , \"entries\" : [ { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true }, { \"dn\" : \"jansId=c0204b2a-4047-4c2b-86a8-a088e2ee54de,ou=resources,ou=uma,o=jans\" , \"id\" : \"c0204b2a-4047-4c2b-86a8-a088e2ee54de\" , \"name\" : \"Jans Cofig Api Uma Resource\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"deletable\" : true } ] } To search using multiple arguments, you can change pattern that you want to find: jans cli --operation-id get-oauth-uma-resources \\ --endpoint-args limit:1,pattern: \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true } ] }", "title": "Get List of UMA Resources"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#get-oauth-uma-resource-by-id", "text": "With get-oauth-uma-resources-by-id operation-id, we can get any specific uma Resource matched with ID . If we know the ID , we can simply use the below command: Command jans cli --operation-id get-oauth-uma-resources-by-id \\ --url-suffix id:361e1db0-19b4-4d83-9cb8-616dda8292b7 Sample Output { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true }", "title": "Get Oauth UMA Resource by ID"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#patch-oauth-uma-resource-by-id", "text": "Using patch-oauth-uma-resources-by-id operation, we can modify UMA Resource partially for its properties. Operation ID: patch-oauth-uma-resources-by-id Description: Patch UMA resource Parameters: id: Resource description ID [string] Schema: Array of JsonPatch To use this operation, specify the id of the Uma that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property name from uma resource to UMA . Input [ { \"op\" : \"replace\" , \"path\" : \"name\" , \"value\" : \"UMA\" } ] Now let's do the operation with the command line. Command jans cli --operation-id patch-oauth-uma-resources-by-id \\ --url-suffix id:c0204b2a-4047-4c2b-86a8-a088e2ee54de --data /tmp/patch-uma.json Sample Output { \"dn\" : \"jansId=c0204b2a-4047-4c2b-86a8-a088e2ee54de,ou=resources,ou=uma,o=jans\" , \"id\" : \"c0204b2a-4047-4c2b-86a8-a088e2ee54de\" , \"name\" : \"UMA\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"deletable\" : true } We see it has replaced the value of the name property from Jans Cofig Api Uma Resource to UMA . Please read about patch method , You can get some idea of how this patch method works to modify particular properties of any task.", "title": "Patch OAuth UMA Resource by ID"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#adds-new-uma-resource", "text": "To add a new Uma Resource, we can use post-oauth-uma-resources operation id. As shown in the output for --info command, the post-oauth-uma-resources operation requires data to be sent according to UmaResource schema. To see the schema, use the command below: Command jans cli --schema UmaResource The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample UmaResource Using the schema and the example above, we have added below data to the file /tmp/uma.json . Input { \"name\" : \"Jans Cofig Api Uma\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : null , \"scopeExpression\" : null , \"clients\" : [ \"inum=b294adfd-b825-4e7f-9815-55d744002315,ou=clients,o=jans\" ], \"resources\" : [ \"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\" ], \"rev\" : \"1\" , \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"type\" : null , \"creationDate\" : null , \"expirationDate\" : null , \"deletable\" : true } Now let's post this uma to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-uma-resources --data /tmp/uma.json", "title": "Adds new Uma Resource"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#updates-an-uma-resource", "text": "To update the uma resource follow the steps below. Get Oauth UMA Resource by ID and store it into a file for editing. The following command will retrieve the existing Uma resource in the schema file. Sample Command jans cli -no-color --operation-id get-oauth-uma-resources-by-id \\ --url-suffix id:c70c3b5c-d543-4dec-923c-4035bdce52bb > /tmp/update-uma.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the UmaResource schema as mentioned here . We have changed only the true to false for deletable in existing uma resource. Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-uma-resources --data /tmp/update-uma.json This will updated the existing uma resource matched with id.", "title": "Updates an UMA resource"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#get-oauth-uma-resource-by-client-id", "text": "With get-oauth-uma-resources-by-clientid operation-id, we can get any specific uma Resource matched with clientid . If we know the clientid , we can simply use the below command: Command jans cli --operation-id get-oauth-uma-resources-by-clientid \\ --url-suffix client id:361e1db0-19b4-4d83-9cb8-616dda8292b7 Sample Output { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true }", "title": "Get Oauth UMA Resource by Client id"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#delete-uma-resource-by-id", "text": "You can delete any Uma Resource by its id value. Command jans cli --operation-id delete-oauth-uma-resources-by-id \\ --url-suffix id:c0204b2a-4047-4c2b-86a8-a088e2ee54de Just change the id to your own according to which one you want to delete.", "title": "Delete Uma Resource by id"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/", "tags": ["administration", "configuration", "openid-connect"], "text": "OpenID Connect Configuration # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and manage the OpenID Connect Client using the command Line. To get the details of Janssen command line operations relevant to OpenID Connect Client, you can check the operations under OauthOpenidConnectClients task using the command below: Let's get the information about OpenID Connect Client Configuration: Command jans cli --info OauthOpenidConnectClients Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Operation ID: get-oauth-openid-clients Description: Gets list of OpenID Connect clients Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-openid-client Description: Update OpenId Connect client Schema: Client Operation ID: post-oauth-openid-client Description: Create new OpenId Connect client Schema: Client Operation ID: get-oauth-openid-clients-by-inum Description: Get OpenId Connect Client by Inum Parameters: inum: Client identifier [string] Operation ID: delete-oauth-openid-client-by-inum Description: Delete OpenId Connect client Parameters: inum: Client identifier [string] Operation ID: patch-oauth-openid-client-by-inum Description: Patch OpenId Connect client Parameters: inum: Client identifier [string] Schema: Array of JsonPatch To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch Get List of OpenID Connect Clients # To get the list of OpenID Connect clients, run the following command: Command jans cli --operation-id get-oauth-openid-clients Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 { { \"start\" : 0 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 3 , \"entries\" : [ { \"dn\" : \"inum=1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"qAnnHv5Yxw6I+xHXJI6kj6f4pogINrnw7Z/sDPXSW10=\" , \"frontChannelLogoutUri\" : \"null\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://www.google.com/\" ], \"claimRedirectUris\" : [], \"responseTypes\" : [ \"code\" ], \"grantTypes\" : [ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"applicationType\" : \"web\" , \"contacts\" : [], \"clientName\" : \"Jans Config Api Client\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"RS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"defaultAcrValues\" : [], \"postLogoutRedirectUris\" : [], \"requestUris\" : [], \"scopes\" : [ \"inum=1800.01.75,ou=scopes,o=jans\" , \"inum=1800.01.76,ou=scopes,o=jans\" , \"inum=1800.01.77,ou=scopes,o=jans\" , \"inum=1800.01.78,ou=scopes,o=jans\" , \"inum=1800.01.71,ou=scopes,o=jans\" , \"inum=1800.01.72,ou=scopes,o=jans\" , ], \"claims\" : [], \"trustedClient\" : false , .... .... .... \"baseDn\" : \"inum=1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe,ou=clients,o=jans\" , \"inum\" : \"1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe\" }, { \"dn\" : \"inum=478049e2-210d-4b64-bc16-10440c973f65,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"37983639-0586-4ed3-8644-b5bc41c4ce49\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://www.google.com/\" ], \"grantTypes\" : [], \"applicationType\" : \"web\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"public\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"trustedClient\" : false , ..... ..... ..... ], \"baseDn\" : \"inum=478049e2-210d-4b64-bc16-10440c973f65,ou=clients,o=jans\" , \"inum\" : \"478049e2-210d-4b64-bc16-10440c973f65\" }, { \"dn\" : \"inum=ec53d411-5243-4c76-b91c-661b35853cd0,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"456e1c1e-796d-4dc0-9f16-7b54c9e4eb5b\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://docs.jans.io/\" ], \"grantTypes\" : [], \"applicationType\" : \"web\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"public\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"trustedClient\" : false , ..... ..... ..... \"baseDn\" : \"inum=ec53d411-5243-4c76-b91c-661b35853cd0,ou=clients,o=jans\" , \"inum\" : \"ec53d411-5243-4c76-b91c-661b35853cd0\" } ] } To search using parameters, use the command below: Command jans cli --operation-id get-oauth-openid-clients \\ --endpoint-args limit:2 Creating a New OpenID Connect Clients # To add an OpenID Connect client, we can use post-oauth-openid-client operation id. As shown in the output for --info command, the post-oauth-openid-client operation requires data to be sent according to Client schema. To see the schema, use the command below: Command jans cli --schema Client The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample Client Using the schema and the example above, we have added OpenID Connect client data to the file /tmp/openid-connect.json . An OpenID Connect client may have many properties, but we are going to fill only the required properties as shown below: Input { \"redirectUris\" : [ \"https://www.google.com/\" ] } Now let's post an OpenID Connect client to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-openid-client \\ --data /tmp/openid-connect.json Update OpenId Connect client # To update the configuration follow the steps below. Get the existing OpenID Connect Client and store it into a file for editing. The following command will retrieve the existing OpenID Connect Client in the schema file. Command jans cli -no-color \\ --operation-id get-oauth-openid-clients-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe > /tmp/update-client.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Client schema as mentioned here . We have changed in parLifetime only the 600 to 700 . Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-openid-client \\ --data /tmp/update-client.json Upon successful execution of the update, the Janssen Server responds with updated configuration Patch OpenID Connect Client by inum # Using patch-oauth-openid-client-by-inum , we can modify OpenID Connect Clients partially for its properties. To use this operation, specify the inum of the OpenID Connect Client that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property applicationType from web to native . Input 1 2 3 4 5 6 7 [ { \"op\" : \"replace\" , \"path\" : \"applicationType\" , \"value\" : \"native\" } ] Now let's do the operation with the command line. jans cli \\ --operation-id patch-oauth-openid-client-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe --data /tmp/schema.json Get OpenID Connect Client by Inum # With get-oauth-openid-clients-by-inum operation-id, we can get any specific OpenID Connect Client matched with Inum . If we know the inum , we can use the below command: jans cli \\ --operation-id get-oauth-openid-clients-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe The result will only show details of client with inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe . Delete OpenID Connect client # Delete the OpenID Connect client using its inum . The command line is: Command jans cli \\ --operation-id delete-oauth-openid-client-by-inum \\ --url-suffix inum:a89b5c29-2a91-48b5-bf27-1bf786954a06 It will delete the OpenID Connect client if it matches with the given inum . Using Text Based UI # Start TUI using the command below: Command jans tui Client Screen # Navigate to Auth Server -> Clients to open the client screen as shown in the image below. This screen shows the OpenID Connect Clients list. To get the list of currently added clients, bring the control to Search box (using the tab key), and press the Enter key. Type the search string to search for the client with the matching client name. Add-Update Client screen # Use the Add Client button to create a new client. After adding the valid data using the Save button, add a new OpenID Connect client. Update the OpenID Connect client as well. To update the client, bring the control to the Specific Client row and press the Enter key, then it will show the edit client screen. If you are editing a client, you will have Active Tokens where you can search and delete tokens related to the edited client as shown image below. To view client details in json format, press key v on keyboard, to delete press delete (or d ) key. Delete Screen # To delete the client, bring the control to the Specific Client row and press the Delete key. Then it will show the Delete confirmation box. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document .", "title": "OpenID Connect Client Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#openid-connect-configuration", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "OpenID Connect Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#using-command-line", "text": "In the Janssen Server, you can deploy and manage the OpenID Connect Client using the command Line. To get the details of Janssen command line operations relevant to OpenID Connect Client, you can check the operations under OauthOpenidConnectClients task using the command below: Let's get the information about OpenID Connect Client Configuration: Command jans cli --info OauthOpenidConnectClients Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Operation ID: get-oauth-openid-clients Description: Gets list of OpenID Connect clients Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-openid-client Description: Update OpenId Connect client Schema: Client Operation ID: post-oauth-openid-client Description: Create new OpenId Connect client Schema: Client Operation ID: get-oauth-openid-clients-by-inum Description: Get OpenId Connect Client by Inum Parameters: inum: Client identifier [string] Operation ID: delete-oauth-openid-client-by-inum Description: Delete OpenId Connect client Parameters: inum: Client identifier [string] Operation ID: patch-oauth-openid-client-by-inum Description: Patch OpenId Connect client Parameters: inum: Client identifier [string] Schema: Array of JsonPatch To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#get-list-of-openid-connect-clients", "text": "To get the list of OpenID Connect clients, run the following command: Command jans cli --operation-id get-oauth-openid-clients Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 { { \"start\" : 0 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 3 , \"entries\" : [ { \"dn\" : \"inum=1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"qAnnHv5Yxw6I+xHXJI6kj6f4pogINrnw7Z/sDPXSW10=\" , \"frontChannelLogoutUri\" : \"null\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://www.google.com/\" ], \"claimRedirectUris\" : [], \"responseTypes\" : [ \"code\" ], \"grantTypes\" : [ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"applicationType\" : \"web\" , \"contacts\" : [], \"clientName\" : \"Jans Config Api Client\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"RS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"defaultAcrValues\" : [], \"postLogoutRedirectUris\" : [], \"requestUris\" : [], \"scopes\" : [ \"inum=1800.01.75,ou=scopes,o=jans\" , \"inum=1800.01.76,ou=scopes,o=jans\" , \"inum=1800.01.77,ou=scopes,o=jans\" , \"inum=1800.01.78,ou=scopes,o=jans\" , \"inum=1800.01.71,ou=scopes,o=jans\" , \"inum=1800.01.72,ou=scopes,o=jans\" , ], \"claims\" : [], \"trustedClient\" : false , .... .... .... \"baseDn\" : \"inum=1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe,ou=clients,o=jans\" , \"inum\" : \"1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe\" }, { \"dn\" : \"inum=478049e2-210d-4b64-bc16-10440c973f65,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"37983639-0586-4ed3-8644-b5bc41c4ce49\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://www.google.com/\" ], \"grantTypes\" : [], \"applicationType\" : \"web\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"public\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"trustedClient\" : false , ..... ..... ..... ], \"baseDn\" : \"inum=478049e2-210d-4b64-bc16-10440c973f65,ou=clients,o=jans\" , \"inum\" : \"478049e2-210d-4b64-bc16-10440c973f65\" }, { \"dn\" : \"inum=ec53d411-5243-4c76-b91c-661b35853cd0,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"456e1c1e-796d-4dc0-9f16-7b54c9e4eb5b\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://docs.jans.io/\" ], \"grantTypes\" : [], \"applicationType\" : \"web\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"public\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"trustedClient\" : false , ..... ..... ..... \"baseDn\" : \"inum=ec53d411-5243-4c76-b91c-661b35853cd0,ou=clients,o=jans\" , \"inum\" : \"ec53d411-5243-4c76-b91c-661b35853cd0\" } ] } To search using parameters, use the command below: Command jans cli --operation-id get-oauth-openid-clients \\ --endpoint-args limit:2", "title": "Get List of OpenID Connect Clients"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#creating-a-new-openid-connect-clients", "text": "To add an OpenID Connect client, we can use post-oauth-openid-client operation id. As shown in the output for --info command, the post-oauth-openid-client operation requires data to be sent according to Client schema. To see the schema, use the command below: Command jans cli --schema Client The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample Client Using the schema and the example above, we have added OpenID Connect client data to the file /tmp/openid-connect.json . An OpenID Connect client may have many properties, but we are going to fill only the required properties as shown below: Input { \"redirectUris\" : [ \"https://www.google.com/\" ] } Now let's post an OpenID Connect client to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-openid-client \\ --data /tmp/openid-connect.json", "title": "Creating a New OpenID Connect Clients"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#update-openid-connect-client", "text": "To update the configuration follow the steps below. Get the existing OpenID Connect Client and store it into a file for editing. The following command will retrieve the existing OpenID Connect Client in the schema file. Command jans cli -no-color \\ --operation-id get-oauth-openid-clients-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe > /tmp/update-client.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Client schema as mentioned here . We have changed in parLifetime only the 600 to 700 . Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-openid-client \\ --data /tmp/update-client.json Upon successful execution of the update, the Janssen Server responds with updated configuration", "title": "Update OpenId Connect client"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#patch-openid-connect-client-by-inum", "text": "Using patch-oauth-openid-client-by-inum , we can modify OpenID Connect Clients partially for its properties. To use this operation, specify the inum of the OpenID Connect Client that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property applicationType from web to native . Input 1 2 3 4 5 6 7 [ { \"op\" : \"replace\" , \"path\" : \"applicationType\" , \"value\" : \"native\" } ] Now let's do the operation with the command line. jans cli \\ --operation-id patch-oauth-openid-client-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe --data /tmp/schema.json", "title": "Patch OpenID Connect Client by inum"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#get-openid-connect-client-by-inum", "text": "With get-oauth-openid-clients-by-inum operation-id, we can get any specific OpenID Connect Client matched with Inum . If we know the inum , we can use the below command: jans cli \\ --operation-id get-oauth-openid-clients-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe The result will only show details of client with inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe .", "title": "Get OpenID Connect Client by Inum"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#delete-openid-connect-client", "text": "Delete the OpenID Connect client using its inum . The command line is: Command jans cli \\ --operation-id delete-oauth-openid-client-by-inum \\ --url-suffix inum:a89b5c29-2a91-48b5-bf27-1bf786954a06 It will delete the OpenID Connect client if it matches with the given inum .", "title": "Delete OpenID Connect client"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#using-text-based-ui", "text": "Start TUI using the command below: Command jans tui", "title": "Using Text Based UI"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#client-screen", "text": "Navigate to Auth Server -> Clients to open the client screen as shown in the image below. This screen shows the OpenID Connect Clients list. To get the list of currently added clients, bring the control to Search box (using the tab key), and press the Enter key. Type the search string to search for the client with the matching client name.", "title": "Client Screen"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#add-update-client-screen", "text": "Use the Add Client button to create a new client. After adding the valid data using the Save button, add a new OpenID Connect client. Update the OpenID Connect client as well. To update the client, bring the control to the Specific Client row and press the Enter key, then it will show the edit client screen. If you are editing a client, you will have Active Tokens where you can search and delete tokens related to the edited client as shown image below. To view client details in json format, press key v on keyboard, to delete press delete (or d ) key.", "title": "Add-Update Client screen"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#delete-screen", "text": "To delete the client, bring the control to the Specific Client row and press the Delete key. Then it will show the Delete confirmation box.", "title": "Delete Screen"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/ssa-config/", "tags": ["administration", "recipes", "open-banking"], "text": "SSA Configuration # This document is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "SSA Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/ssa-config/#ssa-configuration", "text": "This document is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "SSA Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/ssa-config/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/config-guide/auth-server-config/ssa-config/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/", "tags": ["administration", "configuration", "tools", "cli", "curl"], "text": "Most useful configurations and operations on Jans server using CURL # Configuring the Janssen server # To use CURL commands and configure Janssen's Authorization server, you need to have an access token of \"Config-API\" (which is an RP of Jans-auth server). Configurations to the AS can be done only through \"The Config-API client (RP)\". Obtaining an Access token # All commands to configure the AS are protected by an Access token. According to the use case, you must specify the scope for which the access token has been requested. For the client_id and client_secret, contact your administrator. Template curl -u \"client_inum:client_secret\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=put_scope_name_here\" Example : To modify a custom script, you need to request an access token using the scope scope=https://jans.io/oauth/config/scripts.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scripts.write\" Enable an authentication script # Steps # Obtain a token, use scope https://jans.io/oauth/config/scripts.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scripts.write\" Enable the script curl https://<your.jans.server>/jans-config-api/api/v1/config/scripts/name/name_of_the_script \\ -H \"Authorization: Bearer put_access_token_here\" Examples of name_of_the_script ( Authentication methods that are present in the Janssen server.) Name of the script smpp otp duo fido2 super_gluu twilio_sms smpp otp duo fido2 super_gluu Client creation # Creating a client with minimal upfront configuration requires only redirectUris in following format. Add following content in a text file and save it as client.json. { \"redirectUris\" : [ \"http://localhost:8080\" ] } In place of http://localhost:8080 uri used above, any valid redirect URI can be used. To provide full client configuration at the time of creation, Download and use this json format , update the values and save it as client.json. Few important fields to populate are scope , responseTypes , redirectUris (The only mandatory field), grantTypes . If there is a need to update the attributes of the client after creation, then make sure that the client is created with grantTypes list having client_credentials grant type as well. Run curl command curl -X POST https://my.jans.server/jans-auth/restv1/register \\ -H \"Content-Type: application/json\" -d @/some/directory/client.json If client is created successfully, response similar to below will be received: { \"allow_spontaneous_scopes\" : false , \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://my.jans.server/jans-auth/restv1/register?client_id=994ec0a7-1143-456c-85ca-66ba592d7f9a\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"d34f30ff-ae31-4760-8b67-ef071ba9ee68\" , \"client_id\" : \"994ec0a7-1143-456c-85ca-66ba592d7f9a\" , \"token_endpoint_auth_method\" : \"client_secret_basic\" , \"scope\" : \"openid profile permission https://jans.io/auth/ssa.portal uma_protection work_phone phone address test https://jans.io/auth/ssa.admin user_name email clientinfo device_sso org_name https://jans.io/auth/ssa.developer offline_access\" , \"client_secret\" : \"da4c17de-b6bc-4f25-b642-4c7b887c7860\" , \"client_id_issued_at\" : 1672221633 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"par_lifetime\" : 600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : false , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" ], \"subject_type\" : \"pairwise\" , \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1672308033 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" ] } Response contains client_id and client_secret apart from other client configuration details. Get Client Details # Obtain an Access Token with scope https://jans.io/oauth/config/openid/clients.readonly . curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/openid/clients.readonly\" Obtain client information using: curl -X GET https://my.jans.server/jans-config-api/api/v1/openid/clients/client-s_inum_for_which_scope_to_be_added -H \"Authorization: Bearer put_access_token_here\" This will return JSON response similar to the one below. { \"dn\" : \"inum=994ec0a7-1143-456c-85ca-66ba592d7f9a,ou=clients,o=jans\" , \"expirationDate\" : \"2022-12-29T10:00:33\" , \"deletable\" : true , \"clientSecret\" : \"5Mlvuh0JRwl/WcpiUNGGXjtDO4+SprNBjiVFFcWqWB4gu7gYxqcSMw==\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" :[ \"http://localhost:8080\" ], \"responseTypes\" :[ \"code\" ], \"grantTypes\" :[ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"applicationType\" : \"web\" , \"clientName\" : \"dd-test-client\" , \"clientNameLocalized\" :{ }, \"logoUriLocalized\" :{ }, \"clientUriLocalized\" :{ }, \"policyUriLocalized\" :{ }, \"tosUriLocalized\" :{ }, \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"RS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"scopes\" :[ \"inum=F0C4,ou=scopes,o=jans\" , \"inum=43F1,ou=scopes,o=jans\" , \"inum=C4F5,ou=scopes,o=jans\" , \"inum=SSA1-PTL1,ou=scopes,o=jans\" , \"inum=6D99,ou=scopes,o=jans\" , \"inum=7D02,ou=scopes,o=jans\" , \"inum=D491,ou=scopes,o=jans\" , \"inum=C17A,ou=scopes,o=jans\" , \"inum=0465-1DEA,ou=scopes,o=jans\" , \"inum=SSA1-AD01,ou=scopes,o=jans\" , \"inum=10B2,ou=scopes,o=jans\" , \"inum=764C,ou=scopes,o=jans\" , \"inum=341A,ou=scopes,o=jans\" , \"inum=C4F8,ou=scopes,o=jans\" , \"inum=7D01,ou=scopes,o=jans\" , \"inum=SSA1-DEV1,ou=scopes,o=jans\" , \"inum=C4F6,ou=scopes,o=jans\" ], \"trustedClient\" : false , \"persistClientAuthorizations\" : true , \"includeClaimsInIdToken\" : false , \"customAttributes\" :[ ], \"customObjectClasses\" :[ \"top\" ], \"rptAsJwt\" : false , \"accessTokenAsJwt\" : false , \"accessTokenSigningAlg\" : \"RS256\" , \"disabled\" : false , \"attributes\" :{ \"runIntrospectionScriptBeforeJwtCreation\" : false , \"keepClientAuthorizationAfterExpiration\" : false , \"allowSpontaneousScopes\" : false , \"backchannelLogoutSessionRequired\" : false , \"parLifetime\" : 600 , \"requirePar\" : false , \"jansDefaultPromptLogin\" : false , \"minimumAcrLevel\" : -1 }, \"backchannelTokenDeliveryMode\" : \"poll\" , \"backchannelUserCodeParameter\" : false , \"displayName\" : \"dd-test-client\" , \"authenticationMethod\" : \"client_secret_basic\" , \"baseDn\" : \"inum=994ec0a7-1143-456c-85ca-66ba592d7f9a,ou=clients,o=jans\" , \"inum\" : \"994ec0a7-1143-456c-85ca-66ba592d7f9a\" } Add New Scope to Client # To the above client, lets append the profile, so the scope attrib should now have value \"openid user_name profile\"`. This new value will be patched onto the client. Obtain an Access Token with scope https://jans.io/oauth/config/openid/clients.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/openid/clients.write\" Patch the new scope for the client curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://my.jans.server/jans-config-api/api/v1/openid/clients/put_client_inum_here' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"/scope\", \"value\": \"openid user_name profile\" } ]' Add OpenID scope and map to database attribute # Obtain access token curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scopes.write\" Build json on similar lines { \"dn\": \"string\", \"inum\": \"string\", \"displayName\": \"string\", \"id\": \"string\", \"iconUrl\": \"string\", \"description\": \"string\", \"scopeType\": \"openid\", \"claims\": [ \"string\" ], \"defaultScope\": true, \"groupClaims\": true, \"dynamicScopeScripts\": [ \"string\" ], \"umaAuthorizationPolicies\": [ \"string\" ], \"attributes\": { \"spontaneousClientId\": \"string\", \"spontaneousClientScopes\": [ \"string\" ], \"showInConfigurationEndpoint\": true }, \"umaType\": false, \"deletable\": false, \"expirationDate\": \"2022-07-26\" } Run curl. Note the claims field which maps to the database attrib curl -k -X POST https://jans-ui.jans.io/jans-config-api/api/v1/scopes -H \"Content-Type: application/json\" -H \"Authorization: Bearer use_bearer_token_here\" --data '{ \"dn\": \"inum=AAC1,ou=scopes,o=jans\", \"inum\": \"AAC1\", \"displayName\": \"website\", \"id\": \"website\", \"description\": \"website\", \"scopeType\": \"openid\", \"claims\": [\"website\"], \"umaType\": false, \"deletable\": false }' Using the Janssen server # Accessing OpenID Discovery endpoint / Well-known endpoint # curl https://jans-ui.jans.io/.well-known/openid-configuration Client Credentials Flow # curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scopes.write\" Authorization code flow # Steps: On a browser type https://my.jans.server/jans-auth/restv1/authorize?redirect_uri=https://my-redirect-app:8080&client_id=Put_client_id_here&scope=username+openid&response_type=code Based on the default authentication method set, the user will be presented with credentials for login. The OpenID Provider (Gluu Server) verifies the user\u2019s identity and authenticates the user. In the back channel the following steps take place : The OpenID Provider (Gluu Server) sends the user back to the application with an authorization code. The application sends the code to the Token Endpoint to receive an Access Token and ID Token in the response. The application uses the ID Token to authorize the user. At this point the application/RP can access the UserInfo endpoint for claims. Device Authorization code flow # Client_id that is used in the curl command below should have grant_type urn:ietf:params:oauth:grant-type:device_code Call the Device Authorization Endpoint : curl -k -u \"client_id_here:client_secret_here\" https://jans-ui.jans.io/jans-auth/restv1/device_authorization \\ -d scope=openid+profile+email+offline_access\" Response received will be like this { \"user_code\": \"HJDN-BMHQ\", \"device_code\": \"b8a5e5e6b1c10506af4f4bbb5400ca2587dcfe44974d7e62\", \"interval\": 5, \"verification_uri_complete\": \"https://jans-ui.jans.io/device-code?user_code=HJDN-BMHQ\", \"verification_uri\": \"https://jans-ui.jans.io/device-code\", \"expires_in\": 1800 } User should visit the verification_uri link on a browser and enter the user_code . Until the user to activates the device, begin polling token URL to request an Access Token. Use interval from step 2 as the polling interval. curl -k -u \"client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=YOUR_DEVICE_CODE&client_id=YOUR_CLIENT_ID\"", "title": "CURL"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#most-useful-configurations-and-operations-on-jans-server-using-curl", "text": "", "title": "Most useful configurations and operations on Jans server using CURL"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#configuring-the-janssen-server", "text": "To use CURL commands and configure Janssen's Authorization server, you need to have an access token of \"Config-API\" (which is an RP of Jans-auth server). Configurations to the AS can be done only through \"The Config-API client (RP)\".", "title": "Configuring the Janssen server"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#obtaining-an-access-token", "text": "All commands to configure the AS are protected by an Access token. According to the use case, you must specify the scope for which the access token has been requested. For the client_id and client_secret, contact your administrator. Template curl -u \"client_inum:client_secret\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=put_scope_name_here\" Example : To modify a custom script, you need to request an access token using the scope scope=https://jans.io/oauth/config/scripts.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scripts.write\"", "title": "Obtaining an Access token"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#enable-an-authentication-script", "text": "", "title": "Enable an authentication script"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#steps", "text": "Obtain a token, use scope https://jans.io/oauth/config/scripts.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scripts.write\" Enable the script curl https://<your.jans.server>/jans-config-api/api/v1/config/scripts/name/name_of_the_script \\ -H \"Authorization: Bearer put_access_token_here\" Examples of name_of_the_script ( Authentication methods that are present in the Janssen server.) Name of the script smpp otp duo fido2 super_gluu twilio_sms smpp otp duo fido2 super_gluu", "title": "Steps"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#client-creation", "text": "Creating a client with minimal upfront configuration requires only redirectUris in following format. Add following content in a text file and save it as client.json. { \"redirectUris\" : [ \"http://localhost:8080\" ] } In place of http://localhost:8080 uri used above, any valid redirect URI can be used. To provide full client configuration at the time of creation, Download and use this json format , update the values and save it as client.json. Few important fields to populate are scope , responseTypes , redirectUris (The only mandatory field), grantTypes . If there is a need to update the attributes of the client after creation, then make sure that the client is created with grantTypes list having client_credentials grant type as well. Run curl command curl -X POST https://my.jans.server/jans-auth/restv1/register \\ -H \"Content-Type: application/json\" -d @/some/directory/client.json If client is created successfully, response similar to below will be received: { \"allow_spontaneous_scopes\" : false , \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://my.jans.server/jans-auth/restv1/register?client_id=994ec0a7-1143-456c-85ca-66ba592d7f9a\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"d34f30ff-ae31-4760-8b67-ef071ba9ee68\" , \"client_id\" : \"994ec0a7-1143-456c-85ca-66ba592d7f9a\" , \"token_endpoint_auth_method\" : \"client_secret_basic\" , \"scope\" : \"openid profile permission https://jans.io/auth/ssa.portal uma_protection work_phone phone address test https://jans.io/auth/ssa.admin user_name email clientinfo device_sso org_name https://jans.io/auth/ssa.developer offline_access\" , \"client_secret\" : \"da4c17de-b6bc-4f25-b642-4c7b887c7860\" , \"client_id_issued_at\" : 1672221633 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"par_lifetime\" : 600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : false , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" ], \"subject_type\" : \"pairwise\" , \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1672308033 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" ] } Response contains client_id and client_secret apart from other client configuration details.", "title": "Client creation"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#get-client-details", "text": "Obtain an Access Token with scope https://jans.io/oauth/config/openid/clients.readonly . curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/openid/clients.readonly\" Obtain client information using: curl -X GET https://my.jans.server/jans-config-api/api/v1/openid/clients/client-s_inum_for_which_scope_to_be_added -H \"Authorization: Bearer put_access_token_here\" This will return JSON response similar to the one below. { \"dn\" : \"inum=994ec0a7-1143-456c-85ca-66ba592d7f9a,ou=clients,o=jans\" , \"expirationDate\" : \"2022-12-29T10:00:33\" , \"deletable\" : true , \"clientSecret\" : \"5Mlvuh0JRwl/WcpiUNGGXjtDO4+SprNBjiVFFcWqWB4gu7gYxqcSMw==\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" :[ \"http://localhost:8080\" ], \"responseTypes\" :[ \"code\" ], \"grantTypes\" :[ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"applicationType\" : \"web\" , \"clientName\" : \"dd-test-client\" , \"clientNameLocalized\" :{ }, \"logoUriLocalized\" :{ }, \"clientUriLocalized\" :{ }, \"policyUriLocalized\" :{ }, \"tosUriLocalized\" :{ }, \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"RS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"scopes\" :[ \"inum=F0C4,ou=scopes,o=jans\" , \"inum=43F1,ou=scopes,o=jans\" , \"inum=C4F5,ou=scopes,o=jans\" , \"inum=SSA1-PTL1,ou=scopes,o=jans\" , \"inum=6D99,ou=scopes,o=jans\" , \"inum=7D02,ou=scopes,o=jans\" , \"inum=D491,ou=scopes,o=jans\" , \"inum=C17A,ou=scopes,o=jans\" , \"inum=0465-1DEA,ou=scopes,o=jans\" , \"inum=SSA1-AD01,ou=scopes,o=jans\" , \"inum=10B2,ou=scopes,o=jans\" , \"inum=764C,ou=scopes,o=jans\" , \"inum=341A,ou=scopes,o=jans\" , \"inum=C4F8,ou=scopes,o=jans\" , \"inum=7D01,ou=scopes,o=jans\" , \"inum=SSA1-DEV1,ou=scopes,o=jans\" , \"inum=C4F6,ou=scopes,o=jans\" ], \"trustedClient\" : false , \"persistClientAuthorizations\" : true , \"includeClaimsInIdToken\" : false , \"customAttributes\" :[ ], \"customObjectClasses\" :[ \"top\" ], \"rptAsJwt\" : false , \"accessTokenAsJwt\" : false , \"accessTokenSigningAlg\" : \"RS256\" , \"disabled\" : false , \"attributes\" :{ \"runIntrospectionScriptBeforeJwtCreation\" : false , \"keepClientAuthorizationAfterExpiration\" : false , \"allowSpontaneousScopes\" : false , \"backchannelLogoutSessionRequired\" : false , \"parLifetime\" : 600 , \"requirePar\" : false , \"jansDefaultPromptLogin\" : false , \"minimumAcrLevel\" : -1 }, \"backchannelTokenDeliveryMode\" : \"poll\" , \"backchannelUserCodeParameter\" : false , \"displayName\" : \"dd-test-client\" , \"authenticationMethod\" : \"client_secret_basic\" , \"baseDn\" : \"inum=994ec0a7-1143-456c-85ca-66ba592d7f9a,ou=clients,o=jans\" , \"inum\" : \"994ec0a7-1143-456c-85ca-66ba592d7f9a\" }", "title": "Get Client Details"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#add-new-scope-to-client", "text": "To the above client, lets append the profile, so the scope attrib should now have value \"openid user_name profile\"`. This new value will be patched onto the client. Obtain an Access Token with scope https://jans.io/oauth/config/openid/clients.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/openid/clients.write\" Patch the new scope for the client curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://my.jans.server/jans-config-api/api/v1/openid/clients/put_client_inum_here' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"/scope\", \"value\": \"openid user_name profile\" } ]'", "title": "Add New Scope to Client"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#add-openid-scope-and-map-to-database-attribute", "text": "Obtain access token curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scopes.write\" Build json on similar lines { \"dn\": \"string\", \"inum\": \"string\", \"displayName\": \"string\", \"id\": \"string\", \"iconUrl\": \"string\", \"description\": \"string\", \"scopeType\": \"openid\", \"claims\": [ \"string\" ], \"defaultScope\": true, \"groupClaims\": true, \"dynamicScopeScripts\": [ \"string\" ], \"umaAuthorizationPolicies\": [ \"string\" ], \"attributes\": { \"spontaneousClientId\": \"string\", \"spontaneousClientScopes\": [ \"string\" ], \"showInConfigurationEndpoint\": true }, \"umaType\": false, \"deletable\": false, \"expirationDate\": \"2022-07-26\" } Run curl. Note the claims field which maps to the database attrib curl -k -X POST https://jans-ui.jans.io/jans-config-api/api/v1/scopes -H \"Content-Type: application/json\" -H \"Authorization: Bearer use_bearer_token_here\" --data '{ \"dn\": \"inum=AAC1,ou=scopes,o=jans\", \"inum\": \"AAC1\", \"displayName\": \"website\", \"id\": \"website\", \"description\": \"website\", \"scopeType\": \"openid\", \"claims\": [\"website\"], \"umaType\": false, \"deletable\": false }'", "title": "Add OpenID scope and map to database attribute"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#using-the-janssen-server", "text": "", "title": "Using the Janssen server"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#accessing-openid-discovery-endpoint-well-known-endpoint", "text": "curl https://jans-ui.jans.io/.well-known/openid-configuration", "title": "Accessing OpenID Discovery endpoint / Well-known endpoint"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#client-credentials-flow", "text": "curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scopes.write\"", "title": "Client Credentials Flow"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#authorization-code-flow", "text": "Steps: On a browser type https://my.jans.server/jans-auth/restv1/authorize?redirect_uri=https://my-redirect-app:8080&client_id=Put_client_id_here&scope=username+openid&response_type=code Based on the default authentication method set, the user will be presented with credentials for login. The OpenID Provider (Gluu Server) verifies the user\u2019s identity and authenticates the user. In the back channel the following steps take place : The OpenID Provider (Gluu Server) sends the user back to the application with an authorization code. The application sends the code to the Token Endpoint to receive an Access Token and ID Token in the response. The application uses the ID Token to authorize the user. At this point the application/RP can access the UserInfo endpoint for claims.", "title": "Authorization code flow"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#device-authorization-code-flow", "text": "Client_id that is used in the curl command below should have grant_type urn:ietf:params:oauth:grant-type:device_code Call the Device Authorization Endpoint : curl -k -u \"client_id_here:client_secret_here\" https://jans-ui.jans.io/jans-auth/restv1/device_authorization \\ -d scope=openid+profile+email+offline_access\" Response received will be like this { \"user_code\": \"HJDN-BMHQ\", \"device_code\": \"b8a5e5e6b1c10506af4f4bbb5400ca2587dcfe44974d7e62\", \"interval\": 5, \"verification_uri_complete\": \"https://jans-ui.jans.io/device-code?user_code=HJDN-BMHQ\", \"verification_uri\": \"https://jans-ui.jans.io/device-code\", \"expires_in\": 1800 } User should visit the verification_uri link on a browser and enter the user_code . Until the user to activates the device, begin polling token URL to request an Access Token. Use interval from step 2 as the polling interval. curl -k -u \"client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=YOUR_DEVICE_CODE&client_id=YOUR_CLIENT_ID\"", "title": "Device Authorization code flow"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/", "tags": ["administration", "tools", "config-api", "attributes"], "text": "Attributes # Attributes are individual pieces of user data, like uid or email, that are required by applications in order to identify a user and grant access to protected resources. In OpenID Connect, these are called user claims. Listing existing attributes # GET / (gets list of attributes based on search parameters) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|---------------------------------------------------------------------------------| > | limit | query | integer | optional |50 |Search size - max size of the results to return | > | pattern | query | string | optional |N/A |Comma separated search patter. E.g. `pattern=edu`, `pattern=edu,locale,License` | > | status | query | string | optional |all |Search size - max size of the results to return | > | startIndex | query | integer | optional |1 |Index of the first query result | > | sortBy | query | string | optional |inum |Field whose value will be used to order the returned response | > | sortOrder | query | string | optional |ascending |Search size - max size of the results to return | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `200` | `application/json` | `Paginated result` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 697479e0-e6f4-453d-bf7a-ddf31b53efba\" - X GET http : //my.jans.server/jans-config-api/api/v1/attributes?limit=5&pattern=edu,locale,carLicense&startIndex=1 ### Sample Response > { \"start\" : 0 , \"totalEntriesCount\" : 78 , \"entriesCount\" : 2 , \"entries\" : [ { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" }, { \"dn\" : \"inum=0C18,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"0C18\" , \"name\" : \"telephoneNumber\" , \"displayName\" : \"Home Telephone Number\" , \"description\" : \"Home Telephone Number\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"user\" , \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"phone_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:telephoneNumber\" , \"saml2Uri\" : \"urn:oid:2.5.4.20\" , \"urn\" : \"urn:mace:dir:attribute-def:phone_number\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : true , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=0C18,ou=attributes,o=jans\" } } GET /{inum} (gets attribute based on inum) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | `inum` | path | string | required | NA | Attribute unique identifier | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 697479e0-e6f4-453d-bf7a-ddf31b53efba\" - X GET http : //my.jans.server/jans-config-api/api/v1/attributes/08E2 ### Sample Response > { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" } Creating new attribute # POST /{inum} (creates a new attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | None | request | object (JSON) | required | NA | Attribute json | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `201` | `application/json ` | `attribute details json` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X POST - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes' -- data @ post . json ### Sample Request > { \"adminCanAccess\" : true , \"adminCanEdit\" : true , \"adminCanView\" : true , \"custom\" : false , \"dataType\" : \"string\" , \"description\" : \"QAAdded Attribute\" , \"displayName\" : \"QAAdded Attribute\" , \"editType\" : [ \"admin\" , \"user\" ], \"name\" : \"qaattribute\" , \"origin\" : \"jansPerson\" , \"jansMultivaluedAttr\" : false , \"status\" : \"active\" , \"urn\" : \"urn:mace:dir:attribute-def:qaattribute\" , \"userCanAccess\" : true , \"userCanEdit\" : true , \"userCanView\" : true , \"viewType\" : [ \"admin\" , \"user\" ], \"whitePagesCanView\" : false } Updating existing attribute # PUT /{inum} (updates an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | None | request | object (JSON) | required | NA | Attribute json | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X PUT - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes' -- data @ put . json ### Sample Request > { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" } Patching existing attribute # PATCH /{inum} (patches an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|--------------------|-----------|--------------|----------------------------------------| > | inum | path | string | required | NA | Attribute unique identifier | > | None | request | json-patch object | required | NA | json-patch request | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X PATCH - k - H 'Content-Type: application/json-patch+json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes/08E2' -- data @ patch . json ### Sample Request > [ { \"op\" : \"replace\" , \"path\" : \"/displayName\" , \"value\" : \"PatchCustomAttribute123\" } ] Deleting existing attribute # DELETE /{inum} (deletes an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|--------------------|-----------|--------------|----------------------------------------| > | inum | path | string | required | NA | Attribute unique identifier | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `204` | `application/json ` | `No Content` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X DELETE - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes/08E2' ### Sample Request > None", "title": "Attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#attributes", "text": "Attributes are individual pieces of user data, like uid or email, that are required by applications in order to identify a user and grant access to protected resources. In OpenID Connect, these are called user claims.", "title": "Attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#listing-existing-attributes", "text": "GET / (gets list of attributes based on search parameters) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|---------------------------------------------------------------------------------| > | limit | query | integer | optional |50 |Search size - max size of the results to return | > | pattern | query | string | optional |N/A |Comma separated search patter. E.g. `pattern=edu`, `pattern=edu,locale,License` | > | status | query | string | optional |all |Search size - max size of the results to return | > | startIndex | query | integer | optional |1 |Index of the first query result | > | sortBy | query | string | optional |inum |Field whose value will be used to order the returned response | > | sortOrder | query | string | optional |ascending |Search size - max size of the results to return | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `200` | `application/json` | `Paginated result` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 697479e0-e6f4-453d-bf7a-ddf31b53efba\" - X GET http : //my.jans.server/jans-config-api/api/v1/attributes?limit=5&pattern=edu,locale,carLicense&startIndex=1 ### Sample Response > { \"start\" : 0 , \"totalEntriesCount\" : 78 , \"entriesCount\" : 2 , \"entries\" : [ { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" }, { \"dn\" : \"inum=0C18,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"0C18\" , \"name\" : \"telephoneNumber\" , \"displayName\" : \"Home Telephone Number\" , \"description\" : \"Home Telephone Number\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"user\" , \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"phone_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:telephoneNumber\" , \"saml2Uri\" : \"urn:oid:2.5.4.20\" , \"urn\" : \"urn:mace:dir:attribute-def:phone_number\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : true , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=0C18,ou=attributes,o=jans\" } } GET /{inum} (gets attribute based on inum) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | `inum` | path | string | required | NA | Attribute unique identifier | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 697479e0-e6f4-453d-bf7a-ddf31b53efba\" - X GET http : //my.jans.server/jans-config-api/api/v1/attributes/08E2 ### Sample Response > { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" }", "title": "Listing existing attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#creating-new-attribute", "text": "POST /{inum} (creates a new attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | None | request | object (JSON) | required | NA | Attribute json | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `201` | `application/json ` | `attribute details json` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X POST - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes' -- data @ post . json ### Sample Request > { \"adminCanAccess\" : true , \"adminCanEdit\" : true , \"adminCanView\" : true , \"custom\" : false , \"dataType\" : \"string\" , \"description\" : \"QAAdded Attribute\" , \"displayName\" : \"QAAdded Attribute\" , \"editType\" : [ \"admin\" , \"user\" ], \"name\" : \"qaattribute\" , \"origin\" : \"jansPerson\" , \"jansMultivaluedAttr\" : false , \"status\" : \"active\" , \"urn\" : \"urn:mace:dir:attribute-def:qaattribute\" , \"userCanAccess\" : true , \"userCanEdit\" : true , \"userCanView\" : true , \"viewType\" : [ \"admin\" , \"user\" ], \"whitePagesCanView\" : false }", "title": "Creating new attribute"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#updating-existing-attribute", "text": "PUT /{inum} (updates an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | None | request | object (JSON) | required | NA | Attribute json | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X PUT - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes' -- data @ put . json ### Sample Request > { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" }", "title": "Updating existing attribute"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#patching-existing-attribute", "text": "PATCH /{inum} (patches an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|--------------------|-----------|--------------|----------------------------------------| > | inum | path | string | required | NA | Attribute unique identifier | > | None | request | json-patch object | required | NA | json-patch request | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X PATCH - k - H 'Content-Type: application/json-patch+json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes/08E2' -- data @ patch . json ### Sample Request > [ { \"op\" : \"replace\" , \"path\" : \"/displayName\" , \"value\" : \"PatchCustomAttribute123\" } ]", "title": "Patching existing attribute"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#deleting-existing-attribute", "text": "DELETE /{inum} (deletes an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|--------------------|-----------|--------------|----------------------------------------| > | inum | path | string | required | NA | Attribute unique identifier | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `204` | `application/json ` | `No Content` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X DELETE - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes/08E2' ### Sample Request > None", "title": "Deleting existing attribute"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/", "tags": ["administration", "tools", "configuration", "config-api"], "text": "Janssen Config-API Configuration # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and customize the Config-API Configuration using the command line. To get the details of Janssen command line operations relevant to Config-API Configuration, you can check the operations under ConfigurationConfigApi task using the command below: Command jans tui --info ConfigurationConfigApi It will show the details of the available operation-ids for Config-API. Sample Output Operation ID: get-config-api-properties Description: Gets config-api configuration properties. Operation ID: patch-config-api-properties Description: Partially modifies config-api Configuration properties. Schema: Array of JsonPatch To get sample schema type jans tui --schema-sample <schema>, for example jans tui --schema-sample JsonPatch Get The Current Config-API Configuration # Configuration for Config-API is a set of key-value pairs, called properties. When we retrieve the configuration, these properties and their current values are returned as a JSON document. To get the properties of Janssen Config-API Configuration, run the command below: Command jans tui --operation-id = get-config-api-properties It will return the result as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 { \"serviceName\" : \"jans-config-api\" , \"configOauthEnabled\" : true , \"disableLoggerTimer\" : false , \"disableAuditLogger\" : false , \"customAttributeValidationEnabled\" : true , \"acrValidationEnabled\" : true , \"apiApprovedIssuer\" : [ \"https://example.jans.io\" ], \"apiProtectionType\" : \"oauth2\" , \"apiClientId\" : \"1800.b62cb614-a09d-4163-a6bc-32e38a51c4d2\" , \"apiClientPassword\" : \"CN8ggRUhMkw9K0ocQ+LXbA==\" , \"endpointInjectionEnabled\" : false , \"authIssuerUrl\" : \"https://example.jans.io\" , \"authOpenidConfigurationUrl\" : \"https://example.jans.io/.well-known/openid-configuration\" , \"authOpenidIntrospectionUrl\" : \"https://example.jans.io/jans-auth/restv1/introspection\" , \"authOpenidTokenUrl\" : \"https://example.jans.io/jans-auth/restv1/token\" , \"authOpenidRevokeUrl\" : \"https://example.jans.io/jans-auth/restv1/revoke\" , \"exclusiveAuthScopes\" : [ \"jans_stat\" , \"https://jans.io/scim/users.read\" , \"https://jans.io/scim/users.write\" ], \"corsConfigurationFilters\" : [ { \"filterName\" : \"CorsFilter\" , \"corsEnabled\" : true , \"corsAllowedOrigins\" : \"*\" , \"corsAllowedMethods\" : \"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\" , \"corsSupportCredentials\" : true , \"corsLoggingEnabled\" : false , \"corsPreflightMaxAge\" : 1800 , \"corsRequestDecorate\" : true } ], \"loggingLevel\" : \"INFO\" , \"loggingLayout\" : \"text\" , \"disableJdkLogger\" : true , \"maxCount\" : 200 , \"acrExclusionList\" : [ \"simple_password_auth\" ], \"userExclusionAttributes\" : [ \"userPassword\" ], \"userMandatoryAttributes\" : [ \"mail\" , \"displayName\" , \"status\" , \"userPassword\" , \"givenName\" ], \"agamaConfiguration\" : { \"mandatoryAttributes\" : [ \"qname\" , \"source\" ], \"optionalAttributes\" : [ \"serialVersionUID\" , \"enabled\" ] }, \"auditLogConf\" : { \"enabled\" : true , \"headerAttributes\" : [ \"User-inum\" ] }, \"dataFormatConversionConf\" : { \"enabled\" : true , \"ignoreHttpMethod\" : [ \"@jakarta.ws.rs.GET()\" ] }, \"plugins\" : [ { \"name\" : \"admin\" , \"description\" : \"admin-ui plugin\" , \"className\" : \"io.jans.ca.plugin.adminui.rest.ApiApplication\" }, { \"name\" : \"fido2\" , \"description\" : \"fido2 plugin\" , \"className\" : \"io.jans.configapi.plugin.fido2.rest.ApiApplication\" }, { \"name\" : \"scim\" , \"description\" : \"scim plugin\" , \"className\" : \"io.jans.configapi.plugin.scim.rest.ApiApplication\" }, { \"name\" : \"user-management\" , \"description\" : \"user-management plugin\" , \"className\" : \"io.jans.configapi.plugin.mgt.rest.ApiApplication\" }, { \"name\" : \"jans-link\" , \"description\" : \"jans-link plugin\" , \"className\" : \"io.jans.configapi.plugin.link.rest.ApiApplication\" }, { \"name\" : \"saml\" , \"description\" : \"saml plugin\" , \"className\" : \"io.jans.configapi.plugin.saml.rest.ApiApplication\" }, { \"name\" : \"kc-link\" , \"description\" : \"kc-link plugin\" , \"className\" : \"io.jans.configapi.plugin.kc.link.rest.ApiApplication\" }, { \"name\" : \"lock\" , \"description\" : \"lock plugin\" , \"className\" : \"io.jans.configapi.plugin.lock.rest.ApiApplication\" } ], \"assetMgtConfiguration\" : { \"assetMgtEnabled\" : true , \"assetServerUploadEnabled\" : true , \"fileExtensionValidationEnabled\" : true , \"moduleNameValidationEnabled\" : true , \"assetBaseDirectory\" : \"/opt/jans/jetty/%s/custom\" , \"jansServiceModule\" : [ \"jans-auth\" , \"jans-config-api\" , \"jans-fido2\" , \"jans-scim\" ], \"assetDirMapping\" : [ { \"directory\" : \"i18n\" , \"type\" : [ \"properties\" ], \"description\" : \"Resource bundle file.\" }, { \"directory\" : \"libs\" , \"type\" : [ \"jar\" /op t /ja ns /ja ns - cli/co nf ig - cli.py -- i nf o Co nf igura t io n Co nf igApi ], \"description\" : \"java archive library.\" }, { \"directory\" : \"pages\" , \"type\" : [ \"xhtml\" ], \"description\" : \"Web pages.\" }, { \"directory\" : \"static\" , \"type\" : [ \"js\" , \"css\" , \"png\" , \"gif\" , \"jpg\" , \"jpeg\" ], \"description\" : \"Static resources like Java-script, style-sheet and images.\" } ] } } Update Config-API Configuration Properties # To update the configuration, we will use JSON patch schema as shown below. Let's say we want to stop the file extension validation done by config-api's asset management module. This can be done by setting the fileExtensionValidationEnabled property to false . To do that, write a text file ( config-api-assetmgt-patch.json ) with the content that follows the JSON patch schema. config-api-assetmgt-patch.json 1 2 3 4 5 6 7 [ { \"op\" : \"replace\" , \"path\" : \"/assetMgtConfiguration/fileExtensionValidationEnabled\" , \"value\" : false } ] Now, execute the following command to apply this patch: Command jans tui \\ --operation-id = patch-config-api-properties --data ./config-api-assetmgt-patch.json Upon successful execution of the update, the Janssen Server responds with updated configuration. Updating multi-valued property # Let's say we want to update the configuration property userMandatoryAttributes . This property's value is a list of attributes. We want to remove an attribute from the list. For this, we will have to create a JSON patch file that contains the new list and then run a command to push the update to the Janssen Server. Let's do this step-by-step: Get the current value list for userMandatoryAttributes property using steps mentioned in Get the current configuration section Using the current list of values as a starting point, create a JSON patch file config-api-patch.json as below. Update the list as desired by adding or removing items from the list: Sample Contents 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [ { \"op\" : \"replace\" , \"path\" : \"/userMandatoryAttributes\" , \"value\" : [ \"mail\" , \"displayName\" , \"status\" , \"userPassword\" , \"givenName\" , \"gender\" ] } ] Now, execute the following command to apply this patch: Command jans tui \\ --operation-id = patch-config-api-properties --data ./config-api-patch.json Config API Configuration Parameters: # The table below outlines the key configuration parameters for the Jans Config API. It details settings for OAuth2, security, endpoints, logging, and plugin management. Field named Example Description configOauthEnabled true property can be used to enable or disable the oAuth2 authorization. By default, it is set to true. apiApprovedIssuer [\"https:// ,https:// ,https:// \"] Enables to set more than one authorization servers. By default, the current auth-server is set. You can add more servers separated by commas. apiProtectionType oauth2 Currently support mechanism is OAuth 2.0 tokens. apiClientId 1800.52eb1bed-ab5c-4ba6-b87e-90aad26058d0 Jans Config API Client. apiClientPassword lwI/8mcMkF63mvueYTZ0mQ== Encrypted secret of Jans Config API Client endpointInjectionEnabled false To be used if the endpoint needs to be injected. authIssuerUrl https://my-jans-server.jans.io URL of underlying auth-server. authOpenidConfigurationUrl https://my-jans-server.jans.io/.well-known/openid-configuration Metadata URL of the authorization server. authOpenidIntrospectionUrl https://my-jans-server.jans.io/jans-auth/restv1/introspection Authorization server endpoint to check the state of an OAuth 2.0 token and to determine meta-information about the token. authOpenidTokenUrl https://my-jans-server.jans.io/jans-auth/restv1/token Authorization server endpoint to obtain an Access Token, an ID Token, and optionally a Refresh Token. authOpenidRevokeUrl https://my-jans-server.jans.io/jans-auth/restv1/token Authorization server endpoint to notify an OAuth 2.0 authorization server that a previously obtained refresh or access token is no longer needed, allowing the server to clean up security credentials. smallryeHealthRootPath /health-check Deprecated param for health-check exclusiveAuthScopes [\"jans_stat\",\"https://jans.io/scim/users.read\",\"https://jans.io/scim/users.write\"] Scopes that are only validated against the underlying Jansen Authorization server. corsConfigurationFilters [{\"filterName\":\"CorsFilter\",\"corsEnabled\":true,\"corsAllowedOrigins\":\"*\",\"corsAllowedMethods\":\"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\",\"corsAllowedHeaders\":\"\",\"corsExposedHeaders\":\"\",\"corsSupportCredentials\":true,\"corsLoggingEnabled\":false,\"corsPreflightMaxAge\":1800,\"corsRequestDecorate\":true}] This list specifies the CORS configuration filters. exclusiveAuthScopes [\"jans_stat\",\"https://jans.io/scim/users.read\",\"https://jans.io/scim/users.write\"] Scopes that are only validated against the underlying Jansen Authorization server. loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for Config API. loggingLayout \"text\" Contents of logs as plain text format. externalLoggerConfiguration Path to external log4j2 logging configuration. disableJdkLogger true Boolean to disable JDK loggers. maxCount 200 To be used to set maximum records returned in response. userExclusionAttributes [\"userPassword\"] List of attributes to be excluded in User response. userMandatoryAttributes [\"mail\",\"displayName\",\"jansStatus\",\"userPassword\",\"givenName\"] List of attributes mandatory for creating a User. agamaConfiguration {\"mandatoryAttributes\":[\"qname\",\"source\"],\"optionalAttributes\":[\"serialVersionUID\",\"enabled\"]} Configuration parameters like mandatory, optional, etc for agama flow. auditLogConf {\"enabled\":true,\"ignoreHttpMethod\":[],\"headerAttributes\":[\"User-inum\"]} Audit Log configuration. dataFormatConversionConf {\"enabled\":true,\"ignoreHttpMethod\":[\"@jakarta.ws.rs.GET()\"]} DB specific data format conversion configuration for Date field. plugins [{\"name\":\"admin\",\"description\":\"admin-ui plugin\",\"className\":\"io.jans.ca.plugin.adminui.rest.ApiApplication\"},{\"name\":\"fido2\",\"description\":\"fido2 plugin\",\"className\":\"io.jans.configapi.plugin.fido2.rest.ApiApplication\"},{\"name\":\"scim\",\"description\":\"scim plugin\",\"className\":\"io.jans.configapi.plugin.scim.rest.ApiApplication\"},{\"name\":\"user-management\",\"description\":\"user-management plugin\",\"className\":\"io.jans.configapi.plugin.mgt.rest.ApiApplication\"}] List of configured plugin. Two options to make effect any manual changes done to the configuration # Restart jans-config-api Increment the jansRevision property of the configuration without restarting the application. The timer job will detect the change and fetch the latest configuration from the DB. Locating Config API configuration in the Persistence Layer # While it is not recommended that an administrator directly edits a configuration at the persistence layer, it may be useful information for a developer. MySQL # erDiagram jansAppConf { string doc_id PK \"\" string ou \"jans-config-api\" string jansConfDyn \"json configuration for the app\" } Important attributes # OAuth authorization # configOauthEnabled property can be used to enable or disable the oAuth2 authorization. By default, it is set to true. \"configOauthEnabled\" : true Api protection # apiProtectionType property states the protocol used for API authorization. The currently supported value is oauth2 . \"apiProtectionType\" : \"oauth2\" Api protection auth server # apiApprovedIssuer property enables to set more than one authorization servers. By default, the current auth-server is set. You can add more servers separated by commas. apiApprovedIssuer \": [\" https : //<jans.auth.server>,https://<gluu.server>,https://<anyAuth.server>\"] Logging level # loggingLevel property can be used to change the logging level to the desired values (TRACE, DEBUG, INFO, WARN, ERROR) . By default, the level is set to INFO ```javascript \"loggingLevel\":\"DEBUG\", ``` Scopes other than the one defined by config-api # Config API endpoints are oAuth2 protected. These scopes are created during installation. However, few endpoints require scopes defined by other modules like auth-server. A list of these scopes is maintained in the configuration in order to avoid the creation of these scopes during Config API start-up. exclusiveAuthScopes property can be used to change the logging level to the desired value (TRACE, DEBUG, INFO, WARN, ERROR) . By default, the level is set to INFO \"exclusiveAuthScopes\" : [ \"jans_stat\" , \"https://jans.io/scim/users.read\" , \"https://jans.io/scim/users.write\" ], User - Mandatory and exclusion attributes # MandatoryAttributes # userMandatoryAttributes can be used to define mandatory attributes for User while creating and updating. \"userMandatoryAttributes\" : [ \"mail\" , \"displayName\" , \"jansStatus\" , \"userPassword\" , \"givenName\" ], Exclusion attributes # userExclusionAttributes can be used to define User attributes that are not to be returned in the API response. More attributes that are to be skipped in response can be added to the list. \"userExclusionAttributes\" : [ \"userPassword\" ], Agama flow configuration # agamaConfiguration stores Agama-related configuration used in Agama related endpoints. mandatoryAttributes list defines the required attributes for Agama flow creation and update. optionalAttributes list specifies the optional attributes. \"agamaConfiguration\" : { \"mandatoryAttributes\" : [ \"qname\" , \"source\" ], \"optionalAttributes\" : [ \"serialVersionUID\" , \"enabled\" ] } Using Text-based UI # You can start TUI using the command below: Command jans tui Navigate to Config API section where administrators can update Config-API configurations in six sub-tabs, namely Main , Agama , Plugins , Asset Management , Audit Log Conf , Data Format Conversion Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Config-API Configuration. Endpoint details are published in the Swagger document , see endpoint /api/v1/api-config", "title": "Settings"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#janssen-config-api-configuration", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Janssen Config-API Configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the Config-API Configuration using the command line. To get the details of Janssen command line operations relevant to Config-API Configuration, you can check the operations under ConfigurationConfigApi task using the command below: Command jans tui --info ConfigurationConfigApi It will show the details of the available operation-ids for Config-API. Sample Output Operation ID: get-config-api-properties Description: Gets config-api configuration properties. Operation ID: patch-config-api-properties Description: Partially modifies config-api Configuration properties. Schema: Array of JsonPatch To get sample schema type jans tui --schema-sample <schema>, for example jans tui --schema-sample JsonPatch", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#get-the-current-config-api-configuration", "text": "Configuration for Config-API is a set of key-value pairs, called properties. When we retrieve the configuration, these properties and their current values are returned as a JSON document. To get the properties of Janssen Config-API Configuration, run the command below: Command jans tui --operation-id = get-config-api-properties It will return the result as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 { \"serviceName\" : \"jans-config-api\" , \"configOauthEnabled\" : true , \"disableLoggerTimer\" : false , \"disableAuditLogger\" : false , \"customAttributeValidationEnabled\" : true , \"acrValidationEnabled\" : true , \"apiApprovedIssuer\" : [ \"https://example.jans.io\" ], \"apiProtectionType\" : \"oauth2\" , \"apiClientId\" : \"1800.b62cb614-a09d-4163-a6bc-32e38a51c4d2\" , \"apiClientPassword\" : \"CN8ggRUhMkw9K0ocQ+LXbA==\" , \"endpointInjectionEnabled\" : false , \"authIssuerUrl\" : \"https://example.jans.io\" , \"authOpenidConfigurationUrl\" : \"https://example.jans.io/.well-known/openid-configuration\" , \"authOpenidIntrospectionUrl\" : \"https://example.jans.io/jans-auth/restv1/introspection\" , \"authOpenidTokenUrl\" : \"https://example.jans.io/jans-auth/restv1/token\" , \"authOpenidRevokeUrl\" : \"https://example.jans.io/jans-auth/restv1/revoke\" , \"exclusiveAuthScopes\" : [ \"jans_stat\" , \"https://jans.io/scim/users.read\" , \"https://jans.io/scim/users.write\" ], \"corsConfigurationFilters\" : [ { \"filterName\" : \"CorsFilter\" , \"corsEnabled\" : true , \"corsAllowedOrigins\" : \"*\" , \"corsAllowedMethods\" : \"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\" , \"corsSupportCredentials\" : true , \"corsLoggingEnabled\" : false , \"corsPreflightMaxAge\" : 1800 , \"corsRequestDecorate\" : true } ], \"loggingLevel\" : \"INFO\" , \"loggingLayout\" : \"text\" , \"disableJdkLogger\" : true , \"maxCount\" : 200 , \"acrExclusionList\" : [ \"simple_password_auth\" ], \"userExclusionAttributes\" : [ \"userPassword\" ], \"userMandatoryAttributes\" : [ \"mail\" , \"displayName\" , \"status\" , \"userPassword\" , \"givenName\" ], \"agamaConfiguration\" : { \"mandatoryAttributes\" : [ \"qname\" , \"source\" ], \"optionalAttributes\" : [ \"serialVersionUID\" , \"enabled\" ] }, \"auditLogConf\" : { \"enabled\" : true , \"headerAttributes\" : [ \"User-inum\" ] }, \"dataFormatConversionConf\" : { \"enabled\" : true , \"ignoreHttpMethod\" : [ \"@jakarta.ws.rs.GET()\" ] }, \"plugins\" : [ { \"name\" : \"admin\" , \"description\" : \"admin-ui plugin\" , \"className\" : \"io.jans.ca.plugin.adminui.rest.ApiApplication\" }, { \"name\" : \"fido2\" , \"description\" : \"fido2 plugin\" , \"className\" : \"io.jans.configapi.plugin.fido2.rest.ApiApplication\" }, { \"name\" : \"scim\" , \"description\" : \"scim plugin\" , \"className\" : \"io.jans.configapi.plugin.scim.rest.ApiApplication\" }, { \"name\" : \"user-management\" , \"description\" : \"user-management plugin\" , \"className\" : \"io.jans.configapi.plugin.mgt.rest.ApiApplication\" }, { \"name\" : \"jans-link\" , \"description\" : \"jans-link plugin\" , \"className\" : \"io.jans.configapi.plugin.link.rest.ApiApplication\" }, { \"name\" : \"saml\" , \"description\" : \"saml plugin\" , \"className\" : \"io.jans.configapi.plugin.saml.rest.ApiApplication\" }, { \"name\" : \"kc-link\" , \"description\" : \"kc-link plugin\" , \"className\" : \"io.jans.configapi.plugin.kc.link.rest.ApiApplication\" }, { \"name\" : \"lock\" , \"description\" : \"lock plugin\" , \"className\" : \"io.jans.configapi.plugin.lock.rest.ApiApplication\" } ], \"assetMgtConfiguration\" : { \"assetMgtEnabled\" : true , \"assetServerUploadEnabled\" : true , \"fileExtensionValidationEnabled\" : true , \"moduleNameValidationEnabled\" : true , \"assetBaseDirectory\" : \"/opt/jans/jetty/%s/custom\" , \"jansServiceModule\" : [ \"jans-auth\" , \"jans-config-api\" , \"jans-fido2\" , \"jans-scim\" ], \"assetDirMapping\" : [ { \"directory\" : \"i18n\" , \"type\" : [ \"properties\" ], \"description\" : \"Resource bundle file.\" }, { \"directory\" : \"libs\" , \"type\" : [ \"jar\" /op t /ja ns /ja ns - cli/co nf ig - cli.py -- i nf o Co nf igura t io n Co nf igApi ], \"description\" : \"java archive library.\" }, { \"directory\" : \"pages\" , \"type\" : [ \"xhtml\" ], \"description\" : \"Web pages.\" }, { \"directory\" : \"static\" , \"type\" : [ \"js\" , \"css\" , \"png\" , \"gif\" , \"jpg\" , \"jpeg\" ], \"description\" : \"Static resources like Java-script, style-sheet and images.\" } ] } }", "title": "Get The Current Config-API Configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#update-config-api-configuration-properties", "text": "To update the configuration, we will use JSON patch schema as shown below. Let's say we want to stop the file extension validation done by config-api's asset management module. This can be done by setting the fileExtensionValidationEnabled property to false . To do that, write a text file ( config-api-assetmgt-patch.json ) with the content that follows the JSON patch schema. config-api-assetmgt-patch.json 1 2 3 4 5 6 7 [ { \"op\" : \"replace\" , \"path\" : \"/assetMgtConfiguration/fileExtensionValidationEnabled\" , \"value\" : false } ] Now, execute the following command to apply this patch: Command jans tui \\ --operation-id = patch-config-api-properties --data ./config-api-assetmgt-patch.json Upon successful execution of the update, the Janssen Server responds with updated configuration.", "title": "Update Config-API Configuration Properties"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#updating-multi-valued-property", "text": "Let's say we want to update the configuration property userMandatoryAttributes . This property's value is a list of attributes. We want to remove an attribute from the list. For this, we will have to create a JSON patch file that contains the new list and then run a command to push the update to the Janssen Server. Let's do this step-by-step: Get the current value list for userMandatoryAttributes property using steps mentioned in Get the current configuration section Using the current list of values as a starting point, create a JSON patch file config-api-patch.json as below. Update the list as desired by adding or removing items from the list: Sample Contents 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [ { \"op\" : \"replace\" , \"path\" : \"/userMandatoryAttributes\" , \"value\" : [ \"mail\" , \"displayName\" , \"status\" , \"userPassword\" , \"givenName\" , \"gender\" ] } ] Now, execute the following command to apply this patch: Command jans tui \\ --operation-id = patch-config-api-properties --data ./config-api-patch.json", "title": "Updating multi-valued property"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#config-api-configuration-parameters", "text": "The table below outlines the key configuration parameters for the Jans Config API. It details settings for OAuth2, security, endpoints, logging, and plugin management. Field named Example Description configOauthEnabled true property can be used to enable or disable the oAuth2 authorization. By default, it is set to true. apiApprovedIssuer [\"https:// ,https:// ,https:// \"] Enables to set more than one authorization servers. By default, the current auth-server is set. You can add more servers separated by commas. apiProtectionType oauth2 Currently support mechanism is OAuth 2.0 tokens. apiClientId 1800.52eb1bed-ab5c-4ba6-b87e-90aad26058d0 Jans Config API Client. apiClientPassword lwI/8mcMkF63mvueYTZ0mQ== Encrypted secret of Jans Config API Client endpointInjectionEnabled false To be used if the endpoint needs to be injected. authIssuerUrl https://my-jans-server.jans.io URL of underlying auth-server. authOpenidConfigurationUrl https://my-jans-server.jans.io/.well-known/openid-configuration Metadata URL of the authorization server. authOpenidIntrospectionUrl https://my-jans-server.jans.io/jans-auth/restv1/introspection Authorization server endpoint to check the state of an OAuth 2.0 token and to determine meta-information about the token. authOpenidTokenUrl https://my-jans-server.jans.io/jans-auth/restv1/token Authorization server endpoint to obtain an Access Token, an ID Token, and optionally a Refresh Token. authOpenidRevokeUrl https://my-jans-server.jans.io/jans-auth/restv1/token Authorization server endpoint to notify an OAuth 2.0 authorization server that a previously obtained refresh or access token is no longer needed, allowing the server to clean up security credentials. smallryeHealthRootPath /health-check Deprecated param for health-check exclusiveAuthScopes [\"jans_stat\",\"https://jans.io/scim/users.read\",\"https://jans.io/scim/users.write\"] Scopes that are only validated against the underlying Jansen Authorization server. corsConfigurationFilters [{\"filterName\":\"CorsFilter\",\"corsEnabled\":true,\"corsAllowedOrigins\":\"*\",\"corsAllowedMethods\":\"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\",\"corsAllowedHeaders\":\"\",\"corsExposedHeaders\":\"\",\"corsSupportCredentials\":true,\"corsLoggingEnabled\":false,\"corsPreflightMaxAge\":1800,\"corsRequestDecorate\":true}] This list specifies the CORS configuration filters. exclusiveAuthScopes [\"jans_stat\",\"https://jans.io/scim/users.read\",\"https://jans.io/scim/users.write\"] Scopes that are only validated against the underlying Jansen Authorization server. loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for Config API. loggingLayout \"text\" Contents of logs as plain text format. externalLoggerConfiguration Path to external log4j2 logging configuration. disableJdkLogger true Boolean to disable JDK loggers. maxCount 200 To be used to set maximum records returned in response. userExclusionAttributes [\"userPassword\"] List of attributes to be excluded in User response. userMandatoryAttributes [\"mail\",\"displayName\",\"jansStatus\",\"userPassword\",\"givenName\"] List of attributes mandatory for creating a User. agamaConfiguration {\"mandatoryAttributes\":[\"qname\",\"source\"],\"optionalAttributes\":[\"serialVersionUID\",\"enabled\"]} Configuration parameters like mandatory, optional, etc for agama flow. auditLogConf {\"enabled\":true,\"ignoreHttpMethod\":[],\"headerAttributes\":[\"User-inum\"]} Audit Log configuration. dataFormatConversionConf {\"enabled\":true,\"ignoreHttpMethod\":[\"@jakarta.ws.rs.GET()\"]} DB specific data format conversion configuration for Date field. plugins [{\"name\":\"admin\",\"description\":\"admin-ui plugin\",\"className\":\"io.jans.ca.plugin.adminui.rest.ApiApplication\"},{\"name\":\"fido2\",\"description\":\"fido2 plugin\",\"className\":\"io.jans.configapi.plugin.fido2.rest.ApiApplication\"},{\"name\":\"scim\",\"description\":\"scim plugin\",\"className\":\"io.jans.configapi.plugin.scim.rest.ApiApplication\"},{\"name\":\"user-management\",\"description\":\"user-management plugin\",\"className\":\"io.jans.configapi.plugin.mgt.rest.ApiApplication\"}] List of configured plugin.", "title": "Config API Configuration Parameters:"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#two-options-to-make-effect-any-manual-changes-done-to-the-configuration", "text": "Restart jans-config-api Increment the jansRevision property of the configuration without restarting the application. The timer job will detect the change and fetch the latest configuration from the DB.", "title": "Two options to make effect any manual changes done to the configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#locating-config-api-configuration-in-the-persistence-layer", "text": "While it is not recommended that an administrator directly edits a configuration at the persistence layer, it may be useful information for a developer.", "title": "Locating Config API configuration in the Persistence Layer"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#mysql", "text": "erDiagram jansAppConf { string doc_id PK \"\" string ou \"jans-config-api\" string jansConfDyn \"json configuration for the app\" }", "title": "MySQL"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#important-attributes", "text": "", "title": "Important attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#oauth-authorization", "text": "configOauthEnabled property can be used to enable or disable the oAuth2 authorization. By default, it is set to true. \"configOauthEnabled\" : true", "title": "OAuth authorization"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#api-protection", "text": "apiProtectionType property states the protocol used for API authorization. The currently supported value is oauth2 . \"apiProtectionType\" : \"oauth2\"", "title": "Api protection"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#api-protection-auth-server", "text": "apiApprovedIssuer property enables to set more than one authorization servers. By default, the current auth-server is set. You can add more servers separated by commas. apiApprovedIssuer \": [\" https : //<jans.auth.server>,https://<gluu.server>,https://<anyAuth.server>\"]", "title": "Api protection auth server"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#logging-level", "text": "loggingLevel property can be used to change the logging level to the desired values (TRACE, DEBUG, INFO, WARN, ERROR) . By default, the level is set to INFO ```javascript \"loggingLevel\":\"DEBUG\", ```", "title": "Logging level"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#scopes-other-than-the-one-defined-by-config-api", "text": "Config API endpoints are oAuth2 protected. These scopes are created during installation. However, few endpoints require scopes defined by other modules like auth-server. A list of these scopes is maintained in the configuration in order to avoid the creation of these scopes during Config API start-up. exclusiveAuthScopes property can be used to change the logging level to the desired value (TRACE, DEBUG, INFO, WARN, ERROR) . By default, the level is set to INFO \"exclusiveAuthScopes\" : [ \"jans_stat\" , \"https://jans.io/scim/users.read\" , \"https://jans.io/scim/users.write\" ],", "title": "Scopes other than the one defined by config-api"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#user-mandatory-and-exclusion-attributes", "text": "", "title": "User - Mandatory and exclusion attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#mandatoryattributes", "text": "userMandatoryAttributes can be used to define mandatory attributes for User while creating and updating. \"userMandatoryAttributes\" : [ \"mail\" , \"displayName\" , \"jansStatus\" , \"userPassword\" , \"givenName\" ],", "title": "MandatoryAttributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#exclusion-attributes", "text": "userExclusionAttributes can be used to define User attributes that are not to be returned in the API response. More attributes that are to be skipped in response can be added to the list. \"userExclusionAttributes\" : [ \"userPassword\" ],", "title": "Exclusion attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#agama-flow-configuration", "text": "agamaConfiguration stores Agama-related configuration used in Agama related endpoints. mandatoryAttributes list defines the required attributes for Agama flow creation and update. optionalAttributes list specifies the optional attributes. \"agamaConfiguration\" : { \"mandatoryAttributes\" : [ \"qname\" , \"source\" ], \"optionalAttributes\" : [ \"serialVersionUID\" , \"enabled\" ] }", "title": "Agama flow configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#using-text-based-ui", "text": "You can start TUI using the command below: Command jans tui Navigate to Config API section where administrators can update Config-API configurations in six sub-tabs, namely Main , Agama , Plugins , Asset Management , Audit Log Conf , Data Format Conversion", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Config-API Configuration. Endpoint details are published in the Swagger document , see endpoint /api/v1/api-config", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/", "tags": ["administration", "tools", "config-api", "logs"], "text": "Config-api logs: # Two types of logs generated by config-api, application logs and audit log . - Application log contains application functionality logs - Audit log contains information of each request received. Logging configuration # Log configuration is stored in DB along with the config-application other configuration javascript { \"configOauthEnabled\": true, \"apiApprovedIssuer\": [\"https://jans.server2\"], \"apiProtectionType\": \"oauth2\", \"apiClientId\": \"1800.c9c0b756-a1fc-4013-9feb-64d531ac2dc1\", \"apiClientPassword\": \"X9q7cAemqyD9LaS1c5YzIA==\", \"endpointInjectionEnabled\": false, \"authIssuerUrl\": \"https://jans.server2\", \"authOpenidConfigurationUrl\": \"https://jans.server2/.well-known/openid-configuration\", \"authOpenidIntrospectionUrl\": \"https://jans.server2/jans-auth/restv1/introspection\", \"authOpenidTokenUrl\": \"https://jans.server2/jans-auth/restv1/token\", \"authOpenidRevokeUrl\": \"https://jans.server2/jans-auth/restv1/revoke\", \"smallryeHealthRootPath\": \"/health-check\", \"disableJdkLogger\":true, \"loggingLevel\":\"INFO\", \"loggingLayout\":\"text\", \"externalLoggerConfiguration\":\"\", \"exclusiveAuthScopes\": [ \"jans_stat\", \"https://jans.io/scim/users.read\", \"https://jans.io/scim/users.write\" ], \"corsConfigurationFilters\": [ { \"filterName\": \"CorsFilter\", \"corsAllowedOrigins\": \"*\", \"corsAllowedMethods\": \"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\", \"corsAllowedHeaders\": \"\", \"corsExposedHeaders\": \"\", \"corsSupportCredentials\": true, \"corsLoggingEnabled\": false, \"corsPreflightMaxAge\": 1800, \"corsRequestDecorate\": true, \"corsEnabled\": true } ], \"userExclusionAttributes\": [ \"userPassword\" ], \"userMandatoryAttributes\": [ \"mail\", \"displayName\", \"jansStatus\", \"userPassword\", \"givenName\" ], \"agamaConfiguration\": { \"mandatoryAttributes\": [ \"qname\", \"source\" ], \"optionalAttributes\": [ \"serialVersionUID\", \"enabled\" ] }, \"auditLogConf\": { \"enabled\": true, \"ignoreHttpMethod\": [], \"headerAttributes\": [ \"User-inum\" ] }, \"dataFormatConversionConf\": { \"enabled\": true, \"ignoreHttpMethod\": [ \"@jakarta.ws.rs.GET()\" ] }, \"plugins\": [ { \"name\": \"admin\", \"description\": \"admin-ui plugin\", \"className\": \"io.jans.ca.plugin.adminui.rest.ApiApplication\" }, { \"name\": \"fido2\", \"description\": \"fido2 plugin\", \"className\": \"io.jans.configapi.plugin.fido2.rest.ApiApplication\" }, { \"name\": \"scim\", \"description\": \"scim plugin\", \"className\": \"io.jans.configapi.plugin.scim.rest.ApiApplication\" }, { \"name\": \"user-management\", \"description\": \"user-management plugin\", \"className\": \"io.jans.configapi.plugin.mgt.rest.ApiApplication\" } ] } Audit log # Configuration # ... auditLogConf \": { \" enabled \": true, \" ignoreHttpMethod \": [], \" headerAttributes \": [ \" User - inum \" ] ... Field Description Example enabled Flag to enable and disable audit log true , default value is true, to enable audit logging ignoreHttpMethod HTTP methods for which audit is disabled @jakarta.ws.rs.GET(), @jakarta.ws.rs.PATCH(), @jakarta.ws.rs.PATCH(), etc headerAttributes List of HTTP header attributes whose value is to be logged User-inum File name and location on server # Log name: configapi-audit.log Log location: /opt/jans/jetty/jans-config-api/logs Application Logs # Config-api uses log4j to generate application execution logs for each endpoint invocation. These can be used to debug the application. Configuration # DB: ``javascript ... \"loggingLevel\":\"DEBUG\", \"loggingLayout\":\"text\" ... log4j file: https://github.com/JanssenProject/jans/blob/main/jans-config-api/server/src/main/resources/log4j2.xml DB configuration # Fetch configuration curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 3114e010-fd4d-4e62-b5e2-a51b7d6dd231\" - X GET https : //jans.server/jans-config-api/api/v1/api-config Patch configuration curl - X PATCH - k - H 'Content-Type: application/json-patch+json' - H 'Authorization:Bearer 3114e010-fd4d-4e62-b5e2-a51b7d6dd231' - i 'https://jans.server/jans-config-api/api/v1/api-config' -- data '[{\"op\": \"replace\", \"path\": \"/loggingLevel\", \"value\":\"ERROR\"}, {\"op\": \"replace\", \"path\": \"/loggingLayout\", \"value\":\"json\"}, {\"op\": \"replace\", \"path\": \"/auditLogConf/enabled\", \"value\":false} , {\"op\": \"replace\", \"path\": \"/auditLogConf/headerAttributes\", \"value\":[\"User-inum\",\"city\"]}]'", "title": "Logs"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#config-api-logs", "text": "Two types of logs generated by config-api, application logs and audit log . - Application log contains application functionality logs - Audit log contains information of each request received.", "title": "Config-api logs:"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#logging-configuration", "text": "Log configuration is stored in DB along with the config-application other configuration javascript { \"configOauthEnabled\": true, \"apiApprovedIssuer\": [\"https://jans.server2\"], \"apiProtectionType\": \"oauth2\", \"apiClientId\": \"1800.c9c0b756-a1fc-4013-9feb-64d531ac2dc1\", \"apiClientPassword\": \"X9q7cAemqyD9LaS1c5YzIA==\", \"endpointInjectionEnabled\": false, \"authIssuerUrl\": \"https://jans.server2\", \"authOpenidConfigurationUrl\": \"https://jans.server2/.well-known/openid-configuration\", \"authOpenidIntrospectionUrl\": \"https://jans.server2/jans-auth/restv1/introspection\", \"authOpenidTokenUrl\": \"https://jans.server2/jans-auth/restv1/token\", \"authOpenidRevokeUrl\": \"https://jans.server2/jans-auth/restv1/revoke\", \"smallryeHealthRootPath\": \"/health-check\", \"disableJdkLogger\":true, \"loggingLevel\":\"INFO\", \"loggingLayout\":\"text\", \"externalLoggerConfiguration\":\"\", \"exclusiveAuthScopes\": [ \"jans_stat\", \"https://jans.io/scim/users.read\", \"https://jans.io/scim/users.write\" ], \"corsConfigurationFilters\": [ { \"filterName\": \"CorsFilter\", \"corsAllowedOrigins\": \"*\", \"corsAllowedMethods\": \"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\", \"corsAllowedHeaders\": \"\", \"corsExposedHeaders\": \"\", \"corsSupportCredentials\": true, \"corsLoggingEnabled\": false, \"corsPreflightMaxAge\": 1800, \"corsRequestDecorate\": true, \"corsEnabled\": true } ], \"userExclusionAttributes\": [ \"userPassword\" ], \"userMandatoryAttributes\": [ \"mail\", \"displayName\", \"jansStatus\", \"userPassword\", \"givenName\" ], \"agamaConfiguration\": { \"mandatoryAttributes\": [ \"qname\", \"source\" ], \"optionalAttributes\": [ \"serialVersionUID\", \"enabled\" ] }, \"auditLogConf\": { \"enabled\": true, \"ignoreHttpMethod\": [], \"headerAttributes\": [ \"User-inum\" ] }, \"dataFormatConversionConf\": { \"enabled\": true, \"ignoreHttpMethod\": [ \"@jakarta.ws.rs.GET()\" ] }, \"plugins\": [ { \"name\": \"admin\", \"description\": \"admin-ui plugin\", \"className\": \"io.jans.ca.plugin.adminui.rest.ApiApplication\" }, { \"name\": \"fido2\", \"description\": \"fido2 plugin\", \"className\": \"io.jans.configapi.plugin.fido2.rest.ApiApplication\" }, { \"name\": \"scim\", \"description\": \"scim plugin\", \"className\": \"io.jans.configapi.plugin.scim.rest.ApiApplication\" }, { \"name\": \"user-management\", \"description\": \"user-management plugin\", \"className\": \"io.jans.configapi.plugin.mgt.rest.ApiApplication\" } ] }", "title": "Logging configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#audit-log", "text": "", "title": "Audit log"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#configuration", "text": "... auditLogConf \": { \" enabled \": true, \" ignoreHttpMethod \": [], \" headerAttributes \": [ \" User - inum \" ] ... Field Description Example enabled Flag to enable and disable audit log true , default value is true, to enable audit logging ignoreHttpMethod HTTP methods for which audit is disabled @jakarta.ws.rs.GET(), @jakarta.ws.rs.PATCH(), @jakarta.ws.rs.PATCH(), etc headerAttributes List of HTTP header attributes whose value is to be logged User-inum", "title": "Configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#file-name-and-location-on-server", "text": "Log name: configapi-audit.log Log location: /opt/jans/jetty/jans-config-api/logs", "title": "File name and location on server"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#application-logs", "text": "Config-api uses log4j to generate application execution logs for each endpoint invocation. These can be used to debug the application.", "title": "Application Logs"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#configuration_1", "text": "DB: ``javascript ... \"loggingLevel\":\"DEBUG\", \"loggingLayout\":\"text\" ... log4j file: https://github.com/JanssenProject/jans/blob/main/jans-config-api/server/src/main/resources/log4j2.xml", "title": "Configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#db-configuration", "text": "Fetch configuration curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 3114e010-fd4d-4e62-b5e2-a51b7d6dd231\" - X GET https : //jans.server/jans-config-api/api/v1/api-config Patch configuration curl - X PATCH - k - H 'Content-Type: application/json-patch+json' - H 'Authorization:Bearer 3114e010-fd4d-4e62-b5e2-a51b7d6dd231' - i 'https://jans.server/jans-config-api/api/v1/api-config' -- data '[{\"op\": \"replace\", \"path\": \"/loggingLevel\", \"value\":\"ERROR\"}, {\"op\": \"replace\", \"path\": \"/loggingLayout\", \"value\":\"json\"}, {\"op\": \"replace\", \"path\": \"/auditLogConf/enabled\", \"value\":false} , {\"op\": \"replace\", \"path\": \"/auditLogConf/headerAttributes\", \"value\":[\"User-inum\",\"city\"]}]'", "title": "DB configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/monitoring/", "tags": ["administration", "tools", "config-api", "monitoring"], "text": "Health - Check endpoints # /api/v1/health - Returns application consolidated health status - liveness and readiness /api/v1/health/live - Returns application liveness status /api/v1/health/ready -Returns application readiness status /api/v1/health/server-stat - Returns application server status and stats metric like memoryfree , uptime , free_disk_space , etc Sample health response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n [ { \"name\" : \"jans-config-api liveness\" , \"status\" : \"UP\" }, { \"name\" : \"jans-config-api readiness\" , \"status\" : \"UP\" } ] Sample liveness response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"name\" : \"jans-config-api liveness\" , \"status\" : \"UP\" } Sample readiness response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"name\" : \"jans-config-api readiness\" , \"status\" : \"UP\" } Sample server status response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"dbType\" : \"MySQL\" , \"lastUpdate\" : \"2023-03-16T03:17:44\" , \"facterData\" : { \"memoryfree\" : \"7.1%\" , \"swapfree\" : \"60.1%\" , \"hostname\" : \"jans.server2\" , \"ipaddress\" : \"192.168.0.102\" , \"uptime\" : \"3:03\" , \"free_disk_space\" : \"65.0%\" , \"load_average\" : \"0.77\" } } Application logs # Application log can be verified if application is started properly. Refer here for more details.", "title": "Monitoring"}, {"location": "janssen-server/config-guide/config-tools/config-api/monitoring/#health-check-endpoints", "text": "/api/v1/health - Returns application consolidated health status - liveness and readiness /api/v1/health/live - Returns application liveness status /api/v1/health/ready -Returns application readiness status /api/v1/health/server-stat - Returns application server status and stats metric like memoryfree , uptime , free_disk_space , etc Sample health response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n [ { \"name\" : \"jans-config-api liveness\" , \"status\" : \"UP\" }, { \"name\" : \"jans-config-api readiness\" , \"status\" : \"UP\" } ] Sample liveness response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"name\" : \"jans-config-api liveness\" , \"status\" : \"UP\" } Sample readiness response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"name\" : \"jans-config-api readiness\" , \"status\" : \"UP\" } Sample server status response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"dbType\" : \"MySQL\" , \"lastUpdate\" : \"2023-03-16T03:17:44\" , \"facterData\" : { \"memoryfree\" : \"7.1%\" , \"swapfree\" : \"60.1%\" , \"hostname\" : \"jans.server2\" , \"ipaddress\" : \"192.168.0.102\" , \"uptime\" : \"3:03\" , \"free_disk_space\" : \"65.0%\" , \"load_average\" : \"0.77\" } }", "title": "Health - Check endpoints"}, {"location": "janssen-server/config-guide/config-tools/config-api/monitoring/#application-logs", "text": "Application log can be verified if application is started properly. Refer here for more details.", "title": "Application logs"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/", "tags": ["administration", "tools", "config-api", "plugins"], "text": "Overview # Jans Config Api is a REST application that is developed using Weld 4.x (JSR-365) and JAX-RS. Its endpoint can be used to manage configuration and other properties of Jans Auth Server . Jans Config API Plugins # Jans Config API follow a flexible plugin architecture in which the new features can be added using extensions called plugins without altering the application itself. In this section, we will discuss the steps to develop and add plugins in Jans Config API. The plugin architecture implemented in Jans Config API allows the deployer to add/remove new rest APIs (plugin) without changing the core application. A plugin contains one or more Rest API(s) packaged in a Java ARchive (jar file). It is added to Jans Config API by adding the plugin jar file path in the external extraClasspath of the jetty context file. Pre-requisites # The plugin developer should have an understanding of the following: Jakarta EE Platform : The plugin developer should know the Java programming language Weld : Weld is the reference implementation of CDI: Contexts and Dependency Injection for the Java EE Platform JAX-RS : JAX-RS for creating RESTful web services. Maven : Maven to build projects and manage dependencies. Web application container (Jetty) Sample plugin # To help bootstrap the plugin development, we have put together a sample plugin. Clone the Jans Config API project from here . Navigate under the plugins/sample folder. This folder contains the sample plugins for reference. helloworld folder for example contains the code for a basic plugin with GET endpoint sending Hello World! string response. Take the time to explore helloworld which is a minimalistic plugin that showcases very basic aspects of plugin development. Exploring Hello World Plugin # beans.xml # The resources/META-INF/beans.xml is the CDI deployment descriptor required in bean archive . Deployment descriptor helps WELD to explore beans, interceptors, decorators, etc in the bean archive . Refer to the WELD docs to learn more about deployment descriptors. HelloWorldExtension.java # A CDI portable extension is a mechanism by which we can implement additional functionalities on top of the CDI container. In this sample plugin, we have created an extension called HelloWorldExtension.java , implementing jakarta.enterprise.inject.spi.Extension . An extension can observe lifecycle events and also can modify the container\u2019s metamodel. Please refer to the WELD documentation for details. We need to register our extension as a service provider by creating a file named resources/META-INF/services/jakarta.enterprise.inject.spi.Extension (as shown below). com.spl.plugin.helloworld.ext.HelloWorldExtension HelloWorldApplication.java # The com.spl.plugin.helloworld.rest.HelloWorldApplication.java class is annotated with the @ApplicationPath annotation which identifies the application path that serves as the base URI for all resources of the plugin and is used to register JAX-RS resources and providers. HelloWorldResource.java # This is a sample JAX-RS resource with an endpoint returning Hello World! string as http response. Plugin Deployment # Jans Config API is offered as one of the several components of the Jans Auth Server. A plugin jar can be added to Jans Config API by following below steps. On an installed Jans Auth Server with Jans Config API (as component) copy plugin jar to /opt/jans/jetty/jans-config-api/custom/libs location. Add the location of plugin jar inside tag with name extraClasspath (multiple plugins can be added comma separated) of /opt/jans/jetty/jans-config-api/webapps/jans-config-api.xml file. <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"http://www.eclipse.org/jetty/configure_9_0.dtd\"> <Configure class=\"org.eclipse.jetty.webapp.WebAppContext\"> <Set name=\"contextPath\">/jans-config-api</Set> <Set name=\"war\"> <Property name=\"jetty.webapps\" default=\".\" />/jans-config-api.war </Set> <Set name=\"extractWAR\">true</Set> <Set name=\"extraClasspath\">/opt/jans/jetty/jans-config-api/custom/libs/helloWorldjar</Set> </Configure> Restart jans-config-api service. systemctl restart jans-config-api.service", "title": "Plugins"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#overview", "text": "Jans Config Api is a REST application that is developed using Weld 4.x (JSR-365) and JAX-RS. Its endpoint can be used to manage configuration and other properties of Jans Auth Server .", "title": "Overview"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#jans-config-api-plugins", "text": "Jans Config API follow a flexible plugin architecture in which the new features can be added using extensions called plugins without altering the application itself. In this section, we will discuss the steps to develop and add plugins in Jans Config API. The plugin architecture implemented in Jans Config API allows the deployer to add/remove new rest APIs (plugin) without changing the core application. A plugin contains one or more Rest API(s) packaged in a Java ARchive (jar file). It is added to Jans Config API by adding the plugin jar file path in the external extraClasspath of the jetty context file.", "title": "Jans Config API Plugins"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#pre-requisites", "text": "The plugin developer should have an understanding of the following: Jakarta EE Platform : The plugin developer should know the Java programming language Weld : Weld is the reference implementation of CDI: Contexts and Dependency Injection for the Java EE Platform JAX-RS : JAX-RS for creating RESTful web services. Maven : Maven to build projects and manage dependencies. Web application container (Jetty)", "title": "Pre-requisites"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#sample-plugin", "text": "To help bootstrap the plugin development, we have put together a sample plugin. Clone the Jans Config API project from here . Navigate under the plugins/sample folder. This folder contains the sample plugins for reference. helloworld folder for example contains the code for a basic plugin with GET endpoint sending Hello World! string response. Take the time to explore helloworld which is a minimalistic plugin that showcases very basic aspects of plugin development.", "title": "Sample plugin"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#exploring-hello-world-plugin", "text": "", "title": "Exploring Hello World Plugin"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#beansxml", "text": "The resources/META-INF/beans.xml is the CDI deployment descriptor required in bean archive . Deployment descriptor helps WELD to explore beans, interceptors, decorators, etc in the bean archive . Refer to the WELD docs to learn more about deployment descriptors.", "title": "beans.xml"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#helloworldextensionjava", "text": "A CDI portable extension is a mechanism by which we can implement additional functionalities on top of the CDI container. In this sample plugin, we have created an extension called HelloWorldExtension.java , implementing jakarta.enterprise.inject.spi.Extension . An extension can observe lifecycle events and also can modify the container\u2019s metamodel. Please refer to the WELD documentation for details. We need to register our extension as a service provider by creating a file named resources/META-INF/services/jakarta.enterprise.inject.spi.Extension (as shown below). com.spl.plugin.helloworld.ext.HelloWorldExtension", "title": "HelloWorldExtension.java"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#helloworldapplicationjava", "text": "The com.spl.plugin.helloworld.rest.HelloWorldApplication.java class is annotated with the @ApplicationPath annotation which identifies the application path that serves as the base URI for all resources of the plugin and is used to register JAX-RS resources and providers.", "title": "HelloWorldApplication.java"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#helloworldresourcejava", "text": "This is a sample JAX-RS resource with an endpoint returning Hello World! string as http response.", "title": "HelloWorldResource.java"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#plugin-deployment", "text": "Jans Config API is offered as one of the several components of the Jans Auth Server. A plugin jar can be added to Jans Config API by following below steps. On an installed Jans Auth Server with Jans Config API (as component) copy plugin jar to /opt/jans/jetty/jans-config-api/custom/libs location. Add the location of plugin jar inside tag with name extraClasspath (multiple plugins can be added comma separated) of /opt/jans/jetty/jans-config-api/webapps/jans-config-api.xml file. <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"http://www.eclipse.org/jetty/configure_9_0.dtd\"> <Configure class=\"org.eclipse.jetty.webapp.WebAppContext\"> <Set name=\"contextPath\">/jans-config-api</Set> <Set name=\"war\"> <Property name=\"jetty.webapps\" default=\".\" />/jans-config-api.war </Set> <Set name=\"extractWAR\">true</Set> <Set name=\"extraClasspath\">/opt/jans/jetty/jans-config-api/custom/libs/helloWorldjar</Set> </Configure> Restart jans-config-api service. systemctl restart jans-config-api.service", "title": "Plugin Deployment"}, {"location": "janssen-server/config-guide/config-tools/config-api/security/", "tags": ["administration", "tools", "config-api", "security"], "text": "Security # Disclosing vulnerabilities # If you think you found a security vulnerability, please refrain from posting it publicly on the forums, the chat, or GitHub. Instead, email us on security@jans.io. Refer to Janssen Security Policy", "title": "Security"}, {"location": "janssen-server/config-guide/config-tools/config-api/security/#security", "text": "", "title": "Security"}, {"location": "janssen-server/config-guide/config-tools/config-api/security/#disclosing-vulnerabilities", "text": "If you think you found a security vulnerability, please refrain from posting it publicly on the forums, the chat, or GitHub. Instead, email us on security@jans.io. Refer to Janssen Security Policy", "title": "Disclosing vulnerabilities"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/", "tags": ["administration", "configuration", "tools", "tui", "text base UI", "navigation"], "text": "TUI Navigation Guide # General Structure: # The TUI consists of many tabs, each tab may or may not contain nested tabs. The TUI consists of one main navigation bar which contains (Auth Server, FIDO, SCIM, Scripts, Users, and Jans CLI) The tab currently in focus is highlighted at the top. ex: Note: in the image provided below SCIM is focused We can notice that there is a cursor mark on the first of the Navigation bar line, which indicates that the focus currently in this widget General Purpose shortcuts # f1 : Open help dialog (currently, help dialog is static, in the near future it will dynamically change according to the current position inside the TUI ) ESC : Close any dialog or even nested dialog Ctrl+c (Terminate) : Terminate the program (SIGINT) Navigation Shortcuts # General Navigation shortcuts # tab (Next): focus on the next field or widget. shift + tab (Previous): focus on the previous field or widget PageUp (Next tab): Jump to the next tab in dialogs (ex: Client dialog) Note: the focus must be inside the current tab In the Gif provided, the focus was inside the tab itself before we can press the PageUp key * If the focus is on the tab name itself, we can navigate to other tabs by the Up key and Down key PageDown (Previous tab) : Jump to the previous tab in dialogs (ex: Client dialog) Note: the focus must be inside the current tab In the Gif provided, the focus was inside the tab itself before we can press the PageDown key If the focus is on the tab name itself, we can navigate to other tabs by the Up key and Down key Main tabs Navigation shortcuts # Alt + key You can navigate to any tab inside the TUI by using the Alt key followed by a certain letter from the tab you want to navigate too Note: the colored character inside each Tab name is the specified letter for the navigation. you can't navigate from a tab in the main top navigation bar to a nested navigation bar inside another tab, you must navigate to it first. examples on the navigation letters for the main navigation bar: Auth Server -> A FIDO -> F SCIM -> C Scripts -> r Users -> U Jans CLI -> J Custom widget shortcuts # Note: * This section contains any widgets with special shortcuts and behavior Lists (Vertical Nav bar) # currently, we have about 6 List widgets Note: Any list widget can be navigated between its items by the Up key and Down key There are some shortcuts here that can be used in most but not all List widgets delete : can be used to delete a certain item d : can be used to view all the selected item data in the JSON format Enter : can be used to edit the current item ex: p : can be used to update user's password. Date Widgets # The date widget can be used to select a date and time. ex (Client Expiration Date) tab , shift + tab : can be used to navigate between date and time Up , Down , Right , and Left arrows: can be used to change the date and time Note: * in the date section, if you navigate to the right border and then pressed Right , the year will be increased. in the date section, if you navigate to the left border and then pressed Left , the year will be decreased. in the date section, if you navigate to the up border and then pressed Up , the month will be decreased. * in the date section, if you navigate to the down border and then pressed Down , the month will be increased. in the time section, you can navigate between hour, minute, and second by the Right key and the Left key. in the time section, you can increase the time (hour, minute, or second) by the Up key and the Down key. Label Widgets # The label widget is used with scopes to show certain items instead of a long one, it is similar to the list widget tab , shift + tab : can be used to navigate between the button and the labels Right key and Left key can be used to navigate between the labels d : can be used to view all the data of the selected label delete : can be used to delete a certain label Logout and Exit # Exit will close the TUI screen while logout will force re-authentication of TUI using device-code. Navigate to Jans TUI on upper right corner of the screen and hit enter.", "title": "Navigation Guide"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#tui-navigation-guide", "text": "", "title": "TUI Navigation Guide"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#general-structure", "text": "The TUI consists of many tabs, each tab may or may not contain nested tabs. The TUI consists of one main navigation bar which contains (Auth Server, FIDO, SCIM, Scripts, Users, and Jans CLI) The tab currently in focus is highlighted at the top. ex: Note: in the image provided below SCIM is focused We can notice that there is a cursor mark on the first of the Navigation bar line, which indicates that the focus currently in this widget", "title": "General Structure:"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#general-purpose-shortcuts", "text": "f1 : Open help dialog (currently, help dialog is static, in the near future it will dynamically change according to the current position inside the TUI ) ESC : Close any dialog or even nested dialog Ctrl+c (Terminate) : Terminate the program (SIGINT)", "title": "General Purpose shortcuts"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#navigation-shortcuts", "text": "", "title": "Navigation Shortcuts"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#general-navigation-shortcuts", "text": "tab (Next): focus on the next field or widget. shift + tab (Previous): focus on the previous field or widget PageUp (Next tab): Jump to the next tab in dialogs (ex: Client dialog) Note: the focus must be inside the current tab In the Gif provided, the focus was inside the tab itself before we can press the PageUp key * If the focus is on the tab name itself, we can navigate to other tabs by the Up key and Down key PageDown (Previous tab) : Jump to the previous tab in dialogs (ex: Client dialog) Note: the focus must be inside the current tab In the Gif provided, the focus was inside the tab itself before we can press the PageDown key If the focus is on the tab name itself, we can navigate to other tabs by the Up key and Down key", "title": "General Navigation shortcuts"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#main-tabs-navigation-shortcuts", "text": "Alt + key You can navigate to any tab inside the TUI by using the Alt key followed by a certain letter from the tab you want to navigate too Note: the colored character inside each Tab name is the specified letter for the navigation. you can't navigate from a tab in the main top navigation bar to a nested navigation bar inside another tab, you must navigate to it first. examples on the navigation letters for the main navigation bar: Auth Server -> A FIDO -> F SCIM -> C Scripts -> r Users -> U Jans CLI -> J", "title": "Main tabs Navigation shortcuts"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#custom-widget-shortcuts", "text": "Note: * This section contains any widgets with special shortcuts and behavior", "title": "Custom widget shortcuts"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#lists-vertical-nav-bar", "text": "currently, we have about 6 List widgets Note: Any list widget can be navigated between its items by the Up key and Down key There are some shortcuts here that can be used in most but not all List widgets delete : can be used to delete a certain item d : can be used to view all the selected item data in the JSON format Enter : can be used to edit the current item ex: p : can be used to update user's password.", "title": "Lists (Vertical Nav bar)"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#date-widgets", "text": "The date widget can be used to select a date and time. ex (Client Expiration Date) tab , shift + tab : can be used to navigate between date and time Up , Down , Right , and Left arrows: can be used to change the date and time Note: * in the date section, if you navigate to the right border and then pressed Right , the year will be increased. in the date section, if you navigate to the left border and then pressed Left , the year will be decreased. in the date section, if you navigate to the up border and then pressed Up , the month will be decreased. * in the date section, if you navigate to the down border and then pressed Down , the month will be increased. in the time section, you can navigate between hour, minute, and second by the Right key and the Left key. in the time section, you can increase the time (hour, minute, or second) by the Up key and the Down key.", "title": "Date Widgets"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#label-widgets", "text": "The label widget is used with scopes to show certain items instead of a long one, it is similar to the list widget tab , shift + tab : can be used to navigate between the button and the labels Right key and Left key can be used to navigate between the labels d : can be used to view all the data of the selected label delete : can be used to delete a certain label", "title": "Label Widgets"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#logout-and-exit", "text": "Exit will close the TUI screen while logout will force re-authentication of TUI using device-code. Navigate to Jans TUI on upper right corner of the screen and hit enter.", "title": "Logout and Exit"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/using-command-line-log/", "tags": ["administration", "configuration", "tools", "cli", "tui", "commandline", "logging"], "text": "Using TUI Command Line Log # When you do a write operation (post/put/patch) with Jans TUI, it logs activities to file <log-dir>/cli_cmd.log ,default log-dir is home directory. Consider you created a user with TUI and have the following line in cli_cmd.log : /usr/bin/python3 /opt/jans/jans-cli/cli/config_cli.py --operation-id post-user --data '{\"customObjectClasses\": [\"top\", \"jansPerson\"], \"customAttributes\": [{\"name\": \"middleName\", \"multiValued\": false, \"values\": [\"\"]}, {\"name\": \"sn\", \"multiValued\": false, \"values\": [\"Watts\"]}, {\"name\": \"nickname\", \"multiValued\": false, \"values\": [\"\"]}], \"mail\": \"ewatts@foo.org\", \"userId\": \"ewatts\", \"displayName\": \"Emelia Watts\", \"givenName\": \"Emelia\", \"userPassword\": \"TopSecret\", \"jansStatus\": \"active\"}' You can modify this line to create another user, let us change the followings: userId padilla userPassword NewSecret sn Padilla givenName Reggie displayName Padilla Reggie mail reggie.padilla@egg.org New command will become: /usr/bin/python3 /opt/jans/jans-cli/cli/config_cli.py --operation-id post-user --data '{\"customObjectClasses\": [\"top\", \"jansPerson\"], \"customAttributes\": [{\"name\": \"middleName\", \"multiValued\": false, \"values\": [\"\"]}, {\"name\": \"sn\", \"multiValued\": false, \"values\": [\"Padilla\"]}, {\"name\": \"nickname\", \"multiValued\": false, \"values\": [\"\"]}], \"mail\": \"reggie.padilla@egg.org\", \"userId\": \"padilla\", \"displayName\": \"Padilla Reggie\", \"givenName\": \"Reggie\", \"userPassword\": \"NewSecret\", \"jansStatus\": \"active\"}' When you execute this command, user will be created: Server Response: { \"dn\": \"inum=65a5a60c-d314-426d-a8f4-8c36325a1024,ou=people,o=jans\", \"userId\": \"padilla\", \"createdAt\": \"2023-05-30T09:48:58\", \"customAttributes\": [ { \"name\": \"sn\", \"multiValued\": false, \"values\": [ \"Padilla\" ], \"displayValue\": \"Padilla\", \"value\": \"Padilla\" } ], \"customObjectClasses\": [ \"top\", \"jansCustomPerson\" ], \"inum\": \"65a5a60c-d314-426d-a8f4-8c36325a1024\", \"mail\": \"reggie.padilla@egg.org\", \"displayName\": \"Padilla Reggie\", \"jansStatus\": \"active\", \"givenName\": \"Reggie\", \"baseDn\": \"inum=65a5a60c-d314-426d-a8f4-8c36325a1024,ou=people,o=jans\" }", "title": "Using Logs"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/using-command-line-log/#using-tui-command-line-log", "text": "When you do a write operation (post/put/patch) with Jans TUI, it logs activities to file <log-dir>/cli_cmd.log ,default log-dir is home directory. Consider you created a user with TUI and have the following line in cli_cmd.log : /usr/bin/python3 /opt/jans/jans-cli/cli/config_cli.py --operation-id post-user --data '{\"customObjectClasses\": [\"top\", \"jansPerson\"], \"customAttributes\": [{\"name\": \"middleName\", \"multiValued\": false, \"values\": [\"\"]}, {\"name\": \"sn\", \"multiValued\": false, \"values\": [\"Watts\"]}, {\"name\": \"nickname\", \"multiValued\": false, \"values\": [\"\"]}], \"mail\": \"ewatts@foo.org\", \"userId\": \"ewatts\", \"displayName\": \"Emelia Watts\", \"givenName\": \"Emelia\", \"userPassword\": \"TopSecret\", \"jansStatus\": \"active\"}' You can modify this line to create another user, let us change the followings: userId padilla userPassword NewSecret sn Padilla givenName Reggie displayName Padilla Reggie mail reggie.padilla@egg.org New command will become: /usr/bin/python3 /opt/jans/jans-cli/cli/config_cli.py --operation-id post-user --data '{\"customObjectClasses\": [\"top\", \"jansPerson\"], \"customAttributes\": [{\"name\": \"middleName\", \"multiValued\": false, \"values\": [\"\"]}, {\"name\": \"sn\", \"multiValued\": false, \"values\": [\"Padilla\"]}, {\"name\": \"nickname\", \"multiValued\": false, \"values\": [\"\"]}], \"mail\": \"reggie.padilla@egg.org\", \"userId\": \"padilla\", \"displayName\": \"Padilla Reggie\", \"givenName\": \"Reggie\", \"userPassword\": \"NewSecret\", \"jansStatus\": \"active\"}' When you execute this command, user will be created: Server Response: { \"dn\": \"inum=65a5a60c-d314-426d-a8f4-8c36325a1024,ou=people,o=jans\", \"userId\": \"padilla\", \"createdAt\": \"2023-05-30T09:48:58\", \"customAttributes\": [ { \"name\": \"sn\", \"multiValued\": false, \"values\": [ \"Padilla\" ], \"displayValue\": \"Padilla\", \"value\": \"Padilla\" } ], \"customObjectClasses\": [ \"top\", \"jansCustomPerson\" ], \"inum\": \"65a5a60c-d314-426d-a8f4-8c36325a1024\", \"mail\": \"reggie.padilla@egg.org\", \"displayName\": \"Padilla Reggie\", \"jansStatus\": \"active\", \"givenName\": \"Reggie\", \"baseDn\": \"inum=65a5a60c-d314-426d-a8f4-8c36325a1024,ou=people,o=jans\" }", "title": "Using TUI Command Line Log"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/", "tags": ["administration", "configuration", "fido2"], "text": "Janssen FIDO2 Configuration # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and customize the FIDO2 Configuration using the command line. To get the details of Janssen command line operations relevant to FIDO2 Configuration, you can check the operations under Fido2Configuration task using the command below: Command jans cli --info Fido2Configuration It will show the details of the available operation-ids for Fido2. Sample Output Operation ID: get-properties-fido2 Description: Gets Jans Authorization Server Fido2 configuration properties Operation ID: put-properties-fido2 Description: Updates Fido2 configuration properties Schema: Fido2:AppConfiguration To get sample schema type jans cli --schema <schema>, for example jans cli --schema Fido2:AppConfiguration Get The Current Fido2 Configuration # To get the properties of Janssen Fido2 Configuration, run the command below: Command jans cli --operation-id get-properties-fido2 It will return the result as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 { \"issuer\" : \"https://jans-project.lxd\" , \"baseEndpoint\" : \"https://jans-project.lxd/jans-fido2/restv1\" , \"cleanServiceInterval\" : 60 , \"cleanServiceBatchChunkSize\" : 10000 , \"useLocalCache\" : true , \"disableJdkLogger\" : true , \"loggingLevel\" : \"INFO\" , \"loggingLayout\" : \"text\" , \"metricReporterInterval\" : 300 , \"metricReporterKeepDataDays\" : 15 , \"metricReporterEnabled\" : true , \"personCustomObjectClassList\" : [ \"jansCustomPerson\" , \"jansPerson\" ], \"sessionIdPersistInCache\" : false , \"errorReasonEnabled\" : false , \"fido2Configuration\" : { \"authenticatorCertsFolder\" : \"/etc/jans/conf/fido2/authenticator_cert\" , \"mdsCertsFolder\" : \"/etc/jans/conf/fido2/mds/cert\" , \"mdsTocsFolder\" : \"/etc/jans/conf/fido2/mds/toc\" , \"checkU2fAttestations\" : false , \"debugUserAutoEnrollment\" : false , \"unfinishedRequestExpiration\" : 180 , \"authenticationHistoryExpiration\" : 1296000 , \"serverMetadataFolder\" : \"/etc/jans/conf/fido2/server_metadata\" , \"enabledFidoAlgorithms\" : [ \"RS256\" , \"ES256\" ], \"rp\" : [ { \"id\" : \"https://jans-project.lxd\" , \"origins\" : [ \"jans-project.lxd\" ] } ], \"disableMetadataService\" : false , \"attestationMode\" : \"monitor\" , \"assertionOptionsGenerateEndpointEnabled\" : true } } Update FIDO2 Configuration Properties # To update the configuration follow the steps below. Get the current configuration and store it into a file for editing Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Fido2:AppConfiguration schema as mentioned here . The schema details can be retrieved using the command below. The schema defines what values and datatypes are acceptable for each property value. Command jans cli --schema Fido2:AppConfiguration Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-properties-fido2 --data /tmp/conf-data.json Upon successful execution of the update, the Janssen Server responds with updated configuration. Using Text-based UI # In the Janssen Server, You can manage FIDO2 Configuration using the Text-Based UI also. You can start TUI using the command below: Command jans tui Navigate to FIDO section where administrators can update dynamic and static configurations. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the FIDO2 Configuration. Endpoint details are published in the Swagger document .", "title": "FIDO2 Configuration"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#janssen-fido2-configuration", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Janssen FIDO2 Configuration"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the FIDO2 Configuration using the command line. To get the details of Janssen command line operations relevant to FIDO2 Configuration, you can check the operations under Fido2Configuration task using the command below: Command jans cli --info Fido2Configuration It will show the details of the available operation-ids for Fido2. Sample Output Operation ID: get-properties-fido2 Description: Gets Jans Authorization Server Fido2 configuration properties Operation ID: put-properties-fido2 Description: Updates Fido2 configuration properties Schema: Fido2:AppConfiguration To get sample schema type jans cli --schema <schema>, for example jans cli --schema Fido2:AppConfiguration", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#get-the-current-fido2-configuration", "text": "To get the properties of Janssen Fido2 Configuration, run the command below: Command jans cli --operation-id get-properties-fido2 It will return the result as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 { \"issuer\" : \"https://jans-project.lxd\" , \"baseEndpoint\" : \"https://jans-project.lxd/jans-fido2/restv1\" , \"cleanServiceInterval\" : 60 , \"cleanServiceBatchChunkSize\" : 10000 , \"useLocalCache\" : true , \"disableJdkLogger\" : true , \"loggingLevel\" : \"INFO\" , \"loggingLayout\" : \"text\" , \"metricReporterInterval\" : 300 , \"metricReporterKeepDataDays\" : 15 , \"metricReporterEnabled\" : true , \"personCustomObjectClassList\" : [ \"jansCustomPerson\" , \"jansPerson\" ], \"sessionIdPersistInCache\" : false , \"errorReasonEnabled\" : false , \"fido2Configuration\" : { \"authenticatorCertsFolder\" : \"/etc/jans/conf/fido2/authenticator_cert\" , \"mdsCertsFolder\" : \"/etc/jans/conf/fido2/mds/cert\" , \"mdsTocsFolder\" : \"/etc/jans/conf/fido2/mds/toc\" , \"checkU2fAttestations\" : false , \"debugUserAutoEnrollment\" : false , \"unfinishedRequestExpiration\" : 180 , \"authenticationHistoryExpiration\" : 1296000 , \"serverMetadataFolder\" : \"/etc/jans/conf/fido2/server_metadata\" , \"enabledFidoAlgorithms\" : [ \"RS256\" , \"ES256\" ], \"rp\" : [ { \"id\" : \"https://jans-project.lxd\" , \"origins\" : [ \"jans-project.lxd\" ] } ], \"disableMetadataService\" : false , \"attestationMode\" : \"monitor\" , \"assertionOptionsGenerateEndpointEnabled\" : true } }", "title": "Get The Current Fido2 Configuration"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#update-fido2-configuration-properties", "text": "To update the configuration follow the steps below. Get the current configuration and store it into a file for editing Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Fido2:AppConfiguration schema as mentioned here . The schema details can be retrieved using the command below. The schema defines what values and datatypes are acceptable for each property value. Command jans cli --schema Fido2:AppConfiguration Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-properties-fido2 --data /tmp/conf-data.json Upon successful execution of the update, the Janssen Server responds with updated configuration.", "title": "Update FIDO2 Configuration Properties"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#using-text-based-ui", "text": "In the Janssen Server, You can manage FIDO2 Configuration using the Text-Based UI also. You can start TUI using the command below: Command jans tui Navigate to FIDO section where administrators can update dynamic and static configurations.", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the FIDO2 Configuration. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/", "tags": ["administration", "configuration", "group"], "text": "Group Management # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # Command jans cli -scim --info Group Command Output Operation ID: get-groups Description: Query Group resources (see section 3.4.2 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] filter: An expression specifying the search criteria. See section 3.4.2.2 of RFC 7644 [string] startIndex: The 1-based index of the first query result [integer] count: Specifies the desired maximum number of query results per page [integer] sortBy: The attribute whose value will be used to order the returned responses [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] Operation ID: create-group Description: Allows creating a Group resource via POST (see section 3.3 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] Schema: GroupResource Schema: GroupResource Operation ID: get-group-by-id Description: Retrieves a Group resource by Id (see section 3.4.1 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Operation ID: update-group-by-id Description: Updates a Group resource (see section 3.5.1 of RFC 7644). Update works in a replacement fashion&#58; every attribute value found in the payload sent will replace the one in the existing resource representation. Attributes not passed in the payload will be left intact. Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: GroupResource Schema: GroupResource Operation ID: delete-group-by-id Description: Deletes a group resource (see section 3.6 of RFC 7644) Parameters: id: Identifier of the resource to delete [string] Operation ID: patch-group-by-id Description: Updates one or more attributes of a Group resource using a sequence of additions, removals, and replacements operations. See section 3.5.2 of RFC 7644 Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: PatchRequest Schema: PatchRequest Operation ID: search-group Description: Query Group resources (see section 3.4.2 of RFC 7644) Schema: SearchRequest Schema: SearchRequest To get sample schema type jans cli -scim --schema-sample <schema>, for example jans cli -scim --schema-sample SearchRequest Get Groups # This operation can be used to get list of groups. To get the list of groups, run the following command: Command jans cli -scim --operation-id get-groups It will show the list of groups with all the members linked with each of these groups. Sample Output { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"60B7\" , \"meta\" : { \"resourceType\" : \"Group\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/60B7\" }, \"displayName\" : \"Janssen Manager Group\" , \"members\" : [ { \"value\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"type\" : \"User\" , \"display\" : \"Default Admin User\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/f764391d-56de-4b74-b0a2-f32814706dcc\" } ] } ] } You can filter for the advanced search with some of its properties: attributes excludeAttributes filter count [define maximum number of query] sortBy [attribute] sortOrder ['ascending', 'descending'] Create Group # Using create-group operation, we can create groups into Janssen Server. As we have seen in the output of --info command, this operation requires GroupResource schema. To know the details of schema, run the following command: Command jans cli -scim --schema GroupResource The Janssen server also provides sample schema. To get the sample schema of GroupResource : Command jans cli -scim --schema-sample GroupResource According to schema, let's put all the details into a json file /tmp/create-group.json to create a group. sample { \"displayName\" : \"New Group\" } Now let's run the following command to add group into the server: Command jans cli -scim --operation-id create-group --data /tmp/create-group.json Command Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"2024-09-06T03:46:31.224Z\" , \"lastModified\" : \"2024-09-06T03:46:31.224Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" } Get Group by ID # We can view the specific group details through its id using get-group-by-id operation. For example, We can put the above created group id:7a20464c-3651-48a0-9c9c-6b59373df60c with --url-suffix to get the groupe details. The following command as below: Command jans cli -scim --operation-id get-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" Command Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"lastModified\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" , \"members\" : [] } We see members is empty since we did not associate any user with this group yet. We will add members into this gorup in the next operation. Update Group by ID # The update-group-by-id operation can be used to update group name and adding members into the group. Let's create a json file /tmp/update-group.json according to the GroupResource schema: Sample { \"members\" : [ { \"value\" : \"4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" , \"type\" : \"user\" } ] } We can get the value which is actually the id of specific users from user management section. Let's run the following command to update empty members properties with a member into the group we created above . Command jans cli -scim --operation-id update-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" --data /tmp/update-group.json Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"lastModified\" : \"2024-09-06T05:15:53.227Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" , \"members\" : [ { \"value\" : \"4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" , \"type\" : \"User\" , \"display\" : \"Test User\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" } ] } Please remember one thing, this update method just replace the data. If you want to add members instead of replacing then you must try patch-group-by-id . Delete Group by ID # You can delete a group by its ID. The command line looks like: Command jans cli -scim --operation-id delete-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" It will delete the group and all of its associated data if match with the unique group ID. Patch Group # This is also an option to update any existing group resources. The only difference between update-group-by-id and patch-group is that the first one just replace new data with previous one. It won't add any new data into the group. With patch-group-by-id operation, we can add , remove , and replace properties of group. According to the output of --info command, we can see patch-group-by-id requires PatchRequest schema. [ { \"op\": \"add\", \"path\": \"members\", \"value\": { \"value\": \"f764391d-56de-4b74-b0a2-f32814706dcc\", \"type\": \"user\" } } ] Let's run the following command: Command jans cli -scim --operation-id patch-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" --data /tmp/patch-user.json Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document .", "title": "SCIM Group Management"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#group-management", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Group Management"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#using-command-line", "text": "Command jans cli -scim --info Group Command Output Operation ID: get-groups Description: Query Group resources (see section 3.4.2 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] filter: An expression specifying the search criteria. See section 3.4.2.2 of RFC 7644 [string] startIndex: The 1-based index of the first query result [integer] count: Specifies the desired maximum number of query results per page [integer] sortBy: The attribute whose value will be used to order the returned responses [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] Operation ID: create-group Description: Allows creating a Group resource via POST (see section 3.3 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] Schema: GroupResource Schema: GroupResource Operation ID: get-group-by-id Description: Retrieves a Group resource by Id (see section 3.4.1 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Operation ID: update-group-by-id Description: Updates a Group resource (see section 3.5.1 of RFC 7644). Update works in a replacement fashion&#58; every attribute value found in the payload sent will replace the one in the existing resource representation. Attributes not passed in the payload will be left intact. Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: GroupResource Schema: GroupResource Operation ID: delete-group-by-id Description: Deletes a group resource (see section 3.6 of RFC 7644) Parameters: id: Identifier of the resource to delete [string] Operation ID: patch-group-by-id Description: Updates one or more attributes of a Group resource using a sequence of additions, removals, and replacements operations. See section 3.5.2 of RFC 7644 Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: PatchRequest Schema: PatchRequest Operation ID: search-group Description: Query Group resources (see section 3.4.2 of RFC 7644) Schema: SearchRequest Schema: SearchRequest To get sample schema type jans cli -scim --schema-sample <schema>, for example jans cli -scim --schema-sample SearchRequest", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#get-groups", "text": "This operation can be used to get list of groups. To get the list of groups, run the following command: Command jans cli -scim --operation-id get-groups It will show the list of groups with all the members linked with each of these groups. Sample Output { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"60B7\" , \"meta\" : { \"resourceType\" : \"Group\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/60B7\" }, \"displayName\" : \"Janssen Manager Group\" , \"members\" : [ { \"value\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"type\" : \"User\" , \"display\" : \"Default Admin User\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/f764391d-56de-4b74-b0a2-f32814706dcc\" } ] } ] } You can filter for the advanced search with some of its properties: attributes excludeAttributes filter count [define maximum number of query] sortBy [attribute] sortOrder ['ascending', 'descending']", "title": "Get Groups"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#create-group", "text": "Using create-group operation, we can create groups into Janssen Server. As we have seen in the output of --info command, this operation requires GroupResource schema. To know the details of schema, run the following command: Command jans cli -scim --schema GroupResource The Janssen server also provides sample schema. To get the sample schema of GroupResource : Command jans cli -scim --schema-sample GroupResource According to schema, let's put all the details into a json file /tmp/create-group.json to create a group. sample { \"displayName\" : \"New Group\" } Now let's run the following command to add group into the server: Command jans cli -scim --operation-id create-group --data /tmp/create-group.json Command Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"2024-09-06T03:46:31.224Z\" , \"lastModified\" : \"2024-09-06T03:46:31.224Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" }", "title": "Create Group"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#get-group-by-id", "text": "We can view the specific group details through its id using get-group-by-id operation. For example, We can put the above created group id:7a20464c-3651-48a0-9c9c-6b59373df60c with --url-suffix to get the groupe details. The following command as below: Command jans cli -scim --operation-id get-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" Command Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"lastModified\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" , \"members\" : [] } We see members is empty since we did not associate any user with this group yet. We will add members into this gorup in the next operation.", "title": "Get Group by ID"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#update-group-by-id", "text": "The update-group-by-id operation can be used to update group name and adding members into the group. Let's create a json file /tmp/update-group.json according to the GroupResource schema: Sample { \"members\" : [ { \"value\" : \"4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" , \"type\" : \"user\" } ] } We can get the value which is actually the id of specific users from user management section. Let's run the following command to update empty members properties with a member into the group we created above . Command jans cli -scim --operation-id update-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" --data /tmp/update-group.json Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"lastModified\" : \"2024-09-06T05:15:53.227Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" , \"members\" : [ { \"value\" : \"4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" , \"type\" : \"User\" , \"display\" : \"Test User\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" } ] } Please remember one thing, this update method just replace the data. If you want to add members instead of replacing then you must try patch-group-by-id .", "title": "Update Group by ID"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#delete-group-by-id", "text": "You can delete a group by its ID. The command line looks like: Command jans cli -scim --operation-id delete-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" It will delete the group and all of its associated data if match with the unique group ID.", "title": "Delete Group by ID"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#patch-group", "text": "This is also an option to update any existing group resources. The only difference between update-group-by-id and patch-group is that the first one just replace new data with previous one. It won't add any new data into the group. With patch-group-by-id operation, we can add , remove , and replace properties of group. According to the output of --info command, we can see patch-group-by-id requires PatchRequest schema. [ { \"op\": \"add\", \"path\": \"members\", \"value\": { \"value\": \"f764391d-56de-4b74-b0a2-f32814706dcc\", \"type\": \"user\" } } ] Let's run the following command: Command jans cli -scim --operation-id patch-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" --data /tmp/patch-user.json", "title": "Patch Group"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/scim-config/user-config/", "tags": ["administration", "configuration", "user"], "text": "User Management # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can do CRUD operations for user management using its command line tool. To get the details of command line for CRUD operations relevant to User Management, you can find the operation-id under the User task using the Jans CLI in scim mode. The following command line: Command jans cli -scim --info User Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 Operation ID: get-users Description: Query User resources (see section 3.4.2 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] filter: An expression specifying the search criteria. See section 3.4.2.2 of RFC 7644 [string] startIndex: The 1-based index of the first query result [integer] count: Specifies the desired maximum number of query results per page [integer] sortBy: The attribute whose value will be used to order the returned responses [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] Operation ID: create-user Description: Allows creating a User resource via POST (see section 3.3 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] Schema: UserResource Schema: UserResource Operation ID: get-user-by-id Description: Retrieves a User resource by Id (see section 3.4.1 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Operation ID: update-user-by-id Description: Updates a User resource (see section 3.5.1 of RFC 7644). Update works in a replacement fashion; every attribute value found in the payload sent will replace the one in the existing resource representation. Attributes not passed in the payload will be left intact. Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: UserResource Schema: UserResource Operation ID: delete-user-by-id Description: Deletes a user resource Parameters: id: Identifier of the resource to delete [string] Operation ID: patch-user-by-id Description: Updates one or more attributes of a User resource using a sequence of additions, removals, and replacements operations. See section 3.5.2 of RFC 7644 Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: PatchRequest Schema: PatchRequest Operation ID: search-user Description: Query User resources (see section 3.4.2 of RFC 7644) Schema: SearchRequest Schema: SearchRequest To get sample schema type jans cli -scim --schema-sample <schema>, for example jans cli -scim --schema-sample SearchRequest Get Users List # This operation is used to get list of the users and its properties. The following command line: Command jans cli -scim --operation-id get-users Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"meta\" : { \"resourceType\" : \"User\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/f764391d-56de-4b74-b0a2-f32814706dcc\" }, \"userName\" : \"admin\" , \"name\" : { \"familyName\" : \"User\" , \"givenName\" : \"Admin\" , \"middleName\" : \"Admin\" , \"formatted\" : \"Admin Admin User\" }, \"displayName\" : \"Default Admin User\" , \"nickName\" : \"Admin\" , \"active\" : true , \"emails\" : [ { \"value\" : \"admin@imshakil-boss-guppy.gluu.info\" , \"primary\" : false } ], \"groups\" : [ { \"value\" : \"60B7\" , \"display\" : \"Janssen Manager Group\" , \"type\" : \"direct\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/60B7\" } ] } ] } As shown in the output for --info command, get-users operation-id also supports parameters for the advanced search. Those parameters are: 1. attributes 2. excludeAttributes 3. filter 4. count [ define maximum number of query ] 5. sortBy [ attribute ] 6. sortOrder [ 'ascending', 'descending' ] This is an example with endpoint-args : Command jans cli -scim --operation-id get-users --endpoint-args attributes:emails Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"emails\" : [ { \"value\" : \"admin@imshakil-boss-guppy.gluu.info\" , \"primary\" : false } ] } ] } Creating a New User # To create a new user using Jans CLI, we can use create-user operation-id. As shown in the output for --info command, the create-user operation requires data to be sent according to UserResource schema. To see the schema, use the command as below: Command jans cli -scim --schema UserResource The Janssen Server also provides sample data for the above schema. Let's run the following command to get the sample schema: Command jans cli -scim --schema-sample UserResource From the above example of schema file, we can fill required values in a data file /tmp/user.json . As we have seen in the sample schema there are lot of properties, but we are going to fill minimum to create a test user : user.json 1 2 3 4 5 6 7 8 9 10 11 12 13 { \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"password\" : \"pass@word\" , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] } Let's run the following command to create user in Janssen Server: Command jans cli -scim --operation-id create-user --data /tmp/user.json Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-04T06:36:00.882Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] } Find User by Id # We can retrieve user details using user's id . For example in the above created user id is e24c1479-4a61-4f1f-aa30-2ccc13c0b130 . To get the user details by user id, We can use the get-user-by-id operation as below: Command jans cli -scim --operation-id get-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-04T06:36:00.882Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] } Update User by Id # Using Jans CLI, We can update user information. As shown in the output command, the update-user-by-id operation requires user data that needs to be changed. You can find details of user properties in schema . Let's change the nickname for the above Test user . First,we need to put the update data into a json file /tmp/update-user.json : ```json title='update-user.json { \"nickName\": \"testuser\" } Let's run the following command: ```bash title=\"Command\" jans cli -scim --operation-id update-user-by-id \\ --url-suffix=\"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" --data /tmp/update-user.json Sample Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-05T05:38:31.491Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testuser\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] } Patch User by Id # Using patch-user-by-id operation, We can modify user properties partially. As we have seen in the Output of --info command, patch-user-by-id operation requires PatchRequest schema definition for payload data. To get the sample PatchRequest schema, run the followwing command: ```bash titl=\"Command\" jans cli -scim --schema-sample PatchRequest For example, In the above `test user`, we are going to `add` one more email, `remove` nickName and `replace` displayName. Let's put all the operations in a json file `/tmp/patch-user.json`: ```json title=\"patch-user.json\" { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"path\": \"displayName\", \"value\": \"Test User\" }, { \"op\": \"add\", \"path\": \"emails\", \"value\": [ { \"value\": \"test.user@example.jans.io\", \"primary\": true } ] }, { \"op\": \"remove\", \"path\": \"nickName\" } ] } The command line to run all of these operations: Command jans cli -scim --operation patch-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" \\ --data /tmp/patch-user.json Delete User by ID # To delete the, run the following command with the specific user ID as --url-suffix=id:user-id . For example, let's delete the test user we have created earlier: Command jans cli -scim --operation-id delete-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" Using Text-based UI # Using TUI, We can add, update and deleter users in the Janssen Server. To do that, Let's start TUI using the command below: Command /opt/jans/jans-cli/jans_cli_tui.py Navigate to Users to open the users tab as shown in the image below: We can see the list of users from search option To get the list of users available in the Janssen Server, bring the control to Search box (using tab key) and press Enter key. Let's see at a glance of available user attributes. Attributes Description Username ... Password ... First Name ... Middle Name ... Last Name ... Display Name ... Email ... Active ... Nickname ... CIBA Device Registration Token ... CIBA User code ... Locale ... Website URL ... IMAP Data ... jansAdminUIRole ... Enrollment code ... User Permission ... Preferred Language ... Profile URL ... Secret Question ... Email Verified ... Birthdate ... Time zone info ... Phone Number verified ... Preferred Username ... TransientId ... PersistentId ... Country ... Secret Answer ... OpenID Connect JSON formatted address ... User certificate ... Organization ... Picture URL ... Add User # Let's add an user by selecting Add Users tab. Initially we can provide bellow attributes value, We can add extra claims simply by slecting Add Claim Finally save and exit. We will get an unique inum Update User # To modify any user properties, find the user from search box and hit Enter to pop-up user details, update user details and finally hit on Save button to update the changes. Delete User # To delete user, bring the control on the specific user row and press delete or d key from keyboard. It will show a pop-up for confirmation as below: Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document . Get SCIM Client # Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. To see in JSON formate please press d . From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE . Get Access token # Let's get a token, curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type=client_credentials -d scope='https://jans.io/scim/users.read https://jans.io/scim/users write' https://<jans-server>/jans-auth/restv1/token > /tmp/token.json In response token.json we will get access_token { \"access_token\":\"11a76589-7955-4247-9ca5-f3ad7884305...\", \"scope\":\"https://jans.io/scim/users.read\", \"token_type\":\"Bearer\", \"expires_in\":299 } Retrive existing User # To get an existing user curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://<jans-server>/jans-scim/restv1/v2/Users > /tmp/user.json In response user.json we will get { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\": 1, \"startIndex\": 1, \"itemsPerPage\": 1, \"Resources\": [ { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"5fdbb720-a1fd-477f-af92-b7c054f02c98\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-12T14:54:09.531Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/5fdbb720-a1fd-477f-af92-b7c054f02c98\" }, \"userName\": \"admin\", \"name\": { \"familyName\": \"...\", \"givenName\": \"...\", \"middleName\": \"...\", \"formatted\": \"...\" }, \"displayName\": \"Admin\", \"active\": true, \"emails\": [ { \"value\": \"example@gluu.org\", \"primary\": false } ], \"groups\": [ { \"value\": \"60B7\", \"display\": \"Jannsen Manager Group\", \"type\": \"direct\", \"$ref\": \"https://raju.jans13.me/jans-scim/restv1/v2/Groups/60B7\" } ] } ] } Create an User # Let's start creating a dummy user. A client sends a POST request containing a \"User\" to the \"/Users\" endpoint. POST /Users HTTP/1.1 Host: example.com Accept: application/scim+json Content-Type: application/scim+json Authorization: Bearer h480djs93hd8.. Content-Length: ... { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" } } Open a text editor and copy paste the json body, name as input.json . Hit on your terminal with bellow command. curl -k -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users response looks like { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T19:43:32.945Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Barbara\", \"formatted\": \"Ms. Barbara J Jensen III\" } } This new user has been given an id . If possible, inspect your ou=people branch and find the entry whose inum matches the id given. An easier option would be to via Jans TUI and go to Users and search \"bjensen\" to see the recently created user. Updating a User(PUT) # Overwrite your input.json with the following. Replace content in angle brackets accordingly: { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" }, \"displayName\": \"Jensen Barbara\", \"emails\": [ { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": true } ] } PUT with curl : curl -k -X PUT -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Response (output.json) will show the same contents of a full retrieval. Please verify changes were applied whether by inspecting LDAP or issuing a GET. If you have followed the steps properly, you should notice a new e-mail added and the change in displayName attribute Updating a User (PATCH) # With patching, you can be very precise about the modifications you want to apply. Patching syntax follows JSON Patch spec (RFC 6902) closely. While it's not a must to read the RFC to learn how patch works, see section 3.5.2 of SCIM protocol (RFC 7644) to get the grasp. If you prefer reading code, patch test cases found in the Java scim-client project are worth to look at. The following is a simple example that illustrates the kind of modifications developers can achieve via PATCH . Overwrite your input.json with the following: { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"value\": { \"name\": { \"givenName\": \"Joey\" } } }, { \"op\": \"replace\", \"path\": \"emails[type eq \\\"work\\\" or primary eq false].value\", \"value\": \"jensen@example.com\" }, { \"op\": \"add\", \"value\": { \"name\": { \"middleName\": \"Jhon\" } } }, { \"op\": \"add\", \"value\": { \"emails\": [ { \"primary\": true, \"value\": \"my@own.mail\" } ], \"phoneNumbers\": [ { \"type\": \"home\", \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } }, { \"op\": \"remove\", \"path\": \"name.middleName\" }, { \"op\": \"remove\", \"path\": \"phoneNumbers[value ew \\\"01\\\"].type\" } ] } A collection of modification are provided under \"Operations\". They are processed in order of appearance. Also, every operation has a type; patching supports add, remove and replace. The first operations states the following: replace the value of givenName subattribute (that belongs to complex attribute name ) with the string \"Joey\". Operations are easier to understand when using a \"path\". The second operation replaces the value subattribute inside the complex multi-valued attribute emails. Inside the square brackets, we find a filter expression, so the replacement does not apply to all emails in the list but only to those matching the criterion. So the second operation can be read as \"set the value of value subattribute to string jensen@example.com where the type subattribute of the email equals to string \"work\" or if primary attribute is false\". The third operation is similar to the first. It sets the value of a subattribute which was unassigned (null). You could have used \"replace\" operation in this case and results would have been identical. The fourth operation is more interesting. It adds to the current list of emails a new one. It supplies a couple of subattributes for the email to include: primary and value. Additionally, we set the value of (previously unassigned) phoneNumbers multi-valued attribute passing a list of elements. In the fifth operation, we remove the middleName attribute that was set in operation three. Note how we make explicit the path of data to nullify: \"name.middleName\". The sixth operation allows us to remove a specific subattribute of phoneNumbers . The aim is to nullify the \"type\" of the item whose phone number value ends with \"01\". The remove operation can also be used to remove a complete item from a list, or empty the whole list by providing a suitable value for \"path\". Now let's see it in action: curl -k -X PATCH -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> So far our resource look like this { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T22:34:27.465Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Joey\", \"formatted\": \"Ms. Barbara J Jensen III\" }, \"displayName\": \"Jensen Barbara\", \"active\": false, \"emails\": [ { \"value\": \"my@own.mail\", \"primary\": true }, { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": false } ], \"phoneNumbers\": [ { \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } Note the primary subattribute accompanying email \"my@own.mail\" is false but when inserted we provided true . This is because the SCIM specification states that after modifications are applied to resources (PUT or PATCH) , there cannot be more than one item in a multi-valued attribute with primary value set as true . To see more sample JSON payloads, check the .json files used by the scim-client test cases referenced above. Deleting Users # For deleting, the DELETE method of HTTP is used. No input file is used in this case. A delete request could be the following: curl -k -X DELETE -H 'Authorization: Bearer ACCESS_TOKEN' https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Use the inum of our dummy user, Jensen Barbara . Check your LDAP or via Jans TUI to see that Bjensen is gone.", "title": "SCIM User Resources"}, {"location": "janssen-server/config-guide/scim-config/user-config/#user-management", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "User Management"}, {"location": "janssen-server/config-guide/scim-config/user-config/#using-command-line", "text": "In the Janssen Server, you can do CRUD operations for user management using its command line tool. To get the details of command line for CRUD operations relevant to User Management, you can find the operation-id under the User task using the Jans CLI in scim mode. The following command line: Command jans cli -scim --info User Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 Operation ID: get-users Description: Query User resources (see section 3.4.2 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] filter: An expression specifying the search criteria. See section 3.4.2.2 of RFC 7644 [string] startIndex: The 1-based index of the first query result [integer] count: Specifies the desired maximum number of query results per page [integer] sortBy: The attribute whose value will be used to order the returned responses [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] Operation ID: create-user Description: Allows creating a User resource via POST (see section 3.3 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] Schema: UserResource Schema: UserResource Operation ID: get-user-by-id Description: Retrieves a User resource by Id (see section 3.4.1 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Operation ID: update-user-by-id Description: Updates a User resource (see section 3.5.1 of RFC 7644). Update works in a replacement fashion; every attribute value found in the payload sent will replace the one in the existing resource representation. Attributes not passed in the payload will be left intact. Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: UserResource Schema: UserResource Operation ID: delete-user-by-id Description: Deletes a user resource Parameters: id: Identifier of the resource to delete [string] Operation ID: patch-user-by-id Description: Updates one or more attributes of a User resource using a sequence of additions, removals, and replacements operations. See section 3.5.2 of RFC 7644 Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: PatchRequest Schema: PatchRequest Operation ID: search-user Description: Query User resources (see section 3.4.2 of RFC 7644) Schema: SearchRequest Schema: SearchRequest To get sample schema type jans cli -scim --schema-sample <schema>, for example jans cli -scim --schema-sample SearchRequest", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/scim-config/user-config/#get-users-list", "text": "This operation is used to get list of the users and its properties. The following command line: Command jans cli -scim --operation-id get-users Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"meta\" : { \"resourceType\" : \"User\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/f764391d-56de-4b74-b0a2-f32814706dcc\" }, \"userName\" : \"admin\" , \"name\" : { \"familyName\" : \"User\" , \"givenName\" : \"Admin\" , \"middleName\" : \"Admin\" , \"formatted\" : \"Admin Admin User\" }, \"displayName\" : \"Default Admin User\" , \"nickName\" : \"Admin\" , \"active\" : true , \"emails\" : [ { \"value\" : \"admin@imshakil-boss-guppy.gluu.info\" , \"primary\" : false } ], \"groups\" : [ { \"value\" : \"60B7\" , \"display\" : \"Janssen Manager Group\" , \"type\" : \"direct\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/60B7\" } ] } ] } As shown in the output for --info command, get-users operation-id also supports parameters for the advanced search. Those parameters are: 1. attributes 2. excludeAttributes 3. filter 4. count [ define maximum number of query ] 5. sortBy [ attribute ] 6. sortOrder [ 'ascending', 'descending' ] This is an example with endpoint-args : Command jans cli -scim --operation-id get-users --endpoint-args attributes:emails Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"emails\" : [ { \"value\" : \"admin@imshakil-boss-guppy.gluu.info\" , \"primary\" : false } ] } ] }", "title": "Get Users List"}, {"location": "janssen-server/config-guide/scim-config/user-config/#creating-a-new-user", "text": "To create a new user using Jans CLI, we can use create-user operation-id. As shown in the output for --info command, the create-user operation requires data to be sent according to UserResource schema. To see the schema, use the command as below: Command jans cli -scim --schema UserResource The Janssen Server also provides sample data for the above schema. Let's run the following command to get the sample schema: Command jans cli -scim --schema-sample UserResource From the above example of schema file, we can fill required values in a data file /tmp/user.json . As we have seen in the sample schema there are lot of properties, but we are going to fill minimum to create a test user : user.json 1 2 3 4 5 6 7 8 9 10 11 12 13 { \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"password\" : \"pass@word\" , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] } Let's run the following command to create user in Janssen Server: Command jans cli -scim --operation-id create-user --data /tmp/user.json Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-04T06:36:00.882Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] }", "title": "Creating a New User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#find-user-by-id", "text": "We can retrieve user details using user's id . For example in the above created user id is e24c1479-4a61-4f1f-aa30-2ccc13c0b130 . To get the user details by user id, We can use the get-user-by-id operation as below: Command jans cli -scim --operation-id get-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-04T06:36:00.882Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] }", "title": "Find User by Id"}, {"location": "janssen-server/config-guide/scim-config/user-config/#update-user-by-id", "text": "Using Jans CLI, We can update user information. As shown in the output command, the update-user-by-id operation requires user data that needs to be changed. You can find details of user properties in schema . Let's change the nickname for the above Test user . First,we need to put the update data into a json file /tmp/update-user.json : ```json title='update-user.json { \"nickName\": \"testuser\" } Let's run the following command: ```bash title=\"Command\" jans cli -scim --operation-id update-user-by-id \\ --url-suffix=\"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" --data /tmp/update-user.json Sample Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-05T05:38:31.491Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testuser\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] }", "title": "Update User by Id"}, {"location": "janssen-server/config-guide/scim-config/user-config/#patch-user-by-id", "text": "Using patch-user-by-id operation, We can modify user properties partially. As we have seen in the Output of --info command, patch-user-by-id operation requires PatchRequest schema definition for payload data. To get the sample PatchRequest schema, run the followwing command: ```bash titl=\"Command\" jans cli -scim --schema-sample PatchRequest For example, In the above `test user`, we are going to `add` one more email, `remove` nickName and `replace` displayName. Let's put all the operations in a json file `/tmp/patch-user.json`: ```json title=\"patch-user.json\" { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"path\": \"displayName\", \"value\": \"Test User\" }, { \"op\": \"add\", \"path\": \"emails\", \"value\": [ { \"value\": \"test.user@example.jans.io\", \"primary\": true } ] }, { \"op\": \"remove\", \"path\": \"nickName\" } ] } The command line to run all of these operations: Command jans cli -scim --operation patch-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" \\ --data /tmp/patch-user.json", "title": "Patch User by Id"}, {"location": "janssen-server/config-guide/scim-config/user-config/#delete-user-by-id", "text": "To delete the, run the following command with the specific user ID as --url-suffix=id:user-id . For example, let's delete the test user we have created earlier: Command jans cli -scim --operation-id delete-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\"", "title": "Delete User by ID"}, {"location": "janssen-server/config-guide/scim-config/user-config/#using-text-based-ui", "text": "Using TUI, We can add, update and deleter users in the Janssen Server. To do that, Let's start TUI using the command below: Command /opt/jans/jans-cli/jans_cli_tui.py Navigate to Users to open the users tab as shown in the image below: We can see the list of users from search option To get the list of users available in the Janssen Server, bring the control to Search box (using tab key) and press Enter key. Let's see at a glance of available user attributes. Attributes Description Username ... Password ... First Name ... Middle Name ... Last Name ... Display Name ... Email ... Active ... Nickname ... CIBA Device Registration Token ... CIBA User code ... Locale ... Website URL ... IMAP Data ... jansAdminUIRole ... Enrollment code ... User Permission ... Preferred Language ... Profile URL ... Secret Question ... Email Verified ... Birthdate ... Time zone info ... Phone Number verified ... Preferred Username ... TransientId ... PersistentId ... Country ... Secret Answer ... OpenID Connect JSON formatted address ... User certificate ... Organization ... Picture URL ...", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/scim-config/user-config/#add-user", "text": "Let's add an user by selecting Add Users tab. Initially we can provide bellow attributes value, We can add extra claims simply by slecting Add Claim Finally save and exit. We will get an unique inum", "title": "Add User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#update-user", "text": "To modify any user properties, find the user from search box and hit Enter to pop-up user details, update user details and finally hit on Save button to update the changes.", "title": "Update User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#delete-user", "text": "To delete user, bring the control on the specific user row and press delete or d key from keyboard. It will show a pop-up for confirmation as below:", "title": "Delete User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/scim-config/user-config/#get-scim-client", "text": "Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. To see in JSON formate please press d . From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE .", "title": "Get SCIM Client"}, {"location": "janssen-server/config-guide/scim-config/user-config/#get-access-token", "text": "Let's get a token, curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type=client_credentials -d scope='https://jans.io/scim/users.read https://jans.io/scim/users write' https://<jans-server>/jans-auth/restv1/token > /tmp/token.json In response token.json we will get access_token { \"access_token\":\"11a76589-7955-4247-9ca5-f3ad7884305...\", \"scope\":\"https://jans.io/scim/users.read\", \"token_type\":\"Bearer\", \"expires_in\":299 }", "title": "Get Access token"}, {"location": "janssen-server/config-guide/scim-config/user-config/#retrive-existing-user", "text": "To get an existing user curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://<jans-server>/jans-scim/restv1/v2/Users > /tmp/user.json In response user.json we will get { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\": 1, \"startIndex\": 1, \"itemsPerPage\": 1, \"Resources\": [ { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"5fdbb720-a1fd-477f-af92-b7c054f02c98\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-12T14:54:09.531Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/5fdbb720-a1fd-477f-af92-b7c054f02c98\" }, \"userName\": \"admin\", \"name\": { \"familyName\": \"...\", \"givenName\": \"...\", \"middleName\": \"...\", \"formatted\": \"...\" }, \"displayName\": \"Admin\", \"active\": true, \"emails\": [ { \"value\": \"example@gluu.org\", \"primary\": false } ], \"groups\": [ { \"value\": \"60B7\", \"display\": \"Jannsen Manager Group\", \"type\": \"direct\", \"$ref\": \"https://raju.jans13.me/jans-scim/restv1/v2/Groups/60B7\" } ] } ] }", "title": "Retrive existing User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#create-an-user", "text": "Let's start creating a dummy user. A client sends a POST request containing a \"User\" to the \"/Users\" endpoint. POST /Users HTTP/1.1 Host: example.com Accept: application/scim+json Content-Type: application/scim+json Authorization: Bearer h480djs93hd8.. Content-Length: ... { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" } } Open a text editor and copy paste the json body, name as input.json . Hit on your terminal with bellow command. curl -k -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users response looks like { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T19:43:32.945Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Barbara\", \"formatted\": \"Ms. Barbara J Jensen III\" } } This new user has been given an id . If possible, inspect your ou=people branch and find the entry whose inum matches the id given. An easier option would be to via Jans TUI and go to Users and search \"bjensen\" to see the recently created user.", "title": "Create an User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#updating-a-userput", "text": "Overwrite your input.json with the following. Replace content in angle brackets accordingly: { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" }, \"displayName\": \"Jensen Barbara\", \"emails\": [ { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": true } ] } PUT with curl : curl -k -X PUT -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Response (output.json) will show the same contents of a full retrieval. Please verify changes were applied whether by inspecting LDAP or issuing a GET. If you have followed the steps properly, you should notice a new e-mail added and the change in displayName attribute", "title": "Updating a User(PUT)"}, {"location": "janssen-server/config-guide/scim-config/user-config/#updating-a-user-patch", "text": "With patching, you can be very precise about the modifications you want to apply. Patching syntax follows JSON Patch spec (RFC 6902) closely. While it's not a must to read the RFC to learn how patch works, see section 3.5.2 of SCIM protocol (RFC 7644) to get the grasp. If you prefer reading code, patch test cases found in the Java scim-client project are worth to look at. The following is a simple example that illustrates the kind of modifications developers can achieve via PATCH . Overwrite your input.json with the following: { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"value\": { \"name\": { \"givenName\": \"Joey\" } } }, { \"op\": \"replace\", \"path\": \"emails[type eq \\\"work\\\" or primary eq false].value\", \"value\": \"jensen@example.com\" }, { \"op\": \"add\", \"value\": { \"name\": { \"middleName\": \"Jhon\" } } }, { \"op\": \"add\", \"value\": { \"emails\": [ { \"primary\": true, \"value\": \"my@own.mail\" } ], \"phoneNumbers\": [ { \"type\": \"home\", \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } }, { \"op\": \"remove\", \"path\": \"name.middleName\" }, { \"op\": \"remove\", \"path\": \"phoneNumbers[value ew \\\"01\\\"].type\" } ] } A collection of modification are provided under \"Operations\". They are processed in order of appearance. Also, every operation has a type; patching supports add, remove and replace. The first operations states the following: replace the value of givenName subattribute (that belongs to complex attribute name ) with the string \"Joey\". Operations are easier to understand when using a \"path\". The second operation replaces the value subattribute inside the complex multi-valued attribute emails. Inside the square brackets, we find a filter expression, so the replacement does not apply to all emails in the list but only to those matching the criterion. So the second operation can be read as \"set the value of value subattribute to string jensen@example.com where the type subattribute of the email equals to string \"work\" or if primary attribute is false\". The third operation is similar to the first. It sets the value of a subattribute which was unassigned (null). You could have used \"replace\" operation in this case and results would have been identical. The fourth operation is more interesting. It adds to the current list of emails a new one. It supplies a couple of subattributes for the email to include: primary and value. Additionally, we set the value of (previously unassigned) phoneNumbers multi-valued attribute passing a list of elements. In the fifth operation, we remove the middleName attribute that was set in operation three. Note how we make explicit the path of data to nullify: \"name.middleName\". The sixth operation allows us to remove a specific subattribute of phoneNumbers . The aim is to nullify the \"type\" of the item whose phone number value ends with \"01\". The remove operation can also be used to remove a complete item from a list, or empty the whole list by providing a suitable value for \"path\". Now let's see it in action: curl -k -X PATCH -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> So far our resource look like this { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T22:34:27.465Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Joey\", \"formatted\": \"Ms. Barbara J Jensen III\" }, \"displayName\": \"Jensen Barbara\", \"active\": false, \"emails\": [ { \"value\": \"my@own.mail\", \"primary\": true }, { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": false } ], \"phoneNumbers\": [ { \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } Note the primary subattribute accompanying email \"my@own.mail\" is false but when inserted we provided true . This is because the SCIM specification states that after modifications are applied to resources (PUT or PATCH) , there cannot be more than one item in a multi-valued attribute with primary value set as true . To see more sample JSON payloads, check the .json files used by the scim-client test cases referenced above.", "title": "Updating a User (PATCH)"}, {"location": "janssen-server/config-guide/scim-config/user-config/#deleting-users", "text": "For deleting, the DELETE method of HTTP is used. No input file is used in this case. A delete request could be the following: curl -k -X DELETE -H 'Authorization: Bearer ACCESS_TOKEN' https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Use the inum of our dummy user, Jensen Barbara . Check your LDAP or via Jans TUI to see that Bjensen is gone.", "title": "Deleting Users"}, {"location": "janssen-server/developer/cors/", "tags": ["administration", "installation"], "text": "CORS Filter # Overview # CORS Filter is an implementation of the W3C's Cross-Origin Resource Sharing (CORS) specification . The CORS Filter works by adding required Access-Control-* headers to the HttpServletResponse object. The filter also protects against HTTP response splitting. If a request is invalid or not permitted, the request is rejected with HTTP status code 403 (Forbidden). The minimal configuration required to use the CORS Filter is shown below, and is already added to the web.xml in jans-auth.war . The filter name is io.jans.as.server.filter.CorsFilter . <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern /> </filter-mapping> Configure CORS # CORS can be configured in Jans Server using Jans TUI . Follow these steps: Open Jans TUI using jans tui command. Go to Auth Server > Properties and select corsConfigurationFilters This will display the CORS Configuration Filter parameters, as shown below: Define and configure the parameters. Click save at the bottom of the page. Parameters supported by CORS Filters # CORS Filter supports the following initialization parameters: Attribute Description corsAllowedOrigins A list of origins that are allowed to access the resource. A * can be specified to enable access to resource from any origin. Otherwise, a whitelist of comma separated origins can be provided. Eg: http://www.w3.org , https://www.apache.org. Defaults: * (Any origin is allowed to access the resource). corsAllowedMethods A comma separated list of HTTP methods that can be used to access the resource, using cross-origin requests. These are the methods which will also be included as part of Access-Control-Allow-Methods header in pre-flight response. Eg: GET , POST . Defaults: GET , POST , HEAD , OPTIONS corsExposedHeaders A comma separated list of request headers that can be used when making an actual request. These headers will also be returned as part of Access-Control-Allow-Headers header in a pre-flight response. Eg: Origin, Accept . Defaults: Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers corsSupportCredentials A flag that indicates whether the resource supports user credentials. This flag is exposed as part of Access-Control-Allow-Credentials header in a pre-flight response. It helps browser determine whether or not an actual request can be made using credentials. Defaults: true corsLoggingEnabled Value to enable logging, Setting the value to False will disable logging. Defaults: true corsPreflightMaxAge The duration in seconds the browser is allowed to cache the result of the pre-flight request. This will be included as part of the Access-Control-Max-Age header in the pre-flight response. A negative value will prevent the CORS Filter from adding this response header to the pre-flight response. Defaults: 1800 corsRequestDecorate A flag to control if CORS specific attributes should be added to the HttpServletRequest object. Defaults: true", "title": "CORS"}, {"location": "janssen-server/developer/cors/#cors-filter", "text": "", "title": "CORS Filter"}, {"location": "janssen-server/developer/cors/#overview", "text": "CORS Filter is an implementation of the W3C's Cross-Origin Resource Sharing (CORS) specification . The CORS Filter works by adding required Access-Control-* headers to the HttpServletResponse object. The filter also protects against HTTP response splitting. If a request is invalid or not permitted, the request is rejected with HTTP status code 403 (Forbidden). The minimal configuration required to use the CORS Filter is shown below, and is already added to the web.xml in jans-auth.war . The filter name is io.jans.as.server.filter.CorsFilter . <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern /> </filter-mapping>", "title": "Overview"}, {"location": "janssen-server/developer/cors/#configure-cors", "text": "CORS can be configured in Jans Server using Jans TUI . Follow these steps: Open Jans TUI using jans tui command. Go to Auth Server > Properties and select corsConfigurationFilters This will display the CORS Configuration Filter parameters, as shown below: Define and configure the parameters. Click save at the bottom of the page.", "title": "Configure CORS"}, {"location": "janssen-server/developer/cors/#parameters-supported-by-cors-filters", "text": "CORS Filter supports the following initialization parameters: Attribute Description corsAllowedOrigins A list of origins that are allowed to access the resource. A * can be specified to enable access to resource from any origin. Otherwise, a whitelist of comma separated origins can be provided. Eg: http://www.w3.org , https://www.apache.org. Defaults: * (Any origin is allowed to access the resource). corsAllowedMethods A comma separated list of HTTP methods that can be used to access the resource, using cross-origin requests. These are the methods which will also be included as part of Access-Control-Allow-Methods header in pre-flight response. Eg: GET , POST . Defaults: GET , POST , HEAD , OPTIONS corsExposedHeaders A comma separated list of request headers that can be used when making an actual request. These headers will also be returned as part of Access-Control-Allow-Headers header in a pre-flight response. Eg: Origin, Accept . Defaults: Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers corsSupportCredentials A flag that indicates whether the resource supports user credentials. This flag is exposed as part of Access-Control-Allow-Credentials header in a pre-flight response. It helps browser determine whether or not an actual request can be made using credentials. Defaults: true corsLoggingEnabled Value to enable logging, Setting the value to False will disable logging. Defaults: true corsPreflightMaxAge The duration in seconds the browser is allowed to cache the result of the pre-flight request. This will be included as part of the Access-Control-Max-Age header in the pre-flight response. A negative value will prevent the CORS Filter from adding this response header to the pre-flight response. Defaults: 1800 corsRequestDecorate A flag to control if CORS specific attributes should be added to the HttpServletRequest object. Defaults: true", "title": "Parameters supported by CORS Filters"}, {"location": "janssen-server/developer/external-libraries/", "tags": ["administration", "developer", "external", "libraries"], "text": "Using External Libraries In Interception Scripts # Janssen Server Interception script is a very powerful tool that enables developers to control many different aspects of the authentication process. It is possible to use external libraries in interception scripts. It is possible to use external libraries Java libraries in pure Java based interception script. If the interception script is implemented in Jython then it is possible to use external Java libraries as well as external Python libraries .", "title": "External Libraries"}, {"location": "janssen-server/developer/external-libraries/#using-external-libraries-in-interception-scripts", "text": "Janssen Server Interception script is a very powerful tool that enables developers to control many different aspects of the authentication process. It is possible to use external libraries in interception scripts. It is possible to use external libraries Java libraries in pure Java based interception script. If the interception script is implemented in Jython then it is possible to use external Java libraries as well as external Python libraries .", "title": "Using External Libraries In Interception Scripts"}, {"location": "janssen-server/developer/managed-beans/", "tags": ["administration", "developer", "bean", "CdiUtil"], "text": "Ready-to-use code in Custom script: # Jans-auth server uses Weld 3.0 (JSR-365 aka CDI 2.0) for managed beans. The most useful functions are implemented through a set of beans which can be re-used in all custom scripts. Obtaining a bean inside a custom script: # CdiUtil used to obtain managed beans inside a custom script. Relevant methods: Signature Description T bean(Class clazz) Gets the managed bean belonging to the class passed as parameter Usage (jython code): Suppose UserService and AuthenticationService beans have to be referenced in the code, it can be done as below: from io.jans.as.server.service import UserService from io.jans.as.server.service import AuthenticationService ... userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) Commonly used beans: # 1. AuthenticationService # Allows to authenticate a user or obtain the current authenticated user Relevant methods: Signature Description boolean authenticate(String userName) Performs authentication for the user whose identifier ( userName ) is passed as parameter boolean authenticate(String userName, String password) Performs authentication for the user whose identifier ( userName ) is passed as parameter. The password supplied must be the correct password of the user in question User getAuthenticatedUser() Returns a representation of the currently authenticated user. null if no user is currently authenticated. See User data object Usage: from io.jans.as.server.service import AuthenticationService ... #1. authenticate a user using username and password authenticationService = CdiUtil.bean(AuthenticationService) logged_in = authenticationService.authenticate(user_name, user_password) # 2. authenticate method without passing password parameter logged_in = authenticationService.authenticate(user_name) #3. obtain an authenticated user user = authenticationService.getAuthenticatedUser() userName = user.getUserId() emailIds = user.getAttribute(\"oxEmailAlternate\") 2. UserService # Allows CRUD operations for users to the local persistence. Relevant methods: Signature Description User addUser(User user, boolean active) Creates a new user based on the representation passed as parameter. active parameter denotes whether user status ( gluuStatus attribute) will be active or register User addUserAttribute(String userId, String attributeName, String attributeValue) Adds an attribute to the user identified by userId in the database with the name and value passed. Returns a representation of the modified user or null in case of failure or if such name/attribute is already part of such user boolean addUserAttribute(User user, String attributeName, String attributeValue) Adds an attribute to the user object with the name and value passed. This method only alters the user argument and does not persist changes. Returns false if such name/attribute is already part of user User addUserAttributeByUserInum(String userInum, String attributeName, String attributeValue) Adds an attribute to the user whose inum attribute (in the database) equals to userInum using the name and value passed. Returns a representation of the modified user or null in case of failure or if such name/attribute is already part of such user CustomAttribute getCustomAttribute(User user, String attributeName) Gets a representation of the attribute whose name is passed for the user in question ( user ). Returns null if no such attribute is populated String getDnForUser(String inum) Obtains the DN (distinguished name) of the user whose inum attribute equals to userInum (no check that such user may exist is actually made) User getUser(String userId, String... returnAttributes) Retrieves a user representation for the user identified with userId containing only the attributes requested ( returnAttributes ). null is returned if no such user exists User getUserByAttribute(String attributeName, String attributeValue) Retrieves a user (first available) such that the attribute referenced ( attributeName ) has the value passed ( attributeValue ). null is returned if no such user exists String getUserInum(String userId) Retrieves the inum database attribute for the user identified with userId . null is returned if no such user exists User removeUserAttribute(String userId, String attributeName, String attributeValue) Removes attributeValue from the values of the attribute whose name is passed ( attributeName ) for the user identified with userId User replaceUserAttribute(String userId, String attributeName, String oldAttributeValue, String newAttributeValue) Updates the user identified with userId by replacing the value of the attribute attributeName with the value passed. null is returned if no such user exists void setCustomAttribute(User user, String attributeName, String attributeValue) Sets the value of the attribute attributeName with the single value attributeValue for the user representation passes as parameter. This method does not persist changes User updateUser(User user) Updates the user represented by user object in the database Usage # a. Add a user # from io.jans.as.common.service.common import UserService from io.jans.orm.model.base import CustomObjectAttribute; ... new_user = User() found_user.getCustomAttributes().add(new CustomObjectAttribute(\"address\", Arrays.asList(\"London\", \"Texas\", \"Kiev\"))); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"birthdate\", new Date())); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"scimCustomThird\", 18)); found_user.setUserRole(UserRole.ADMIN); found_user.setMemberOf(Arrays.asList(\"group_1\", \"group_2\", \"group_3\")); CustomObjectAttribute multiValuedSingleValue = new CustomObjectAttribute(\"oxExternalUid\", \"multivalued_single_valued\"); multiValuedSingleValue.setMultiValued(true); foundUser.getCustomAttributes().add(multiValuedSingleValue); new_user = CdiUtil.bean(UserService).addUser(new_user, True) b. Add user attributes # userObject = userService.addUserAttribute(user_name, \"oxExternalUid\", cert_user_external_uid, true) c. Get User # # example 1 - get User by userId user = userService.getUser(user_name) # example 2 - get User by User-Id only if attribute oxExternalUid is populated user = userService.getUser(user_name, \"oxExternalUid\") customAttributeValue = userService.getCustomAttribute(user, \"oxExternalUid\") d. Get specific User attribute # status_attribute_value = userService.getCustomAttribute(find_user_by_uid, \"gluuStatus\") e. Replace user attributes # userService.replaceUserAttribute(user_name, \"oxOTPCache\", cachedOTP, localTotpKey) f. Remove user attribute # userService.removeUserAttribute(user.getUserId(),\"oxTrustExternalId\", \"wwpass:%s\"%puid) g. Update users # found_user = userService.getUser(user_name) found_user.getCustomAttributes().add(new CustomObjectAttribute(\"address\", Arrays.asList(\"London\", \"Texas\", \"Kiev\"))); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"birthdate\", new Date())); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"scimCustomThird\", 18)); found_user.setUserRole(UserRole.ADMIN); found_user.setMemberOf(Arrays.asList(\"group_1\", \"group_2\", \"group_3\")); userService.updateUser(found_user) 4. User # A class employed to represent a user entry in the persistence. Provides getters and setters to retrieve and assign value(s) for attributes 5. CustomAttribute # A class that models an attribute. An attribute has a name and a collection of associated values 6. Identity # The authentication flow in jans-auth server is stateless and the instance is preserved because the Identity parameters (another name for session parameters) are persisted in databases. A function in the PersonAuthenticationType script called getExtraParametersForStep should be overridden to include any new session variable. The underlying Jans-auth server takes care of retrieving it, persisting it etc. def getExtraParametersForStep(self, configurationAttributes, step): return Arrays.asList(\"sessionParamName1\", \"sessionParamName2\", \"sessionParamName3\") Bean details: |Signature|Description| |-|-| | Object getWorkingParameter(String name) |Retrieves a working parameter by name previously set via setWorkingParameter | | void setWorkingParameter(String name, Object value) |Binds data to a name for further use in an authentication flow. Recommended values to store are String s| | SessionId getSessionId() |Retrieves a reference to the associated server session object, see SessionId | Usage from io.jans.as.server.security import Identity identity = CdiUtil.bean(Identity) #1. newExpDate = identity.getWorkingParameter(\"expDate\") #2. identity.setWorkingParameter(\"expDate\", expDate) #3. session_attributes = identity.getSessionId().getSessionAttributes() session_attributes.containsKey(\"remote_ip\") 8. SessionIdService # #1. get session sessionIdservice = CdiUtil.bean(SessionIdService).getSessionId() #2. update session sessionIdservice.getSessionAttributes().put(key, value) sessionIdservice.updateSessionId(session) 9. GrantService # 10. ClientService : Provides operations with clients. # Usage: from io.jans.as.server.service import ClientService clientService = CdiUtil.bean(ClientService) client = clientService.getClient(clientId) 7. HttpService: HttpService # Provides utility methods to execute HTTP requests, manipulate responses, etc Relevant methods: Signature Description HttpClient getHttpsClient() Returns an instance of org.apache.http.client.HttpClient (see oxcore-util class SslDefaultHttpClient ) HttpServiceResponse executeGet(HttpClient httpClient, String requestUri) Perform a GET on the URI requested. Returns an instance of io.jans.as.server.model.net.HttpServiceResponse (a wrapper on org.apache.http.HttpResponse ) byte[] getResponseContent(HttpResponse httpResponse) Consumes the bytes of the associated response. Returns null if the response status code is not 200 (OK) 8. CacheService # Provides a unified means to interact with the underlying cache provider configured in the Jans-auth Server Relevant methods: Signature Description void clear() Flushes the whole cache Object get(String key) Retrieves the value of key in the cache. null if there is no such key present void put(int expirationInSeconds, String key, Object object) Puts an object in the cache associated to the key passed. An expiration in seconds can be provided put(String key, Object object) Puts an object in the cache associated to the key passed. The expiration used is the default expiration configured in Gluu void remove(String key) Removes an entry from the cache 9. FacesService : Provides utilities to properly build encoded URLs and make redirections. This class is used a great deal in custom scripts # Relevant methods: Signature Description void redirectToExternalURL(String url) Redirects the user's browser to the URL passed as parameter String encodeParameters(String url, Map<String, Object> parameters) Builds a URL by appending query parameters as supplied in parameters map. Every value in the map is properly URL-encoded 10. FacesMessages # Allows manipulation of JSF context messages Relevant methods: Signature Description void add(Severity severity, String message) Adds a message to the JSF context with the severity ( javax.faces.application.FacesMessage.Severity ) specified void clear() Clears the messages of the JSF context String evalAsString(String expression) Evaluates an EL expression using the JSF context and returns the result as a String void setKeepMessages() Sets the \"keep messages\" property of the JSF flash 11. StringHelper # Provides many utility methods that often arise in the manipulation of Strings Usage: from io.jans.util import StringHelper isNotEmptyString # if StringHelper.isNotEmptyString(user_name): # do something equalsIgnoreCase # if StringHelper.equalsIgnoreCase(authentication_mode, \"one_step\"): # do something isEmpty # if StringHelper.isEmpty(auth_method): # do something split # allowedClientsListArray = StringHelper.split(allowedClientsList, \",\") toLowerCase # remoteAttribute = StringHelper.toLowerCase(remoteAttributesListArray[i]) base64urlencode # StringUtils.base64urlencode(input); 13. EncryptionService # Allows to encrypt/decrypt strings using a 3DES cipher whose salt is found in /etc/jans/conf/salt Relevant methods: Signature Description String decrypt(String encryptedString) Decrypts the encrypted string supplied Properties decryptAllProperties(Properties connectionProperties) Returns a java.util.Properties object with all decrypted values found in connectionProperties String encrypt(String unencryptedString) Encrypts the string supplied Usage: # from io.jans.as.common.service.common import EncryptionService .... encryptionService = CdiUtil.bean(EncryptionService) pwd_decrypted = encryptionService.decrypt(\"stringtobedecrypted\") 14. Base64Util # Usage: from io.jans.as.model.util import Base64Util .... Base64Util.base64urldecodeToString(input_string) Base64Util.base64urlencode(input_string.encode('utf-8')));", "title": "Managed Beans"}, {"location": "janssen-server/developer/managed-beans/#ready-to-use-code-in-custom-script", "text": "Jans-auth server uses Weld 3.0 (JSR-365 aka CDI 2.0) for managed beans. The most useful functions are implemented through a set of beans which can be re-used in all custom scripts.", "title": "Ready-to-use code in Custom script:"}, {"location": "janssen-server/developer/managed-beans/#obtaining-a-bean-inside-a-custom-script", "text": "CdiUtil used to obtain managed beans inside a custom script. Relevant methods: Signature Description T bean(Class clazz) Gets the managed bean belonging to the class passed as parameter Usage (jython code): Suppose UserService and AuthenticationService beans have to be referenced in the code, it can be done as below: from io.jans.as.server.service import UserService from io.jans.as.server.service import AuthenticationService ... userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService)", "title": "Obtaining a bean inside a custom script:"}, {"location": "janssen-server/developer/managed-beans/#commonly-used-beans", "text": "", "title": "Commonly used beans:"}, {"location": "janssen-server/developer/managed-beans/#1-authenticationservice", "text": "Allows to authenticate a user or obtain the current authenticated user Relevant methods: Signature Description boolean authenticate(String userName) Performs authentication for the user whose identifier ( userName ) is passed as parameter boolean authenticate(String userName, String password) Performs authentication for the user whose identifier ( userName ) is passed as parameter. The password supplied must be the correct password of the user in question User getAuthenticatedUser() Returns a representation of the currently authenticated user. null if no user is currently authenticated. See User data object Usage: from io.jans.as.server.service import AuthenticationService ... #1. authenticate a user using username and password authenticationService = CdiUtil.bean(AuthenticationService) logged_in = authenticationService.authenticate(user_name, user_password) # 2. authenticate method without passing password parameter logged_in = authenticationService.authenticate(user_name) #3. obtain an authenticated user user = authenticationService.getAuthenticatedUser() userName = user.getUserId() emailIds = user.getAttribute(\"oxEmailAlternate\")", "title": "1. AuthenticationService"}, {"location": "janssen-server/developer/managed-beans/#2-userservice", "text": "Allows CRUD operations for users to the local persistence. Relevant methods: Signature Description User addUser(User user, boolean active) Creates a new user based on the representation passed as parameter. active parameter denotes whether user status ( gluuStatus attribute) will be active or register User addUserAttribute(String userId, String attributeName, String attributeValue) Adds an attribute to the user identified by userId in the database with the name and value passed. Returns a representation of the modified user or null in case of failure or if such name/attribute is already part of such user boolean addUserAttribute(User user, String attributeName, String attributeValue) Adds an attribute to the user object with the name and value passed. This method only alters the user argument and does not persist changes. Returns false if such name/attribute is already part of user User addUserAttributeByUserInum(String userInum, String attributeName, String attributeValue) Adds an attribute to the user whose inum attribute (in the database) equals to userInum using the name and value passed. Returns a representation of the modified user or null in case of failure or if such name/attribute is already part of such user CustomAttribute getCustomAttribute(User user, String attributeName) Gets a representation of the attribute whose name is passed for the user in question ( user ). Returns null if no such attribute is populated String getDnForUser(String inum) Obtains the DN (distinguished name) of the user whose inum attribute equals to userInum (no check that such user may exist is actually made) User getUser(String userId, String... returnAttributes) Retrieves a user representation for the user identified with userId containing only the attributes requested ( returnAttributes ). null is returned if no such user exists User getUserByAttribute(String attributeName, String attributeValue) Retrieves a user (first available) such that the attribute referenced ( attributeName ) has the value passed ( attributeValue ). null is returned if no such user exists String getUserInum(String userId) Retrieves the inum database attribute for the user identified with userId . null is returned if no such user exists User removeUserAttribute(String userId, String attributeName, String attributeValue) Removes attributeValue from the values of the attribute whose name is passed ( attributeName ) for the user identified with userId User replaceUserAttribute(String userId, String attributeName, String oldAttributeValue, String newAttributeValue) Updates the user identified with userId by replacing the value of the attribute attributeName with the value passed. null is returned if no such user exists void setCustomAttribute(User user, String attributeName, String attributeValue) Sets the value of the attribute attributeName with the single value attributeValue for the user representation passes as parameter. This method does not persist changes User updateUser(User user) Updates the user represented by user object in the database", "title": "2. UserService"}, {"location": "janssen-server/developer/managed-beans/#usage", "text": "", "title": "Usage"}, {"location": "janssen-server/developer/managed-beans/#a-add-a-user", "text": "from io.jans.as.common.service.common import UserService from io.jans.orm.model.base import CustomObjectAttribute; ... new_user = User() found_user.getCustomAttributes().add(new CustomObjectAttribute(\"address\", Arrays.asList(\"London\", \"Texas\", \"Kiev\"))); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"birthdate\", new Date())); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"scimCustomThird\", 18)); found_user.setUserRole(UserRole.ADMIN); found_user.setMemberOf(Arrays.asList(\"group_1\", \"group_2\", \"group_3\")); CustomObjectAttribute multiValuedSingleValue = new CustomObjectAttribute(\"oxExternalUid\", \"multivalued_single_valued\"); multiValuedSingleValue.setMultiValued(true); foundUser.getCustomAttributes().add(multiValuedSingleValue); new_user = CdiUtil.bean(UserService).addUser(new_user, True)", "title": "a. Add a user"}, {"location": "janssen-server/developer/managed-beans/#b-add-user-attributes", "text": "userObject = userService.addUserAttribute(user_name, \"oxExternalUid\", cert_user_external_uid, true)", "title": "b. Add user attributes"}, {"location": "janssen-server/developer/managed-beans/#c-get-user", "text": "# example 1 - get User by userId user = userService.getUser(user_name) # example 2 - get User by User-Id only if attribute oxExternalUid is populated user = userService.getUser(user_name, \"oxExternalUid\") customAttributeValue = userService.getCustomAttribute(user, \"oxExternalUid\")", "title": "c. Get User"}, {"location": "janssen-server/developer/managed-beans/#d-get-specific-user-attribute", "text": "status_attribute_value = userService.getCustomAttribute(find_user_by_uid, \"gluuStatus\")", "title": "d. Get specific User attribute"}, {"location": "janssen-server/developer/managed-beans/#e-replace-user-attributes", "text": "userService.replaceUserAttribute(user_name, \"oxOTPCache\", cachedOTP, localTotpKey)", "title": "e. Replace user attributes"}, {"location": "janssen-server/developer/managed-beans/#f-remove-user-attribute", "text": "userService.removeUserAttribute(user.getUserId(),\"oxTrustExternalId\", \"wwpass:%s\"%puid)", "title": "f. Remove user attribute"}, {"location": "janssen-server/developer/managed-beans/#g-update-users", "text": "found_user = userService.getUser(user_name) found_user.getCustomAttributes().add(new CustomObjectAttribute(\"address\", Arrays.asList(\"London\", \"Texas\", \"Kiev\"))); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"birthdate\", new Date())); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"scimCustomThird\", 18)); found_user.setUserRole(UserRole.ADMIN); found_user.setMemberOf(Arrays.asList(\"group_1\", \"group_2\", \"group_3\")); userService.updateUser(found_user)", "title": "g. Update users"}, {"location": "janssen-server/developer/managed-beans/#4-user", "text": "A class employed to represent a user entry in the persistence. Provides getters and setters to retrieve and assign value(s) for attributes", "title": "4. User"}, {"location": "janssen-server/developer/managed-beans/#5-customattribute", "text": "A class that models an attribute. An attribute has a name and a collection of associated values", "title": "5. CustomAttribute"}, {"location": "janssen-server/developer/managed-beans/#6-identity", "text": "The authentication flow in jans-auth server is stateless and the instance is preserved because the Identity parameters (another name for session parameters) are persisted in databases. A function in the PersonAuthenticationType script called getExtraParametersForStep should be overridden to include any new session variable. The underlying Jans-auth server takes care of retrieving it, persisting it etc. def getExtraParametersForStep(self, configurationAttributes, step): return Arrays.asList(\"sessionParamName1\", \"sessionParamName2\", \"sessionParamName3\") Bean details: |Signature|Description| |-|-| | Object getWorkingParameter(String name) |Retrieves a working parameter by name previously set via setWorkingParameter | | void setWorkingParameter(String name, Object value) |Binds data to a name for further use in an authentication flow. Recommended values to store are String s| | SessionId getSessionId() |Retrieves a reference to the associated server session object, see SessionId | Usage from io.jans.as.server.security import Identity identity = CdiUtil.bean(Identity) #1. newExpDate = identity.getWorkingParameter(\"expDate\") #2. identity.setWorkingParameter(\"expDate\", expDate) #3. session_attributes = identity.getSessionId().getSessionAttributes() session_attributes.containsKey(\"remote_ip\")", "title": "6. Identity"}, {"location": "janssen-server/developer/managed-beans/#8-sessionidservice", "text": "#1. get session sessionIdservice = CdiUtil.bean(SessionIdService).getSessionId() #2. update session sessionIdservice.getSessionAttributes().put(key, value) sessionIdservice.updateSessionId(session)", "title": "8. SessionIdService"}, {"location": "janssen-server/developer/managed-beans/#9-grantservice", "text": "", "title": "9. GrantService"}, {"location": "janssen-server/developer/managed-beans/#10-clientservice-provides-operations-with-clients", "text": "Usage: from io.jans.as.server.service import ClientService clientService = CdiUtil.bean(ClientService) client = clientService.getClient(clientId)", "title": "10. ClientService : Provides operations with clients."}, {"location": "janssen-server/developer/managed-beans/#7-httpservice-httpservice", "text": "Provides utility methods to execute HTTP requests, manipulate responses, etc Relevant methods: Signature Description HttpClient getHttpsClient() Returns an instance of org.apache.http.client.HttpClient (see oxcore-util class SslDefaultHttpClient ) HttpServiceResponse executeGet(HttpClient httpClient, String requestUri) Perform a GET on the URI requested. Returns an instance of io.jans.as.server.model.net.HttpServiceResponse (a wrapper on org.apache.http.HttpResponse ) byte[] getResponseContent(HttpResponse httpResponse) Consumes the bytes of the associated response. Returns null if the response status code is not 200 (OK)", "title": "7. HttpService: HttpService"}, {"location": "janssen-server/developer/managed-beans/#8-cacheservice", "text": "Provides a unified means to interact with the underlying cache provider configured in the Jans-auth Server Relevant methods: Signature Description void clear() Flushes the whole cache Object get(String key) Retrieves the value of key in the cache. null if there is no such key present void put(int expirationInSeconds, String key, Object object) Puts an object in the cache associated to the key passed. An expiration in seconds can be provided put(String key, Object object) Puts an object in the cache associated to the key passed. The expiration used is the default expiration configured in Gluu void remove(String key) Removes an entry from the cache", "title": "8. CacheService"}, {"location": "janssen-server/developer/managed-beans/#9-facesservice-provides-utilities-to-properly-build-encoded-urls-and-make-redirections-this-class-is-used-a-great-deal-in-custom-scripts", "text": "Relevant methods: Signature Description void redirectToExternalURL(String url) Redirects the user's browser to the URL passed as parameter String encodeParameters(String url, Map<String, Object> parameters) Builds a URL by appending query parameters as supplied in parameters map. Every value in the map is properly URL-encoded", "title": "9. FacesService : Provides utilities to properly build encoded URLs and make redirections. This class is used a great deal in custom scripts"}, {"location": "janssen-server/developer/managed-beans/#10-facesmessages", "text": "Allows manipulation of JSF context messages Relevant methods: Signature Description void add(Severity severity, String message) Adds a message to the JSF context with the severity ( javax.faces.application.FacesMessage.Severity ) specified void clear() Clears the messages of the JSF context String evalAsString(String expression) Evaluates an EL expression using the JSF context and returns the result as a String void setKeepMessages() Sets the \"keep messages\" property of the JSF flash", "title": "10. FacesMessages"}, {"location": "janssen-server/developer/managed-beans/#11-stringhelper", "text": "Provides many utility methods that often arise in the manipulation of Strings Usage: from io.jans.util import StringHelper", "title": "11. StringHelper"}, {"location": "janssen-server/developer/managed-beans/#isnotemptystring", "text": "if StringHelper.isNotEmptyString(user_name): # do something", "title": "isNotEmptyString"}, {"location": "janssen-server/developer/managed-beans/#equalsignorecase", "text": "if StringHelper.equalsIgnoreCase(authentication_mode, \"one_step\"): # do something", "title": "equalsIgnoreCase"}, {"location": "janssen-server/developer/managed-beans/#isempty", "text": "if StringHelper.isEmpty(auth_method): # do something", "title": "isEmpty"}, {"location": "janssen-server/developer/managed-beans/#split", "text": "allowedClientsListArray = StringHelper.split(allowedClientsList, \",\")", "title": "split"}, {"location": "janssen-server/developer/managed-beans/#tolowercase", "text": "remoteAttribute = StringHelper.toLowerCase(remoteAttributesListArray[i])", "title": "toLowerCase"}, {"location": "janssen-server/developer/managed-beans/#base64urlencode", "text": "StringUtils.base64urlencode(input);", "title": "base64urlencode"}, {"location": "janssen-server/developer/managed-beans/#13-encryptionservice", "text": "Allows to encrypt/decrypt strings using a 3DES cipher whose salt is found in /etc/jans/conf/salt Relevant methods: Signature Description String decrypt(String encryptedString) Decrypts the encrypted string supplied Properties decryptAllProperties(Properties connectionProperties) Returns a java.util.Properties object with all decrypted values found in connectionProperties String encrypt(String unencryptedString) Encrypts the string supplied", "title": "13. EncryptionService"}, {"location": "janssen-server/developer/managed-beans/#usage_1", "text": "from io.jans.as.common.service.common import EncryptionService .... encryptionService = CdiUtil.bean(EncryptionService) pwd_decrypted = encryptionService.decrypt(\"stringtobedecrypted\")", "title": "Usage:"}, {"location": "janssen-server/developer/managed-beans/#14-base64util", "text": "Usage: from io.jans.as.model.util import Base64Util .... Base64Util.base64urldecodeToString(input_string) Base64Util.base64urlencode(input_string.encode('utf-8')));", "title": "14. Base64Util"}, {"location": "janssen-server/developer/xframe/", "tags": ["administration", "installation"], "text": "X-Frame-Options Header # Overview # AS has io.jans.as.server.filter.HeadersFilter which is responsible for attaching headers to server responses. <filter-mapping> <filter-name>HeadersFilter</filter-name> <url-pattern /> </filter-mapping> Configure X-Frame-Options Header # The X-Frame-Options HTTP response header can be used to indicate whether a browser should be allowed to render a page in a , , or . Sites can use this to avoid click-jacking attacks, by ensuring that their content is not embedded into other sites. There are two AS configuration properties related to X-Frame-Options : xframeOptionsHeaderValue - sets value of X-Frame-Options header. Default value is SAMEORIGIN . Possible values are: SAMEORIGIN or DENY . applyXFrameOptionsHeaderIfUriContainsAny - array of strings. If incoming request contains any string from this array it will attach X-Frame-Options header to response. By default AS attaches X-Frame-Options header to all responses where request uri contains .htm . It means for all AS pages.", "title": "X-Frame-Options"}, {"location": "janssen-server/developer/xframe/#x-frame-options-header", "text": "", "title": "X-Frame-Options Header"}, {"location": "janssen-server/developer/xframe/#overview", "text": "AS has io.jans.as.server.filter.HeadersFilter which is responsible for attaching headers to server responses. <filter-mapping> <filter-name>HeadersFilter</filter-name> <url-pattern /> </filter-mapping>", "title": "Overview"}, {"location": "janssen-server/developer/xframe/#configure-x-frame-options-header", "text": "The X-Frame-Options HTTP response header can be used to indicate whether a browser should be allowed to render a page in a , , or . Sites can use this to avoid click-jacking attacks, by ensuring that their content is not embedded into other sites. There are two AS configuration properties related to X-Frame-Options : xframeOptionsHeaderValue - sets value of X-Frame-Options header. Default value is SAMEORIGIN . Possible values are: SAMEORIGIN or DENY . applyXFrameOptionsHeaderIfUriContainsAny - array of strings. If incoming request contains any string from this array it will attach X-Frame-Options header to response. By default AS attaches X-Frame-Options header to all responses where request uri contains .htm . It means for all AS pages.", "title": "Configure X-Frame-Options Header"}, {"location": "janssen-server/developer/agama/advanced-usages/", "tags": ["developer", "agama"], "text": "Advanced usages # UI templates # Template overrides # Template overrides is a mechanism that allows templates customization and promotes flows reuse. If an existing flow serves well the needs of a new flow you are writing, with this feature you can homogenize your UI for a more pleasant user experience. To start, use Trigger to play around with the existing flow - as is - from the flow you are creating. Collect the URLs of the pages you are not comfortable with: grab them directly from the browser's address bar. Then proceed as follows with every URL to locate the actual templates physically: Remove the https://.../fl/ portion of the URL Split the URL obtained into two pieces: a folder name and a remainder . The remainder starts after the last slash found in the URL, and usually ends in .fls In your Janssen server, locate the directory /opt/jans/jetty/jans-auth/agama/ftl cd to the directory specified by the folder List the contents of the directory and pick the filename that best matches the remainder Save a copy of every selected file in the directory associated to your flow ( basePath directive) or in a subdirectory of it. Rename the files if desired too. Now, build the Override templates directive passing several pairs of strings separated by lines or spaces. Every pair consists of a string specifying the original template location, that is, <folder>/<filename> followed by the path to the new template version relative to the base path of your flow. Output encoding # By default, the engine sends rendered pages using UTF-8 character encoding. To specify a different encoding the ftl directive can be used in pages, for instance, <#ftl encoding=\"ISO-8859-5\"> . Always place this at the top of a template. Localization and internationalization # To allow templates render text according to users' language or country, you can add a file named labels.txt to the web directory of a project. There you can place the so-called \"internationalization labels\" (common UI-related messages) as per your needs. The file is expected to have a structure as follows: key = value ... more key/value pairs [ locale ID 1 ] key/value pairs for this locale [ locale ID 2 ] key/value pairs for this locale ... [ locale ID n ] key/value pairs for this locale Note how the file is split into sections for every locale to support. The first section (no locale) will contain the \"default\" labels - more on this later. One locale conveys mostly the same concept of a Java locale (class java.util.Locale ). In this case, a locale represents a language, country/region, and variant combination. Examples of locale IDs are: de_CH : German as used in Switzerland ca_ES_VALENCIA : Catalan as used in Spain (province of Valencia) th_TH_TH : Thai as used in Thailand together with Thai digits ja : Japanese (in general) There may be several sections regarding the same language, like de_CH , de_DE , de_LU , and plain de . Agama engine will pick the text from the section that best maches the settings of the end-user browser (normally, this is supplied through the Accept-Language HTTP header). As an example, if the browser's preferred language is German from Luxembourg, the lookup is made in de_LU section. If no text is found there, the de section is tried. The opening \"no locale\" section is used as a last resort - that's why it is said to contain the \"default\" labels. To reference a label from a template an expression like ${labels(\"<KEY>\")} can be used. This will retrieve the proper text using the rules just described. When the lookup fails thoroughly (no way to found a label matching the key), the four character string null is returned. This helps to easily locate template issues if any. A value (message) associated to a key can contain placeholders where data can be injected. Suppose the following key/value pair: disk.count = The disk {1} contains {0} file(s) Using ${labels(\"disk.count\")} will just retrieve the message as is, however, positional arguments can be passed. As an example, ${labels(\"disk.count\", 7, \"SSD-NVME-123\")} will generate The disk SSD-NVME-123 contains 7 file(s) . Note parameters are not restricted to literals (fixed values) like 0 , false , or \"world\" . Variables can also be used. It is recommended to employ literals/variables whose data types are string, number, date, or boolean only. Labels are global: not only can they be accessed from the project where they are originally defined but from any other project. This allows template overrides to work smoothly, however, it brings the possibility of key collisions, that is, two or more projects defining labels with the same keys. To mitigate this problem, it is recommended to prefix all keys with the name/identifier of the originating project, like: myproject.salutation = hello! [es] myproject.salutation = hola! [it] myproject.salutation = ciao! When leaving salutation alone, it is likely other projects added to the server in the future may contain their own version of salutation leading to unexpected results. Additional notes: Language codes should follow the ISO 639 alpha-2 standard Country/region codes should be driven by ISO 3166 alpha-2 or UN M.49 numeric-3 area code Except for the locale section headings, the syntax of labels.txt adheres to that of Java properties files. This is a human-friendly, low-surpise format: a label key starts a line and its value comes after an equal sign or a colon. For readability one or more empty lines can be used between contiguous key/value pairs. Any line starting with ! or # is ignored and thus can be used as a comment or note When positional arguments are passed, Java class java.text.MessageFormat is internally employed. This allows powerful formatting and proper handling of plurals. If for some reason, formatting fails, the resulting string will be error! . Check the server logs and try to simplify your message in this case Access to AS labels # The jans-auth server comes with a series of files known as \"resource bundles\" that follow the naming jans-auth_xx.properties where xx represents an ISO 639 language code. Bundles can be added or overridden by placing suitable properties files in directory /opt/jans/jetty/jans-auth/custom/i18n . Strings stored in these bundles can be accessed from templates using expressions like ${msgs.<KEY>} . As most keys in resource bundles contain dot characters, the alternative notation ${msgs[\"KEY\"]} works better for FreeMarker, for example ${msgs[\"login.errorMessage\"]} . Whenever possible, it is recommended to place your internationalization labels in the web folder of the project and use the ${labels(... notation instead. Note msgs has no support for parameterized placeholders: strings are all static. Reusable templates # A widespread practice in web page authoring is to compose pages based on reusable pieces. As an example, the need for a common header and footer is ubiquitous in HTML projects. With FreeMarker, composition can be achieved by means of macros . These are the equivalent to functions in programming, they can generate output based on parameters passed and can be called anywhere in a template. Agama already makes use of macros for this purpose. Take a look at the ftlh files found at /opt/jans/jetty/jans-auth/agama . These templates are used to present errors, like timeouts, flow crashes, etc. Example: Here, two pages will be built to demonstrate the concept of composition in FreeMarker templates: a homepage and an \"about us\" page. These will be made up of a header, a sidebar, and their respective main content. Assume the sidebar should be shown only for the home page. Note FreeMarker comments are of the form <#-- This won't be printed in the output --> One way to structure the solution is the following: <#-- aside.ftlh --> <#macro sidebar> <aside> <h2>Recommended tracks</h2> <nav> <ul> <li><a href=\"#\">Efilnikufesin</a></li> <li><a href=\"#\">P.O.N.X.</a></li> <!--li><a href=\"#\">Planet caravan</a></li--> </ul> </nav> </aside> </#macro> aside.ftlh has static markup for a sidebar. It is defined inside a macro called sidebar . <#-- commons.ftlh --> <#import \"aside.ftlh\" as sbar> <#macro header> <header> <h1>Welcome</h1> <nav> <ul> <li><a href=\"#\">Home</a></li> <li><a href=\"#\">About</a></li> <li><a href=\"#\">Sign Up</a></li> </ul> </nav> </header> </#macro> <#macro main useSidebar=false> <!DOCTYPE html> <html> <body> <@header/> <#if useSidebar> <@sbar.sidebar/> </#if> <#nested> </body> </html> </#macro> commons.ftlh template imports aside.ftlh associating it with the shortname sbar . Additionally: It defines two macros: header and main . The macro header generates a static navigation menu main macro is the skeleton of a very simple HTML page main has a parameter named useSidebar whose default is false The sidebar macro is called using <@sbar.sidebar/> while header with <@header/> (local macro) <#-- index.ftlh --> <#import \"commons.ftlh\" as com> <@com.main useSidebar=true> <article> <h1>This is the index page!</h1> <p>Temporibus ut nisi quibusdam iusto vitae similique laudantium. Minima cumque ducimus sit ut dolores. Autem quam soluta illo et omnis expedita voluptas magnam. Sit aperiam laboriosam magnam et amet deleniti. Sit et velit unde quibusdam esse ullam voluptatem. Enim sint blanditiis dolores. Laborum velit eos dolor ad quaerat. Quo tempora excepturi enim dolor harum sunt ipsa. Quis sit dolorem harum ipsa fuga voluptatem commodi. </p> </article> </@com.main> index.ftlh is the homepage: Template commons.ftlh is imported and its macro main called passing true for useSidebar The markup inside <@com.main... tag is the content to be \"inserted\" when the <#nested> directive is reached <#-- about.ftlh --> <#import \"commons.ftlh\" as com> <@com.main> <article> <h1>About us</h1> <p>We don't know ourselves very well.</p> </article> </@com.main> about.ftlh is the \"about us\" page. It works like the homepage except the sidebar will not be shown. Cancellation # Important Ensure you have previously gone through the contents of this page before proceeding This is a feature that in conjuction with template overrides allows developers to implement alternative routing and backtracking. Suppose a flow is designed to reuse two or more existing subflows. As expected these subflows are neither aware of each other nor of its parent. How can the parent make so that once the user has landed at a page belonging to a given subflow A be presented the alternative to take another route, say, to subflow B? Clearly a page at flow A can be overriden, however, how to abort A and make it jump to B? The answer is cancellation. Through flow cancellation, a running flow can be aborted and the control returned to one of its parents for further processing. This can achieved by overriding a template so that the POST to the current URL includes a form field named _abort . POSTing this way will provoke the associated Trigger call to return a value like { aborted: true, data: ..., url: ... } where data is a map consisting of the payload (form fields) sent with the POST. Thus, developers can build custom pages and add for example a button to provoke the cancellation. Then, back in the flow implementation take the user to the desired path. The url property will hold the URL where cancellation took place relative to https://your-server/jans-auth/fl/ . As an example, suppose there exists two flows that allow users to enter and validate a one-time passcode (OTP), one flow sends the OTP via e-mail while the other through an SMS. Assume these flows receive a user identifier as input and render a single UI page each to enter the received OTP. If we are interested in building a flow that prompts for username/password credentials and use the SMS-based OTP flow with a customization that consists of showing a link like \"Didn't get an SMS?, send the passcode to my e-mail\", the following is a sketch of an implementation: ... //validate username/password ... result = Trigger co.acme.SmsOTP userId Override templates \"path/to/enter_otp.ftlh\" \"cust_enter_otp.ftlh\" When result.aborted is true //The user clicked on \"send the passcode to my e-mail\" result = Trigger co.acme.EmailOTP userId When result.success is true result.data = { userId: userId } Finish result The overriden template cust_enter_otp.ftlh would have a form like: ... <form method=\"post\" enctype=\"application/x-www-form-urlencoded\"> <button type=\"submit\" name=\"_abort\"> Didn't get an SMS?, send the passcode to my e-mail</button> </form> Note you cannot make cancellation occur at an arbitrary point of a flow. It can only happen when a page has been rendered, that is, an RRF directive is in execution. When a flow is aborted and the control returned back to a parent, there is no way to \"resume\" execution of the flow target of the cancellation. Cancellation bubble-up # In order to override a page, the path to the corresponding template can be easily derived from the URL seen at the browser's address bar when the subflow is Trigger ed. Note the page may not necessarily belong directly to the subflow triggered but probably to another flow lying deep in a chain of Trigger invocations. As an example suppose you are interested in building a flow A that reuses flow B. You identify a page shown that needs to be overriden. It might happen this page is actually rendered by C - a flow that B in turn reuses. In scenarios like this cancellation still works transparently and developers need not be aware of flows dependencies. In practice, when cancellation occurs at C, it bubbles up to B and then to A, which is the target of this process. Note that even flow B (as is) may also be overriding C's templates. Resolution of a template path takes place from the inner to the outer flow, so it occurs this way in the example: path is as found in C's RRF instruction path is looked up on the list provided in B's Override templates . If a match is found, path is updated accordingly path is looked up on the list provided in A's Override templates . If a match is found, path is updated accordingly The page referenced by path is rendered Engine internals # Here we provide insight on some behavioral aspects of the engine that may result of interest to developers. Flow advance and navigation # Once a web page (or a response in general) is replied to a client (e.g. web browser), a POST is required to make the flow proceed . The POST is expected to be sent to the current URL only, otherwise, a 404 error will be thrown. The engine will then respond with a redirect (usually 301) so the client will GET the next URL to be rendered. This pattern of navigation is known as \"POST-REDIRECT-GET\". There is a clear correspondence of the \"current URL\" with the physical path of the template rendered. As an example, if the browser location shows https://<your-host>/jans-auth/fl/foo/bar.fls , the involved template is stored at /opt/jans/jetty/jans-auth/agama/ftl/foo and has name bar . This makes flows more predictable and easier to reason about. Note however URLs are not manipulable: an attempt to set the browser location to a URL corresponding to a different template will not make that template be rendered or provoke any unexpected jump in the flow control. Instead, an error page is shown that allows users to re-take where they left off or to restart from scratch. In other words, navigation honors the \"current flow URL\" avoiding attempts to re-visit past stages or make unexpected moves to future ones. Additionally, the engine by default sends responses with proper HTTP headers so page contents are not cached. This is key to prevent manipulation and allows a safe usage of the browser's back button, where it will not be possible to visit past stages. Code transpilation # The engine has some timers running in the background. One of them transpiles code when a change is detected in a given flow's source (written in Agama language). The transpilation process generates vanilla Javascript code runnable through Mozilla Rhino by using a transformation chain like (DSL) flow code -> (ANTLR4) parse tree -> (XML) abstract syntax tree -> JS. The transformation chain guarantees that a flow written in Agama DSL cannot: Access Java classes/instances not specified in the original flow code (i.e. the only bridge to Java world is via Call s) Access/modify the standard javascript built-in objects directly Conflict with javascript keywords Notes You can find the (ANTLR4) DSL grammar here . The last step of the transformation chain is carried out by means of this Freemarker transformer Other engine characteristics # Some interesting facts for the curious: The engine does not use asynchronous paradigms: no events, callbacks, extra threads, etc. All computations remain in the classic request/response servlet lifecycle familiar to most Java developers Continuations allow to express a flow as if it were a straight sequence of commands despite there are actual pauses in the middle: the gaps between an HTTP response and the next request Currently Mozilla Rhino seems to be the only mechanism that brings continuations into the Java language In order to preserve server statelessness, continuations are persisted to storage at every flow pause. This way the proper state can be restored when the continuation is resumed in the upcoming HTTP request", "title": "Advanced usages"}, {"location": "janssen-server/developer/agama/advanced-usages/#advanced-usages", "text": "", "title": "Advanced usages"}, {"location": "janssen-server/developer/agama/advanced-usages/#ui-templates", "text": "", "title": "UI templates"}, {"location": "janssen-server/developer/agama/advanced-usages/#template-overrides", "text": "Template overrides is a mechanism that allows templates customization and promotes flows reuse. If an existing flow serves well the needs of a new flow you are writing, with this feature you can homogenize your UI for a more pleasant user experience. To start, use Trigger to play around with the existing flow - as is - from the flow you are creating. Collect the URLs of the pages you are not comfortable with: grab them directly from the browser's address bar. Then proceed as follows with every URL to locate the actual templates physically: Remove the https://.../fl/ portion of the URL Split the URL obtained into two pieces: a folder name and a remainder . The remainder starts after the last slash found in the URL, and usually ends in .fls In your Janssen server, locate the directory /opt/jans/jetty/jans-auth/agama/ftl cd to the directory specified by the folder List the contents of the directory and pick the filename that best matches the remainder Save a copy of every selected file in the directory associated to your flow ( basePath directive) or in a subdirectory of it. Rename the files if desired too. Now, build the Override templates directive passing several pairs of strings separated by lines or spaces. Every pair consists of a string specifying the original template location, that is, <folder>/<filename> followed by the path to the new template version relative to the base path of your flow.", "title": "Template overrides"}, {"location": "janssen-server/developer/agama/advanced-usages/#output-encoding", "text": "By default, the engine sends rendered pages using UTF-8 character encoding. To specify a different encoding the ftl directive can be used in pages, for instance, <#ftl encoding=\"ISO-8859-5\"> . Always place this at the top of a template.", "title": "Output encoding"}, {"location": "janssen-server/developer/agama/advanced-usages/#localization-and-internationalization", "text": "To allow templates render text according to users' language or country, you can add a file named labels.txt to the web directory of a project. There you can place the so-called \"internationalization labels\" (common UI-related messages) as per your needs. The file is expected to have a structure as follows: key = value ... more key/value pairs [ locale ID 1 ] key/value pairs for this locale [ locale ID 2 ] key/value pairs for this locale ... [ locale ID n ] key/value pairs for this locale Note how the file is split into sections for every locale to support. The first section (no locale) will contain the \"default\" labels - more on this later. One locale conveys mostly the same concept of a Java locale (class java.util.Locale ). In this case, a locale represents a language, country/region, and variant combination. Examples of locale IDs are: de_CH : German as used in Switzerland ca_ES_VALENCIA : Catalan as used in Spain (province of Valencia) th_TH_TH : Thai as used in Thailand together with Thai digits ja : Japanese (in general) There may be several sections regarding the same language, like de_CH , de_DE , de_LU , and plain de . Agama engine will pick the text from the section that best maches the settings of the end-user browser (normally, this is supplied through the Accept-Language HTTP header). As an example, if the browser's preferred language is German from Luxembourg, the lookup is made in de_LU section. If no text is found there, the de section is tried. The opening \"no locale\" section is used as a last resort - that's why it is said to contain the \"default\" labels. To reference a label from a template an expression like ${labels(\"<KEY>\")} can be used. This will retrieve the proper text using the rules just described. When the lookup fails thoroughly (no way to found a label matching the key), the four character string null is returned. This helps to easily locate template issues if any. A value (message) associated to a key can contain placeholders where data can be injected. Suppose the following key/value pair: disk.count = The disk {1} contains {0} file(s) Using ${labels(\"disk.count\")} will just retrieve the message as is, however, positional arguments can be passed. As an example, ${labels(\"disk.count\", 7, \"SSD-NVME-123\")} will generate The disk SSD-NVME-123 contains 7 file(s) . Note parameters are not restricted to literals (fixed values) like 0 , false , or \"world\" . Variables can also be used. It is recommended to employ literals/variables whose data types are string, number, date, or boolean only. Labels are global: not only can they be accessed from the project where they are originally defined but from any other project. This allows template overrides to work smoothly, however, it brings the possibility of key collisions, that is, two or more projects defining labels with the same keys. To mitigate this problem, it is recommended to prefix all keys with the name/identifier of the originating project, like: myproject.salutation = hello! [es] myproject.salutation = hola! [it] myproject.salutation = ciao! When leaving salutation alone, it is likely other projects added to the server in the future may contain their own version of salutation leading to unexpected results. Additional notes: Language codes should follow the ISO 639 alpha-2 standard Country/region codes should be driven by ISO 3166 alpha-2 or UN M.49 numeric-3 area code Except for the locale section headings, the syntax of labels.txt adheres to that of Java properties files. This is a human-friendly, low-surpise format: a label key starts a line and its value comes after an equal sign or a colon. For readability one or more empty lines can be used between contiguous key/value pairs. Any line starting with ! or # is ignored and thus can be used as a comment or note When positional arguments are passed, Java class java.text.MessageFormat is internally employed. This allows powerful formatting and proper handling of plurals. If for some reason, formatting fails, the resulting string will be error! . Check the server logs and try to simplify your message in this case", "title": "Localization and internationalization"}, {"location": "janssen-server/developer/agama/advanced-usages/#access-to-as-labels", "text": "The jans-auth server comes with a series of files known as \"resource bundles\" that follow the naming jans-auth_xx.properties where xx represents an ISO 639 language code. Bundles can be added or overridden by placing suitable properties files in directory /opt/jans/jetty/jans-auth/custom/i18n . Strings stored in these bundles can be accessed from templates using expressions like ${msgs.<KEY>} . As most keys in resource bundles contain dot characters, the alternative notation ${msgs[\"KEY\"]} works better for FreeMarker, for example ${msgs[\"login.errorMessage\"]} . Whenever possible, it is recommended to place your internationalization labels in the web folder of the project and use the ${labels(... notation instead. Note msgs has no support for parameterized placeholders: strings are all static.", "title": "Access to AS labels"}, {"location": "janssen-server/developer/agama/advanced-usages/#reusable-templates", "text": "A widespread practice in web page authoring is to compose pages based on reusable pieces. As an example, the need for a common header and footer is ubiquitous in HTML projects. With FreeMarker, composition can be achieved by means of macros . These are the equivalent to functions in programming, they can generate output based on parameters passed and can be called anywhere in a template. Agama already makes use of macros for this purpose. Take a look at the ftlh files found at /opt/jans/jetty/jans-auth/agama . These templates are used to present errors, like timeouts, flow crashes, etc. Example: Here, two pages will be built to demonstrate the concept of composition in FreeMarker templates: a homepage and an \"about us\" page. These will be made up of a header, a sidebar, and their respective main content. Assume the sidebar should be shown only for the home page. Note FreeMarker comments are of the form <#-- This won't be printed in the output --> One way to structure the solution is the following: <#-- aside.ftlh --> <#macro sidebar> <aside> <h2>Recommended tracks</h2> <nav> <ul> <li><a href=\"#\">Efilnikufesin</a></li> <li><a href=\"#\">P.O.N.X.</a></li> <!--li><a href=\"#\">Planet caravan</a></li--> </ul> </nav> </aside> </#macro> aside.ftlh has static markup for a sidebar. It is defined inside a macro called sidebar . <#-- commons.ftlh --> <#import \"aside.ftlh\" as sbar> <#macro header> <header> <h1>Welcome</h1> <nav> <ul> <li><a href=\"#\">Home</a></li> <li><a href=\"#\">About</a></li> <li><a href=\"#\">Sign Up</a></li> </ul> </nav> </header> </#macro> <#macro main useSidebar=false> <!DOCTYPE html> <html> <body> <@header/> <#if useSidebar> <@sbar.sidebar/> </#if> <#nested> </body> </html> </#macro> commons.ftlh template imports aside.ftlh associating it with the shortname sbar . Additionally: It defines two macros: header and main . The macro header generates a static navigation menu main macro is the skeleton of a very simple HTML page main has a parameter named useSidebar whose default is false The sidebar macro is called using <@sbar.sidebar/> while header with <@header/> (local macro) <#-- index.ftlh --> <#import \"commons.ftlh\" as com> <@com.main useSidebar=true> <article> <h1>This is the index page!</h1> <p>Temporibus ut nisi quibusdam iusto vitae similique laudantium. Minima cumque ducimus sit ut dolores. Autem quam soluta illo et omnis expedita voluptas magnam. Sit aperiam laboriosam magnam et amet deleniti. Sit et velit unde quibusdam esse ullam voluptatem. Enim sint blanditiis dolores. Laborum velit eos dolor ad quaerat. Quo tempora excepturi enim dolor harum sunt ipsa. Quis sit dolorem harum ipsa fuga voluptatem commodi. </p> </article> </@com.main> index.ftlh is the homepage: Template commons.ftlh is imported and its macro main called passing true for useSidebar The markup inside <@com.main... tag is the content to be \"inserted\" when the <#nested> directive is reached <#-- about.ftlh --> <#import \"commons.ftlh\" as com> <@com.main> <article> <h1>About us</h1> <p>We don't know ourselves very well.</p> </article> </@com.main> about.ftlh is the \"about us\" page. It works like the homepage except the sidebar will not be shown.", "title": "Reusable templates"}, {"location": "janssen-server/developer/agama/advanced-usages/#cancellation", "text": "Important Ensure you have previously gone through the contents of this page before proceeding This is a feature that in conjuction with template overrides allows developers to implement alternative routing and backtracking. Suppose a flow is designed to reuse two or more existing subflows. As expected these subflows are neither aware of each other nor of its parent. How can the parent make so that once the user has landed at a page belonging to a given subflow A be presented the alternative to take another route, say, to subflow B? Clearly a page at flow A can be overriden, however, how to abort A and make it jump to B? The answer is cancellation. Through flow cancellation, a running flow can be aborted and the control returned to one of its parents for further processing. This can achieved by overriding a template so that the POST to the current URL includes a form field named _abort . POSTing this way will provoke the associated Trigger call to return a value like { aborted: true, data: ..., url: ... } where data is a map consisting of the payload (form fields) sent with the POST. Thus, developers can build custom pages and add for example a button to provoke the cancellation. Then, back in the flow implementation take the user to the desired path. The url property will hold the URL where cancellation took place relative to https://your-server/jans-auth/fl/ . As an example, suppose there exists two flows that allow users to enter and validate a one-time passcode (OTP), one flow sends the OTP via e-mail while the other through an SMS. Assume these flows receive a user identifier as input and render a single UI page each to enter the received OTP. If we are interested in building a flow that prompts for username/password credentials and use the SMS-based OTP flow with a customization that consists of showing a link like \"Didn't get an SMS?, send the passcode to my e-mail\", the following is a sketch of an implementation: ... //validate username/password ... result = Trigger co.acme.SmsOTP userId Override templates \"path/to/enter_otp.ftlh\" \"cust_enter_otp.ftlh\" When result.aborted is true //The user clicked on \"send the passcode to my e-mail\" result = Trigger co.acme.EmailOTP userId When result.success is true result.data = { userId: userId } Finish result The overriden template cust_enter_otp.ftlh would have a form like: ... <form method=\"post\" enctype=\"application/x-www-form-urlencoded\"> <button type=\"submit\" name=\"_abort\"> Didn't get an SMS?, send the passcode to my e-mail</button> </form> Note you cannot make cancellation occur at an arbitrary point of a flow. It can only happen when a page has been rendered, that is, an RRF directive is in execution. When a flow is aborted and the control returned back to a parent, there is no way to \"resume\" execution of the flow target of the cancellation.", "title": "Cancellation"}, {"location": "janssen-server/developer/agama/advanced-usages/#cancellation-bubble-up", "text": "In order to override a page, the path to the corresponding template can be easily derived from the URL seen at the browser's address bar when the subflow is Trigger ed. Note the page may not necessarily belong directly to the subflow triggered but probably to another flow lying deep in a chain of Trigger invocations. As an example suppose you are interested in building a flow A that reuses flow B. You identify a page shown that needs to be overriden. It might happen this page is actually rendered by C - a flow that B in turn reuses. In scenarios like this cancellation still works transparently and developers need not be aware of flows dependencies. In practice, when cancellation occurs at C, it bubbles up to B and then to A, which is the target of this process. Note that even flow B (as is) may also be overriding C's templates. Resolution of a template path takes place from the inner to the outer flow, so it occurs this way in the example: path is as found in C's RRF instruction path is looked up on the list provided in B's Override templates . If a match is found, path is updated accordingly path is looked up on the list provided in A's Override templates . If a match is found, path is updated accordingly The page referenced by path is rendered", "title": "Cancellation bubble-up"}, {"location": "janssen-server/developer/agama/advanced-usages/#engine-internals", "text": "Here we provide insight on some behavioral aspects of the engine that may result of interest to developers.", "title": "Engine internals"}, {"location": "janssen-server/developer/agama/advanced-usages/#flow-advance-and-navigation", "text": "Once a web page (or a response in general) is replied to a client (e.g. web browser), a POST is required to make the flow proceed . The POST is expected to be sent to the current URL only, otherwise, a 404 error will be thrown. The engine will then respond with a redirect (usually 301) so the client will GET the next URL to be rendered. This pattern of navigation is known as \"POST-REDIRECT-GET\". There is a clear correspondence of the \"current URL\" with the physical path of the template rendered. As an example, if the browser location shows https://<your-host>/jans-auth/fl/foo/bar.fls , the involved template is stored at /opt/jans/jetty/jans-auth/agama/ftl/foo and has name bar . This makes flows more predictable and easier to reason about. Note however URLs are not manipulable: an attempt to set the browser location to a URL corresponding to a different template will not make that template be rendered or provoke any unexpected jump in the flow control. Instead, an error page is shown that allows users to re-take where they left off or to restart from scratch. In other words, navigation honors the \"current flow URL\" avoiding attempts to re-visit past stages or make unexpected moves to future ones. Additionally, the engine by default sends responses with proper HTTP headers so page contents are not cached. This is key to prevent manipulation and allows a safe usage of the browser's back button, where it will not be possible to visit past stages.", "title": "Flow advance and navigation"}, {"location": "janssen-server/developer/agama/advanced-usages/#code-transpilation", "text": "The engine has some timers running in the background. One of them transpiles code when a change is detected in a given flow's source (written in Agama language). The transpilation process generates vanilla Javascript code runnable through Mozilla Rhino by using a transformation chain like (DSL) flow code -> (ANTLR4) parse tree -> (XML) abstract syntax tree -> JS. The transformation chain guarantees that a flow written in Agama DSL cannot: Access Java classes/instances not specified in the original flow code (i.e. the only bridge to Java world is via Call s) Access/modify the standard javascript built-in objects directly Conflict with javascript keywords Notes You can find the (ANTLR4) DSL grammar here . The last step of the transformation chain is carried out by means of this Freemarker transformer", "title": "Code transpilation"}, {"location": "janssen-server/developer/agama/advanced-usages/#other-engine-characteristics", "text": "Some interesting facts for the curious: The engine does not use asynchronous paradigms: no events, callbacks, extra threads, etc. All computations remain in the classic request/response servlet lifecycle familiar to most Java developers Continuations allow to express a flow as if it were a straight sequence of commands despite there are actual pauses in the middle: the gaps between an HTTP response and the next request Currently Mozilla Rhino seems to be the only mechanism that brings continuations into the Java language In order to preserve server statelessness, continuations are persisted to storage at every flow pause. This way the proper state can be restored when the continuation is resumed in the upcoming HTTP request", "title": "Other engine characteristics"}, {"location": "janssen-server/developer/agama/agama-best-practices/", "tags": ["administration", "developer", "agama"], "text": "Recommended practices in Agama development # Project reuse and customizations # Agama was designed with reusability in mind. If a project provides functionalities of your interest but you find it does not quite achieve what you want, do not try to modify the project. Instead, create a new separate project reusing the flows and code found in the original project. It might be tempting to just take an Agama project archive, apply some editions, add files to it, repack, and redeploy it. This practice is not recommended. Think of a project as a library used to develop software. In normal situations you will not to hack or patch a library but use wrapper code to override or tailor its behavior. Agama provides a couple of vehicles to manipulate behavior and appearance: Template overrides Flow cancellation These allow you to preserve encapsulation and keep project intrusiveness controlled. About flow design # It is up to developers how to design a flow. This will normally require identifying the several \"steps\" that make up the \"journey\" and the conditions upon which \"branching\" takes place. Also it is important to check already existing flows in the server that may be reused for the purpose. Agama language was made to structure flows only, not for doing general purpose programming. This means developers have to use Java for doing low-level computations in the Janssen engine. This way, the resulting implementation (in DSL) serves as a depiction of the flow itself, hiding most of the internal details. About crashes # As a flow executes things can go wrong for reasons that developers cannot foresee. A database may have crashed, a connection to an external system may have failed, the flow itself may have some bug, etc. When an abnormal situation is presented, a flow simply crashes. If a flow crashes, its parent flows (or flow) if they exist, crash as well. Trying to handle crashes involves a lot of planning and work which is too costly and will unlikely account for the so many things that might fail in a real setting. Thus, coding defensively is not recommended. While it is possible to deal with Java exceptions (product of Call s) and other abnormalities when Trigger ing flows, these features should be used sparingly. Internationalization labels # When using localization and internationalization use meaningful label keys and prefix all of them with the name of the project in question. If your project is called magicAuthnJourneys , then magicAuthnJourneys.image.caption and magicAuthnJourneys.start_button_label are good examples. This is a strategy that avoids possible name collisions in labels. OOP prose warning # Java support adds the ability to execute pieces of business logic required to build up a flow. These \u201cpieces of logic\u201d match well to Java methods, however situations like this must be avoided: x = \u2026 // A java object obtained in some way y = \u2026 // A java object obtained in some way Call x methodA arg1 arg2 \u2026 Call x methodB arg1 arg2 arg3 \u2026 z = Call y methodC \u2026 Call x methodD \u2026 z \u2026 If all those calls represent a meaningful unit of work they should be abstracted out and grouped into a single method invocation which should be thoroughly implemented in Java. Note Agama should not be used to do object-oriented programming but to make a clear, concise representation of a flow. As a rule of thumb, let Java do the heavy work; this is wiser, safer, and faster. Variable naming # Camel case is recommended. Also, in real-world flows developers would like to prefix a variable name with j when its value originates from a Java call and does not match any of Agama types directly. Example: jCustomerDetail . Finishing flows # Carefully decide how use the Finish directive in a flow. Specially when terminating sucessfully, many times developers would like to attach the identity of the user in question, as in Finish userId . This results in a successful authentication event and makes sense, but this is not always desired. Sometimes due to decomposition practices (in order to favor re-use and better organization), small flows can arise that should not carry the user identifier. As an example, suppose several flows exist for OTP (one-time passcode) authentication, like SMS, e-mail, token-based, etc. These would receive the user identifier as an input and act accordingly by verifying the passcode the user has entered at the browser. A parent flow can be used to prompt for a username and password first, and then forward the user to the OTP flow that better matches the user's preferences. This sounds fine, however, since any flow can be triggered by means of an authentication request by default, a skilled individual might try to launch one of the OTP flows directly passing proper parameters. This would result in authentications using a single factor (i.e. no password) which is undesirable. Thus, it is recommended to include userId in Finish only when there is a reason to do so, that is, when the authentication carried out by the flow is strong enough. This largely depends on the defined organization policies, but using a two-factor authentication is often a good sign of strength. Another approach is explicitly state which flows should not be triggered from a browser directly. This can be done in the Agama project descriptor , project.json . Recall the simplest way to express a positive authentication outcome is just Finish true .", "title": "Agama Best Practices"}, {"location": "janssen-server/developer/agama/agama-best-practices/#recommended-practices-in-agama-development", "text": "", "title": "Recommended practices in Agama development"}, {"location": "janssen-server/developer/agama/agama-best-practices/#project-reuse-and-customizations", "text": "Agama was designed with reusability in mind. If a project provides functionalities of your interest but you find it does not quite achieve what you want, do not try to modify the project. Instead, create a new separate project reusing the flows and code found in the original project. It might be tempting to just take an Agama project archive, apply some editions, add files to it, repack, and redeploy it. This practice is not recommended. Think of a project as a library used to develop software. In normal situations you will not to hack or patch a library but use wrapper code to override or tailor its behavior. Agama provides a couple of vehicles to manipulate behavior and appearance: Template overrides Flow cancellation These allow you to preserve encapsulation and keep project intrusiveness controlled.", "title": "Project reuse and customizations"}, {"location": "janssen-server/developer/agama/agama-best-practices/#about-flow-design", "text": "It is up to developers how to design a flow. This will normally require identifying the several \"steps\" that make up the \"journey\" and the conditions upon which \"branching\" takes place. Also it is important to check already existing flows in the server that may be reused for the purpose. Agama language was made to structure flows only, not for doing general purpose programming. This means developers have to use Java for doing low-level computations in the Janssen engine. This way, the resulting implementation (in DSL) serves as a depiction of the flow itself, hiding most of the internal details.", "title": "About flow design"}, {"location": "janssen-server/developer/agama/agama-best-practices/#about-crashes", "text": "As a flow executes things can go wrong for reasons that developers cannot foresee. A database may have crashed, a connection to an external system may have failed, the flow itself may have some bug, etc. When an abnormal situation is presented, a flow simply crashes. If a flow crashes, its parent flows (or flow) if they exist, crash as well. Trying to handle crashes involves a lot of planning and work which is too costly and will unlikely account for the so many things that might fail in a real setting. Thus, coding defensively is not recommended. While it is possible to deal with Java exceptions (product of Call s) and other abnormalities when Trigger ing flows, these features should be used sparingly.", "title": "About crashes"}, {"location": "janssen-server/developer/agama/agama-best-practices/#internationalization-labels", "text": "When using localization and internationalization use meaningful label keys and prefix all of them with the name of the project in question. If your project is called magicAuthnJourneys , then magicAuthnJourneys.image.caption and magicAuthnJourneys.start_button_label are good examples. This is a strategy that avoids possible name collisions in labels.", "title": "Internationalization labels"}, {"location": "janssen-server/developer/agama/agama-best-practices/#oop-prose-warning", "text": "Java support adds the ability to execute pieces of business logic required to build up a flow. These \u201cpieces of logic\u201d match well to Java methods, however situations like this must be avoided: x = \u2026 // A java object obtained in some way y = \u2026 // A java object obtained in some way Call x methodA arg1 arg2 \u2026 Call x methodB arg1 arg2 arg3 \u2026 z = Call y methodC \u2026 Call x methodD \u2026 z \u2026 If all those calls represent a meaningful unit of work they should be abstracted out and grouped into a single method invocation which should be thoroughly implemented in Java. Note Agama should not be used to do object-oriented programming but to make a clear, concise representation of a flow. As a rule of thumb, let Java do the heavy work; this is wiser, safer, and faster.", "title": "OOP prose warning"}, {"location": "janssen-server/developer/agama/agama-best-practices/#variable-naming", "text": "Camel case is recommended. Also, in real-world flows developers would like to prefix a variable name with j when its value originates from a Java call and does not match any of Agama types directly. Example: jCustomerDetail .", "title": "Variable naming"}, {"location": "janssen-server/developer/agama/agama-best-practices/#finishing-flows", "text": "Carefully decide how use the Finish directive in a flow. Specially when terminating sucessfully, many times developers would like to attach the identity of the user in question, as in Finish userId . This results in a successful authentication event and makes sense, but this is not always desired. Sometimes due to decomposition practices (in order to favor re-use and better organization), small flows can arise that should not carry the user identifier. As an example, suppose several flows exist for OTP (one-time passcode) authentication, like SMS, e-mail, token-based, etc. These would receive the user identifier as an input and act accordingly by verifying the passcode the user has entered at the browser. A parent flow can be used to prompt for a username and password first, and then forward the user to the OTP flow that better matches the user's preferences. This sounds fine, however, since any flow can be triggered by means of an authentication request by default, a skilled individual might try to launch one of the OTP flows directly passing proper parameters. This would result in authentications using a single factor (i.e. no password) which is undesirable. Thus, it is recommended to include userId in Finish only when there is a reason to do so, that is, when the authentication carried out by the flow is strong enough. This largely depends on the defined organization policies, but using a two-factor authentication is often a good sign of strength. Another approach is explicitly state which flows should not be triggered from a browser directly. This can be done in the Agama project descriptor , project.json . Recall the simplest way to express a positive authentication outcome is just Finish true .", "title": "Finishing flows"}, {"location": "janssen-server/developer/agama/engine-bridge-config/", "tags": ["administration", "developer", "agama"], "text": "Engine and bridge configurations # Availability # The engine and the bridge are two of the components part of the Agama Framework implementation in Janssen. The engine is a piece of software in charge of parsing flows written in Agama DSL and put them into action. The \"bridge\" is a regular jython script that temporarily hands control to the engine when an Agama flow is started, and receives control back once the flow has finished. This script is in charge of completing the authentication process for the user. By default, the bridge is disabled. To activate it do the following: Open TUI Navigate to Scripts > Search 'agama' > Select the script and hit enter > check enabled > save Engine configuration # Some aspects of the engine are configurable and they are integral part of the Jans authentication server's JSON configuration - specifically the section labeled agamaConfiguration . To learn how to perform changes in the server's configuration click here . The properties of Agama engine configuration are described in the following: enabled : A boolean value that specifies if the engine is enabled. To disable the engine, open TUI and navigate to Auth Server > properties > agamaConfiguration . Then uncheck enabled and hit save templatesPath : A path relative to /opt/jans/jetty/jans-auth/agama that serves as the root of Agama flow pages. Default value is /ftl scriptsPath : A path relative to /opt/jans/jetty/jans-auth/agama that serves as the root of the hierarchy of (Java/Groovy) classes added on the fly. Default value is /scripts maxItemsLoggedInCollections : When a list or map is logged in a flow, only the first few items are included in the output. You can use this property to increase that limit. Default value is 9 pageMismatchErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when an unexpected URL is requested while a flow is in course. Default value is mismatch.ftlh interruptionErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when a user exceeds the amount of time allowed to take a flow to completion. Note that in order to preserve resources, the engine holds references to unfinished flows only for a small period of time (usually less than two minutes). Once the reference is lost, the error page regarded here won't be shown but pageMismatchErrorPage . Default value is timeout.ftlh crashErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when an error has occured while running the flow. It contains a brief description of the problem for troubleshooting. Default value is crash.ftlh finishedFlowPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when a flow has finished (whether successfully or not) in the phase handled exclusively by the engine. This page features an auto-submitting form that users won't notice in practice. This page will rarely need modifications. Default value is finished.ftlh bridgeScriptPage : This is a facelets (JSF) page the bridge needs for proper operation. This page resides in the authentication server WAR file and will rarely need modifications. Default value is agama.xhtml serializeRules : A JSON object specifying the serialization rules, see below. It is not recommended to remove items from the out-of-the-box rules. Adding items is fine Serialization rules # At certain points in the course of a flow, serialization of all its variables is required. The engine employs two mechanisms for this purpose: standard Java serialization and KRYO serialization. Depending on the type of (Java) object to be serialized, administrators can specify when a mechanism is preferred over the other through a set of simple rules. This can be better explained with an example. Suppose the following configuration: \"serializeRules\": { \"JAVA\": [\"ice\", \"com.acme\"], \"KRYO\": [ \"com.acme.bike\" ] } If the object to serialize belongs to class com.acme.bike.SuperSonic , both lists are traversed for the best package match. Here KRYO wins because it has a perfect match with respect to the package of the class If the class were com.acme.bike.mega.SuperSonic , KRYO still wins because it has the closest match to the package of the class In case of ice.cream.Salty , JAVA is chosen (best match) In case of org.buskers.Singer , no matches are found, however, KRYO is chosen - it's the fallback method In case of com.acmeMan , no matches are found. KRYO is picked as in the previous case Please account additional behaviors: If the object's class is in the default package (unnamed package), KRYO is used If the exact class name is found in one of the lists, the method represented by such list is employed If the object is a (Java) exception, JAVA is used unless the full class name appears listed in the KRYO rules Bridge configuration # Administrators can modify the behavior of the bridge by setting the finish_userid_db_attribute configuration property of the script. This is used to map the identity of the user to login in the case of sucessfully finished flows. The value of this property will contain a physical database attribute that will be correlated with the userId passed in the Finish instruction of the flow.", "title": "Engine and bridge configurations"}, {"location": "janssen-server/developer/agama/engine-bridge-config/#engine-and-bridge-configurations", "text": "", "title": "Engine and bridge configurations"}, {"location": "janssen-server/developer/agama/engine-bridge-config/#availability", "text": "The engine and the bridge are two of the components part of the Agama Framework implementation in Janssen. The engine is a piece of software in charge of parsing flows written in Agama DSL and put them into action. The \"bridge\" is a regular jython script that temporarily hands control to the engine when an Agama flow is started, and receives control back once the flow has finished. This script is in charge of completing the authentication process for the user. By default, the bridge is disabled. To activate it do the following: Open TUI Navigate to Scripts > Search 'agama' > Select the script and hit enter > check enabled > save", "title": "Availability"}, {"location": "janssen-server/developer/agama/engine-bridge-config/#engine-configuration", "text": "Some aspects of the engine are configurable and they are integral part of the Jans authentication server's JSON configuration - specifically the section labeled agamaConfiguration . To learn how to perform changes in the server's configuration click here . The properties of Agama engine configuration are described in the following: enabled : A boolean value that specifies if the engine is enabled. To disable the engine, open TUI and navigate to Auth Server > properties > agamaConfiguration . Then uncheck enabled and hit save templatesPath : A path relative to /opt/jans/jetty/jans-auth/agama that serves as the root of Agama flow pages. Default value is /ftl scriptsPath : A path relative to /opt/jans/jetty/jans-auth/agama that serves as the root of the hierarchy of (Java/Groovy) classes added on the fly. Default value is /scripts maxItemsLoggedInCollections : When a list or map is logged in a flow, only the first few items are included in the output. You can use this property to increase that limit. Default value is 9 pageMismatchErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when an unexpected URL is requested while a flow is in course. Default value is mismatch.ftlh interruptionErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when a user exceeds the amount of time allowed to take a flow to completion. Note that in order to preserve resources, the engine holds references to unfinished flows only for a small period of time (usually less than two minutes). Once the reference is lost, the error page regarded here won't be shown but pageMismatchErrorPage . Default value is timeout.ftlh crashErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when an error has occured while running the flow. It contains a brief description of the problem for troubleshooting. Default value is crash.ftlh finishedFlowPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when a flow has finished (whether successfully or not) in the phase handled exclusively by the engine. This page features an auto-submitting form that users won't notice in practice. This page will rarely need modifications. Default value is finished.ftlh bridgeScriptPage : This is a facelets (JSF) page the bridge needs for proper operation. This page resides in the authentication server WAR file and will rarely need modifications. Default value is agama.xhtml serializeRules : A JSON object specifying the serialization rules, see below. It is not recommended to remove items from the out-of-the-box rules. Adding items is fine", "title": "Engine configuration"}, {"location": "janssen-server/developer/agama/engine-bridge-config/#serialization-rules", "text": "At certain points in the course of a flow, serialization of all its variables is required. The engine employs two mechanisms for this purpose: standard Java serialization and KRYO serialization. Depending on the type of (Java) object to be serialized, administrators can specify when a mechanism is preferred over the other through a set of simple rules. This can be better explained with an example. Suppose the following configuration: \"serializeRules\": { \"JAVA\": [\"ice\", \"com.acme\"], \"KRYO\": [ \"com.acme.bike\" ] } If the object to serialize belongs to class com.acme.bike.SuperSonic , both lists are traversed for the best package match. Here KRYO wins because it has a perfect match with respect to the package of the class If the class were com.acme.bike.mega.SuperSonic , KRYO still wins because it has the closest match to the package of the class In case of ice.cream.Salty , JAVA is chosen (best match) In case of org.buskers.Singer , no matches are found, however, KRYO is chosen - it's the fallback method In case of com.acmeMan , no matches are found. KRYO is picked as in the previous case Please account additional behaviors: If the object's class is in the default package (unnamed package), KRYO is used If the exact class name is found in one of the lists, the method represented by such list is employed If the object is a (Java) exception, JAVA is used unless the full class name appears listed in the KRYO rules", "title": "Serialization rules"}, {"location": "janssen-server/developer/agama/engine-bridge-config/#bridge-configuration", "text": "Administrators can modify the behavior of the bridge by setting the finish_userid_db_attribute configuration property of the script. This is used to map the identity of the user to login in the case of sucessfully finished flows. The value of this property will contain a physical database attribute that will be correlated with the userId passed in the Finish instruction of the flow.", "title": "Bridge configuration"}, {"location": "janssen-server/developer/agama/faq/", "tags": ["administration", "developer", "agama"], "text": "Frequently asked questions # Common errors # Unable to find a suitable constructor with arity ... in class ... # A Java invocation of the form Call package.className#new ... is passing an incorrect number of arguments or their data types do not match the signature of any of the constructors for that class. Unable to find a suitable method called ... with arity ... in class ... # A java invocation is attempting to call a method that is not part of the given class, the number of arguments passed for the method is not correct, or the arguments could not be converted to make a successful call. No Finish instruction was reached # This occurs when no Finish statement has been found in the execution of a flow and there are no remaining instructions. Serialization errors # Agama engine saves the state of a flow every time an RRF or RFAC instruction is reached. The State can be understood as the set of all variables defined in a flow and their associated values up to certain point. Most of times, variables hold basic Agama values like strings, booleans, numbers, lists or maps, however, more complex values may appear due to Java Call s. The engine does its best to properly serialize these Java objects, nonetheless, this is not always possible. In these cases, the flow crashes and errors will appear on screen as well as in the server logs. Use the information in the logs to detect the problematic Java class. This would normally allow you to identify the variable that is causing the issue. Now you have several options to proceed: Check if the value held by the variable is needed for the given RRF/RFAC or some upcoming statement. If that's not the case, simply set it to null before RRF/RFAC occurs Extract only the necessary pieces from the variable, that is, grab only the fields from the object which are of use for the rest of the flow. If they are simple values like strings or numbers, serialization will succeed. Ensure to nullify or overwrite the original variable Adjust the given class so it is \"serialization\" friendlier. Sometimes, adding a no-args constructor fixes the problem. In other cases, making the class implement the java.io.Serializable interface will make it work. The error in the log should provide a hint Tweak the engine serialization rules so an alternative type of serialization can be used for this particular object Modify your Java code so an alternative class is used instead In general, a good practice is to avoid handling complex variables in flows. Letting big object graphs live in the state has a negative impact on performance and also increases the risk of serialization issues. Libraries and classes added on the fly # What Groovy and Java versions are supported? # Groovy 4.0 and Java 8 or higher. The runtime is Amazon Corretto 17. How to add third party libraries? # You can include jar files in the lib directory of a project . This applies only for VM-based installation of Janssen. Onboarding the jar files require a restart of the authentication server. A class is still available after removing the corresponding file # This is because the JVM does not support unloading: even if a given source file is removed, its corresponding class will still be accessible - it remains in the classpath. The classpath will be clean again after a service restart. How to add log statements? # The Jans server uses slf4j and log4j2 logging frameworks. Below is a simple usage example for Java/Groovy code: import org.slf4j.Logger; import org.slf4j.LoggerFactory; ... Logger logger = LoggerFactory.getLogger(your.class); logger.info(\"ahoy, ahoy\"); Note The logging descriptor used by the server can be found here Depending on the package your class belongs to, the message may not appear in the server log. In this case, you have two choices: Supply a custom log4j descriptor Use a class in package io.jans when calling getLogger . A good example would be using io.jans.agama.model.Flow How to append data to a flow's log directly? # Call method log of class io.jans.agama.engine.script.LogUtils . This method receives a variable number of arguments as DSL's Log does. Thus you can do LogUtils.log(\"@w Today is Friday %th\", 13) , as in the logging examples . How to use Contexts and Dependency Injection (CDI)? # Jans server uses Weld (a CDI reference implementation), and as such makes heavy use of managed beans, scopes, dependency injection, events, etc. Unless the code added is part of a jar library , annotations related to scopes or dependency injection won't take any effect in your code. This is because the Java container does a thorough scanning of classes upon start, but the source code files in lib directory are compiled upon use and modification, as expected in a scripting scenario. Java/Groovy files can however reuse any of the (application-scoped) managed beans available in the server's classpath. To obtain a reference to a bean, use a call like: import io.jans.service.cdi.util.CdiUtil; ... ref = CdiUtil.bean(managedBean.class); More advanced bean lookup capabilities are provided by method instance of this class where you can supply qualifiers. Templates # How to implement localization? # This topic is covered here . How to modify the built-in error pages? # Agama features some error pages out-of-the-box. They can be customized by editing the corresponding files referenced in the configuration doc page. Is Javascript supported? # Yes, the template engine is not concerned about the kind of contents linked in markup. It does not even care if your markup makes any sense. For FreeMarker, templates just produce a textual output. A flow page is not rendered as HTML, the browser just shows the source code as text # This is due to lack of proper Content-Type response header. This occurs if your template has filename extension other than ftlh . If you don't want to rename your template, insert <#ftl output_format=\"HTML\"> at the beginning of the file. How to produce JSON instead of HTML? # In your templates use <#ftl output_format=\"JSON\"> in the first line. Take a look at the templates whose name start with json_ in folder /opt/jans/jetty/jans-auth/agama . Particularly check how JSON content can be escaped - unfortunately FreeMarker does not support escaping for JSON out-of-the-box. Development tools # Are there any IDE or editor plugins available for coding flows and manage projects? # Not plugins but you can use Agama Lab for projects and flows authoring. How to debug flows? # We plan to offer a debugger in the future. In the meantime, you can do printf -like debugging using the Log instruction. See Agama logging . Miscellaneous # How to launch a flow? # A flow is launched by issuing an authentication request in a browser as explained here . Does flow execution timeout? # Yes. The maximum amount of time an end-user can take to fully complete a flow is driven by the configuration of the authentication server and can be constrained even more in the flow itself. Read about timeouts here . How to prevent launching a flow directly from the browser? # This can be configured in the project's metadata file . Updates in a flow's code are not reflected in its execution # When a project is re-deployed, a flow remains unchanged if it comes with errors in the provided .gama file. The tool used for deployment will let you know which flows have errors and their descriptions. Why are the contents of a list or map logged partially? # This is to avoid traversing big structures fully. You can increase the value of maxItemsLoggedInCollections in the engine configuration . How to add two numbers or compare numeric values in Agama? # Agama only provides operators for equality/inequality check in conditional statements. Comparisons like \"less-than\", \"greater-than-or-equal\", etc. require Java usage, however, the structure of an authentication flow will rarely have to deal with this kind of computations. Hint : methods like addExact , incrementExact , etc. in java.lang.Math may help you to do some arithmetic. How to concatenate strings in Agama? # See the previous answer. A two-lines solution could be: strings = [ s1, s2, ... ] Call java.lang.String#join \"\" strings How to know the index of a given loop iteration? # See the examples in the Looping section of the language reference . How to know the number of iterations carried out by a loop once it has finished? # You can assign this value to a variable at the top of your loop declaration. See the examples in the Looping section of the language reference . How to access localization labels from Java code? # In Freemarker, localization labels are accessed using the ${labels(key, ...)} notation. The following would be a Java equivalent: import io.jans.agama.engine.service.LabelsService; ... lbls = io.jans.service.cdi.util.CdiUtil.bean(LabelsService.class); String label = lbls.get(\"<label key>\", ... optional extra params); Note the localization context (language, country, etc.) used in such a call is based on the HTTP request that is taking place when the code is invoked. Can Agama code be called from Java? # No. These two languages are supposed to play roles that should not be mixed, check here . How to run flows from native applications instead of web browsers? # There is a separate doc page covering this aspect here .", "title": "FAQ"}, {"location": "janssen-server/developer/agama/faq/#frequently-asked-questions", "text": "", "title": "Frequently asked questions"}, {"location": "janssen-server/developer/agama/faq/#common-errors", "text": "", "title": "Common errors"}, {"location": "janssen-server/developer/agama/faq/#unable-to-find-a-suitable-constructor-with-arity-in-class", "text": "A Java invocation of the form Call package.className#new ... is passing an incorrect number of arguments or their data types do not match the signature of any of the constructors for that class.", "title": "Unable to find a suitable constructor with arity ... in class ..."}, {"location": "janssen-server/developer/agama/faq/#unable-to-find-a-suitable-method-called-with-arity-in-class", "text": "A java invocation is attempting to call a method that is not part of the given class, the number of arguments passed for the method is not correct, or the arguments could not be converted to make a successful call.", "title": "Unable to find a suitable method called ... with arity ... in class ..."}, {"location": "janssen-server/developer/agama/faq/#no-finish-instruction-was-reached", "text": "This occurs when no Finish statement has been found in the execution of a flow and there are no remaining instructions.", "title": "No Finish instruction was reached"}, {"location": "janssen-server/developer/agama/faq/#serialization-errors", "text": "Agama engine saves the state of a flow every time an RRF or RFAC instruction is reached. The State can be understood as the set of all variables defined in a flow and their associated values up to certain point. Most of times, variables hold basic Agama values like strings, booleans, numbers, lists or maps, however, more complex values may appear due to Java Call s. The engine does its best to properly serialize these Java objects, nonetheless, this is not always possible. In these cases, the flow crashes and errors will appear on screen as well as in the server logs. Use the information in the logs to detect the problematic Java class. This would normally allow you to identify the variable that is causing the issue. Now you have several options to proceed: Check if the value held by the variable is needed for the given RRF/RFAC or some upcoming statement. If that's not the case, simply set it to null before RRF/RFAC occurs Extract only the necessary pieces from the variable, that is, grab only the fields from the object which are of use for the rest of the flow. If they are simple values like strings or numbers, serialization will succeed. Ensure to nullify or overwrite the original variable Adjust the given class so it is \"serialization\" friendlier. Sometimes, adding a no-args constructor fixes the problem. In other cases, making the class implement the java.io.Serializable interface will make it work. The error in the log should provide a hint Tweak the engine serialization rules so an alternative type of serialization can be used for this particular object Modify your Java code so an alternative class is used instead In general, a good practice is to avoid handling complex variables in flows. Letting big object graphs live in the state has a negative impact on performance and also increases the risk of serialization issues.", "title": "Serialization errors"}, {"location": "janssen-server/developer/agama/faq/#libraries-and-classes-added-on-the-fly", "text": "", "title": "Libraries and classes added on the fly"}, {"location": "janssen-server/developer/agama/faq/#what-groovy-and-java-versions-are-supported", "text": "Groovy 4.0 and Java 8 or higher. The runtime is Amazon Corretto 17.", "title": "What Groovy and Java versions are supported?"}, {"location": "janssen-server/developer/agama/faq/#how-to-add-third-party-libraries", "text": "You can include jar files in the lib directory of a project . This applies only for VM-based installation of Janssen. Onboarding the jar files require a restart of the authentication server.", "title": "How to add third party libraries?"}, {"location": "janssen-server/developer/agama/faq/#a-class-is-still-available-after-removing-the-corresponding-file", "text": "This is because the JVM does not support unloading: even if a given source file is removed, its corresponding class will still be accessible - it remains in the classpath. The classpath will be clean again after a service restart.", "title": "A class is still available after removing the corresponding file"}, {"location": "janssen-server/developer/agama/faq/#how-to-add-log-statements", "text": "The Jans server uses slf4j and log4j2 logging frameworks. Below is a simple usage example for Java/Groovy code: import org.slf4j.Logger; import org.slf4j.LoggerFactory; ... Logger logger = LoggerFactory.getLogger(your.class); logger.info(\"ahoy, ahoy\"); Note The logging descriptor used by the server can be found here Depending on the package your class belongs to, the message may not appear in the server log. In this case, you have two choices: Supply a custom log4j descriptor Use a class in package io.jans when calling getLogger . A good example would be using io.jans.agama.model.Flow", "title": "How to add log statements?"}, {"location": "janssen-server/developer/agama/faq/#how-to-append-data-to-a-flows-log-directly", "text": "Call method log of class io.jans.agama.engine.script.LogUtils . This method receives a variable number of arguments as DSL's Log does. Thus you can do LogUtils.log(\"@w Today is Friday %th\", 13) , as in the logging examples .", "title": "How to append data to a flow's log directly?"}, {"location": "janssen-server/developer/agama/faq/#how-to-use-contexts-and-dependency-injection-cdi", "text": "Jans server uses Weld (a CDI reference implementation), and as such makes heavy use of managed beans, scopes, dependency injection, events, etc. Unless the code added is part of a jar library , annotations related to scopes or dependency injection won't take any effect in your code. This is because the Java container does a thorough scanning of classes upon start, but the source code files in lib directory are compiled upon use and modification, as expected in a scripting scenario. Java/Groovy files can however reuse any of the (application-scoped) managed beans available in the server's classpath. To obtain a reference to a bean, use a call like: import io.jans.service.cdi.util.CdiUtil; ... ref = CdiUtil.bean(managedBean.class); More advanced bean lookup capabilities are provided by method instance of this class where you can supply qualifiers.", "title": "How to use Contexts and Dependency Injection (CDI)?"}, {"location": "janssen-server/developer/agama/faq/#templates", "text": "", "title": "Templates"}, {"location": "janssen-server/developer/agama/faq/#how-to-implement-localization", "text": "This topic is covered here .", "title": "How to implement localization?"}, {"location": "janssen-server/developer/agama/faq/#how-to-modify-the-built-in-error-pages", "text": "Agama features some error pages out-of-the-box. They can be customized by editing the corresponding files referenced in the configuration doc page.", "title": "How to modify the built-in error pages?"}, {"location": "janssen-server/developer/agama/faq/#is-javascript-supported", "text": "Yes, the template engine is not concerned about the kind of contents linked in markup. It does not even care if your markup makes any sense. For FreeMarker, templates just produce a textual output.", "title": "Is Javascript supported?"}, {"location": "janssen-server/developer/agama/faq/#a-flow-page-is-not-rendered-as-html-the-browser-just-shows-the-source-code-as-text", "text": "This is due to lack of proper Content-Type response header. This occurs if your template has filename extension other than ftlh . If you don't want to rename your template, insert <#ftl output_format=\"HTML\"> at the beginning of the file.", "title": "A flow page is not rendered as HTML, the browser just shows the source code as text"}, {"location": "janssen-server/developer/agama/faq/#how-to-produce-json-instead-of-html", "text": "In your templates use <#ftl output_format=\"JSON\"> in the first line. Take a look at the templates whose name start with json_ in folder /opt/jans/jetty/jans-auth/agama . Particularly check how JSON content can be escaped - unfortunately FreeMarker does not support escaping for JSON out-of-the-box.", "title": "How to produce JSON instead of HTML?"}, {"location": "janssen-server/developer/agama/faq/#development-tools", "text": "", "title": "Development tools"}, {"location": "janssen-server/developer/agama/faq/#are-there-any-ide-or-editor-plugins-available-for-coding-flows-and-manage-projects", "text": "Not plugins but you can use Agama Lab for projects and flows authoring.", "title": "Are there any IDE or editor plugins available for coding flows and manage projects?"}, {"location": "janssen-server/developer/agama/faq/#how-to-debug-flows", "text": "We plan to offer a debugger in the future. In the meantime, you can do printf -like debugging using the Log instruction. See Agama logging .", "title": "How to debug flows?"}, {"location": "janssen-server/developer/agama/faq/#miscellaneous", "text": "", "title": "Miscellaneous"}, {"location": "janssen-server/developer/agama/faq/#how-to-launch-a-flow", "text": "A flow is launched by issuing an authentication request in a browser as explained here .", "title": "How to launch a flow?"}, {"location": "janssen-server/developer/agama/faq/#does-flow-execution-timeout", "text": "Yes. The maximum amount of time an end-user can take to fully complete a flow is driven by the configuration of the authentication server and can be constrained even more in the flow itself. Read about timeouts here .", "title": "Does flow execution timeout?"}, {"location": "janssen-server/developer/agama/faq/#how-to-prevent-launching-a-flow-directly-from-the-browser", "text": "This can be configured in the project's metadata file .", "title": "How to prevent launching a flow directly from the browser?"}, {"location": "janssen-server/developer/agama/faq/#updates-in-a-flows-code-are-not-reflected-in-its-execution", "text": "When a project is re-deployed, a flow remains unchanged if it comes with errors in the provided .gama file. The tool used for deployment will let you know which flows have errors and their descriptions.", "title": "Updates in a flow's code are not reflected in its execution"}, {"location": "janssen-server/developer/agama/faq/#why-are-the-contents-of-a-list-or-map-logged-partially", "text": "This is to avoid traversing big structures fully. You can increase the value of maxItemsLoggedInCollections in the engine configuration .", "title": "Why are the contents of a list or map logged partially?"}, {"location": "janssen-server/developer/agama/faq/#how-to-add-two-numbers-or-compare-numeric-values-in-agama", "text": "Agama only provides operators for equality/inequality check in conditional statements. Comparisons like \"less-than\", \"greater-than-or-equal\", etc. require Java usage, however, the structure of an authentication flow will rarely have to deal with this kind of computations. Hint : methods like addExact , incrementExact , etc. in java.lang.Math may help you to do some arithmetic.", "title": "How to add two numbers or compare numeric values in Agama?"}, {"location": "janssen-server/developer/agama/faq/#how-to-concatenate-strings-in-agama", "text": "See the previous answer. A two-lines solution could be: strings = [ s1, s2, ... ] Call java.lang.String#join \"\" strings", "title": "How to concatenate strings in Agama?"}, {"location": "janssen-server/developer/agama/faq/#how-to-know-the-index-of-a-given-loop-iteration", "text": "See the examples in the Looping section of the language reference .", "title": "How to know the index of a given loop iteration?"}, {"location": "janssen-server/developer/agama/faq/#how-to-know-the-number-of-iterations-carried-out-by-a-loop-once-it-has-finished", "text": "You can assign this value to a variable at the top of your loop declaration. See the examples in the Looping section of the language reference .", "title": "How to know the number of iterations carried out by a loop once it has finished?"}, {"location": "janssen-server/developer/agama/faq/#how-to-access-localization-labels-from-java-code", "text": "In Freemarker, localization labels are accessed using the ${labels(key, ...)} notation. The following would be a Java equivalent: import io.jans.agama.engine.service.LabelsService; ... lbls = io.jans.service.cdi.util.CdiUtil.bean(LabelsService.class); String label = lbls.get(\"<label key>\", ... optional extra params); Note the localization context (language, country, etc.) used in such a call is based on the HTTP request that is taking place when the code is invoked.", "title": "How to access localization labels from Java code?"}, {"location": "janssen-server/developer/agama/faq/#can-agama-code-be-called-from-java", "text": "No. These two languages are supposed to play roles that should not be mixed, check here .", "title": "Can Agama code be called from Java?"}, {"location": "janssen-server/developer/agama/faq/#how-to-run-flows-from-native-applications-instead-of-web-browsers", "text": "There is a separate doc page covering this aspect here .", "title": "How to run flows from native applications instead of web browsers?"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/", "tags": ["administration", "developer", "agama"], "text": "Flows navigation, UI pages and assets # RRF is a powerful construct in Agama. Its syntax follows this pattern: ( assignment-var =)? RRF \"path-to-UI-template\" map-variable ? Execution involves several steps which can be summarized as: location of template, rendering, and user-data retrieval. The process is explained in the following. Template location # Note For convenience, references to the server directory /opt/jans/jetty/jans-auth/agama will be replaced by <AGAMA-DIR> from here onwards. A path is built by concatenating the Basepath of the flow this RRF belongs to and the actual template path, i.e. path-to-UI-template as in the introductory parapraph. Then the engine's templates path root is prepended to it. The \"root\" is the value set in the engine configuration for the property templatesPath . Thus, in a default installation, the value to prepend would be <AGAMA-DIR>/ftl . If there is no such file, the flow will crash right away, otherwise, processing continues. How to build templates? # Templates are expected to be written using Apache FreeMarker . This is a simple and highly productive language to produce HTML and other forms of output. By convention templates generating HTML markup in Agama should have the extension ftlh . Practically they will look and behave as regular HTML files. Developers are encouraged to take a peep at the FreeMarker manual before trying to write their first pages. It usually boils down to produce the desired markup plus adding some placeholders for information that is dynamic. The key concept there is Template + data-model = output which is pretty natural. The sumation in this equation is generally referred to as \"rendering a template\" in this documentation. Rendering # Rendering is the process of \"injecting\" the variable passed ( map-variable in the above) into a template. If no variable is present in the instruction, it is assumed an empty map was passed, i.e. { } . The variable injected (\"data model\" in FreeMarker terms) always has to be an Agama map , Java bean or object implementing the java.util.Map interface. This will allow access to the contents of such variable from within the template. Here is a simple example. Suppose you want to ask for a username and password in a page called login.ftl and that such page will be stored in <AGAMA-DIR>/ftl/myflow/pages/login.ftl . Assume the flow has the header directive Basepath \"myflow\" . Also, let's say we want to pass a custom salutation message to be shown at the top of the page. Here is how the Agama code would look like: ... obj = { message: \"Hey ho!, let's go\" } RRF \"pages/login.ftl\" obj ... And here the UI page contents: <!doctype html> <html xmlns=\"http://www.w3.org/1999/xhtml\"> ... <body> <h1>${message}</h1> <form method=\"post\" enctype=\"application/x-www-form-urlencoded\"> <div> <label for=\"username\">Username</label> <input type=\"text\" name=\"username\"> </div> <div> <label for=\"password\">Password</label> <input type=\"password\" name=\"password\"> </div> <input type=\"submit\" value=\"Login\"> </form> </body> </html> Extended data model # The data model (injected map ) is attached some additional keys for convenience: webCtx . It gives easy access to often needed bits like current path, locale, etc. This is a Java object you can inspect here . Take a look at the getters; writing ${webCtx.contextPath} in a template will insert the result of calling method getContextPath - normally the string /jans-auth cache . Allows developers to retrieve values already stored in the Jans configured cache, e.g. ${cache.myKey} . To avoid template errors in case of a cache miss, you can use Freemarker's safeguard expressions . Note you cannot store/modify values in the cache from templates labels and msgs . These give access to localized messages. They are useful when templates have to render different texts depening on user context, such as country and language. Learn more here Assets handling # Clearly, templates can link other local web resources like Javascript code, images, etc. The location of this kind of files is expected to be in the filesystem under <AGAMA-DIR>/fl directory. Note this is not the same directory of templates. Doing so would allow users to retrieve the code of templates by simple URL manipulation. As an example, suppose your flow Basepath is foo and you have the instructions RRF index.ftlh and RRF bar/index2.ftlh somewhere in your code. Then your local <AGAMA-DIR>/ftl would look like: foo |- index.ftlh +- bar \\- index2.ftlh Say index.ftlh has markup like <img src=\"bar/me.png\"> and index2.ftlh has <link href=\"my/style.css\" rel=\"stylesheet\"> somewhere. This is how <AGAMA-DIR>/fl would look like: foo +- bar |- me.png \\- my \\- style.css User-data retrieval # Once the rendered page is shown in the browser, the flow execution is literally paused. If the user stands idly at this page, nothing will happen. To make the flow proceed, an HTTP POST must be made to the current URL. This is exactly what login.ftl of the above example tries to do: it provides a button that submits the form via POST for the flow to resume execution. Once the flow continues, an Agama map is built using all form fields received at the server and bound to the variable used in the assignment of the RRF instruction (the variable referred as assignment-var in the introduction of this page). This only applies when RRF has an assignment associated, of course. If the earlier example is modified to ... obj = { message: \"Hey ho!, let's go\" } credentials = RRF \"pages/login.ftl\" obj ... the form values can then be referenced as credentials.username and credentials.password in the flow. In other words, the keys of the resulting map will correspond to the form field names. The values will all be strings . 3-param variant # In the Jans Agama engine, RRF can be passed a third parameter: RRF templatePath variable boolean . When the boolean value is true the callback URL will be available while RRF is in execution (as in RFAC ). In this case, if the callback is visited, data passed to it will be set as the result of the RRF . If a POST to the current URL is received first, i.e. callback not hit, behavior will be as in the two-param RRF invocation. This is also the case when a false value is passed for the third parameter. The three-param variant of RRF can be useful when: The decision to redirect to an external site can only be done from the browser itself The external site expects to receive an HTTP POST. In this case, the rendered template may contain a form with fields as needed plus auto-submission logic in Javascript to perform the actual POST. This typically occurs in inbound-identity flows where identity providers require authentication requests serialized in application/x-www-form-urlencoded format as is the case of SAML HTTP POST binding, for example", "title": "Navigation, UI pages and assets"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#flows-navigation-ui-pages-and-assets", "text": "RRF is a powerful construct in Agama. Its syntax follows this pattern: ( assignment-var =)? RRF \"path-to-UI-template\" map-variable ? Execution involves several steps which can be summarized as: location of template, rendering, and user-data retrieval. The process is explained in the following.", "title": "Flows navigation, UI pages and assets"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#template-location", "text": "Note For convenience, references to the server directory /opt/jans/jetty/jans-auth/agama will be replaced by <AGAMA-DIR> from here onwards. A path is built by concatenating the Basepath of the flow this RRF belongs to and the actual template path, i.e. path-to-UI-template as in the introductory parapraph. Then the engine's templates path root is prepended to it. The \"root\" is the value set in the engine configuration for the property templatesPath . Thus, in a default installation, the value to prepend would be <AGAMA-DIR>/ftl . If there is no such file, the flow will crash right away, otherwise, processing continues.", "title": "Template location"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#how-to-build-templates", "text": "Templates are expected to be written using Apache FreeMarker . This is a simple and highly productive language to produce HTML and other forms of output. By convention templates generating HTML markup in Agama should have the extension ftlh . Practically they will look and behave as regular HTML files. Developers are encouraged to take a peep at the FreeMarker manual before trying to write their first pages. It usually boils down to produce the desired markup plus adding some placeholders for information that is dynamic. The key concept there is Template + data-model = output which is pretty natural. The sumation in this equation is generally referred to as \"rendering a template\" in this documentation.", "title": "How to build templates?"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#rendering", "text": "Rendering is the process of \"injecting\" the variable passed ( map-variable in the above) into a template. If no variable is present in the instruction, it is assumed an empty map was passed, i.e. { } . The variable injected (\"data model\" in FreeMarker terms) always has to be an Agama map , Java bean or object implementing the java.util.Map interface. This will allow access to the contents of such variable from within the template. Here is a simple example. Suppose you want to ask for a username and password in a page called login.ftl and that such page will be stored in <AGAMA-DIR>/ftl/myflow/pages/login.ftl . Assume the flow has the header directive Basepath \"myflow\" . Also, let's say we want to pass a custom salutation message to be shown at the top of the page. Here is how the Agama code would look like: ... obj = { message: \"Hey ho!, let's go\" } RRF \"pages/login.ftl\" obj ... And here the UI page contents: <!doctype html> <html xmlns=\"http://www.w3.org/1999/xhtml\"> ... <body> <h1>${message}</h1> <form method=\"post\" enctype=\"application/x-www-form-urlencoded\"> <div> <label for=\"username\">Username</label> <input type=\"text\" name=\"username\"> </div> <div> <label for=\"password\">Password</label> <input type=\"password\" name=\"password\"> </div> <input type=\"submit\" value=\"Login\"> </form> </body> </html>", "title": "Rendering"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#extended-data-model", "text": "The data model (injected map ) is attached some additional keys for convenience: webCtx . It gives easy access to often needed bits like current path, locale, etc. This is a Java object you can inspect here . Take a look at the getters; writing ${webCtx.contextPath} in a template will insert the result of calling method getContextPath - normally the string /jans-auth cache . Allows developers to retrieve values already stored in the Jans configured cache, e.g. ${cache.myKey} . To avoid template errors in case of a cache miss, you can use Freemarker's safeguard expressions . Note you cannot store/modify values in the cache from templates labels and msgs . These give access to localized messages. They are useful when templates have to render different texts depening on user context, such as country and language. Learn more here", "title": "Extended data model"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#assets-handling", "text": "Clearly, templates can link other local web resources like Javascript code, images, etc. The location of this kind of files is expected to be in the filesystem under <AGAMA-DIR>/fl directory. Note this is not the same directory of templates. Doing so would allow users to retrieve the code of templates by simple URL manipulation. As an example, suppose your flow Basepath is foo and you have the instructions RRF index.ftlh and RRF bar/index2.ftlh somewhere in your code. Then your local <AGAMA-DIR>/ftl would look like: foo |- index.ftlh +- bar \\- index2.ftlh Say index.ftlh has markup like <img src=\"bar/me.png\"> and index2.ftlh has <link href=\"my/style.css\" rel=\"stylesheet\"> somewhere. This is how <AGAMA-DIR>/fl would look like: foo +- bar |- me.png \\- my \\- style.css", "title": "Assets handling"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#user-data-retrieval", "text": "Once the rendered page is shown in the browser, the flow execution is literally paused. If the user stands idly at this page, nothing will happen. To make the flow proceed, an HTTP POST must be made to the current URL. This is exactly what login.ftl of the above example tries to do: it provides a button that submits the form via POST for the flow to resume execution. Once the flow continues, an Agama map is built using all form fields received at the server and bound to the variable used in the assignment of the RRF instruction (the variable referred as assignment-var in the introduction of this page). This only applies when RRF has an assignment associated, of course. If the earlier example is modified to ... obj = { message: \"Hey ho!, let's go\" } credentials = RRF \"pages/login.ftl\" obj ... the form values can then be referenced as credentials.username and credentials.password in the flow. In other words, the keys of the resulting map will correspond to the form field names. The values will all be strings .", "title": "User-data retrieval"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#3-param-variant", "text": "In the Jans Agama engine, RRF can be passed a third parameter: RRF templatePath variable boolean . When the boolean value is true the callback URL will be available while RRF is in execution (as in RFAC ). In this case, if the callback is visited, data passed to it will be set as the result of the RRF . If a POST to the current URL is received first, i.e. callback not hit, behavior will be as in the two-param RRF invocation. This is also the case when a false value is passed for the third parameter. The three-param variant of RRF can be useful when: The decision to redirect to an external site can only be done from the browser itself The external site expects to receive an HTTP POST. In this case, the rendered template may contain a form with fields as needed plus auto-submission logic in Javascript to perform the actual POST. This typically occurs in inbound-identity flows where identity providers require authentication requests serialized in application/x-www-form-urlencoded format as is the case of SAML HTTP POST binding, for example", "title": "3-param variant"}, {"location": "janssen-server/developer/agama/jans-agama-engine/", "tags": ["administration", "developer", "agama"], "text": "Janssen Agama Engine # Introduction # The Janssen Server implements the Agama framework through several components bundled in its authentication server (AS): The engine: the piece of software that actually runs the flows and interacts with the user's browser - sort of a small web application. As expected, these flows are mainly targetted at user authentication A transpiler: code written in Agama language is transpiled to an intermediate representation which can then be interpreted at runtime by the engine The bridge: since the engine itself does not implement an authentication protocol, another piece is required to put flows in the context of a standard authorization framework like OpenId Connect. This is what the bridge does The deployer: a piece of software capable of deploying Agama projects to the engine. The rest of this document describes implementation-specific details of the engine bundled with the Jans Server. These details give shape to the requirements abstractly defined for an Agama-compliant engine . Note Ensure both the Agama engine and the bridge are enabled in the Janssen server to effectively use engine's features Launching flows # Flows can be launched by sending an (OpenId Connect) authentication request to the user's browser. This usually boils down to making a redirection to a URL looking like https://<jans-server-name>/jans-auth/restv1/authorize?acr_values=agama_flowQname&scope=...&response_type=...&redirect_uri=https...&client_id=...&state=... . Check the OpenId Connect spec for more details. Note Jans Server is spec-compliant. Things to highlight: The acr_values parameter carries the qualified name (identifier) of the flow to launch prefixed with the string agama_ , for example acr_values=agama_test.acme.co If the flow to call receives input parameters, this data can be appended to the acr_values parameter: use a hyphen to separate the flow name and the parameters expressed in Base64 URL encoded format. For example, if the flow had inputs height and color , you would encode the string {\"height\": 190, \"color\": \"blue\"} and the resulting value would be agama_test.acme.co-eyJoZWlnaHQiOiAxOTAsICJjb2xvciI6ICJibHVlIn0 . When a given input variable is not provided, the engine will assign a null value automatically Authentication and Finish # When a top-level flow (i.e. one with no parents) finishes successfully, the selection of the user to authenticate is driven by the userId passed in data , as in obj = { success: true, data: { userId: \"john_doe\" } } // map literals cannot be passed directly to Finish - a variable can be used instead Finish obj By default userId maps to the uid attribute that generally all user entries already have in the database of Jans Server, in other words, the \"user name\". This attribute is configurable though via property finish_userid_db_attribute of the bridge script . In some cases, you would like to change that to mail in order to pass things like { success: true, data: { userId: \"john_doe@jd.me\" } } for instance. Important If the database lookup does not produce exactly one user entry, this is treated as a failed authentication attempt by the authentication server. When the authentication succeeds, the whole contents of data are stored in the authentication server's session of the given user under the key agamaData . Contents are serialized to a JSON string previously. Crashes, timeouts, and failures # Execution rules define several possible flow states . For crashed, timed out, and finished failed flows, the engine will present proper error pages to users. These are configurable by properties crashErrorPage , interruptionErrorPage , and finishedFlowPage respectively, of the engine-configuration . How timeouts work # Authentication flows are normally short-lived. They usually span no more than a few minutes. In Agama, the maximum amount of time an end-user can take to fully complete a flow is driven by the configuration of the authentication server , specifically the sessionIdUnauthenticatedUnusedLifetime property which is measured in seconds. As an example, if this value is 120, any attempt to authenticate taking more than two minutes will throw the given error page. Moreover, when a flow specifies its own timeout in the header the effective timeout is the smallest value between sessionIdUnauthenticatedUnusedLifetime and the value in the header. Depending on specific needs, sessionIdUnauthenticatedUnusedLifetime may have to be set to a higher value than the server's default. This may be the case where flows send e-mail notifications with temporary codes, for instance. Logging # There are three relevant sources of log data: The engine. It emits information related to flows transpilation, projects deployment, and flow crashes - generally low-level information Log instructions. These are statements originated directly from the Agama code Call directives. Foreign code can issue logging statements as well as any other code a Call may depend on. See the FAQ The following table details the location of log data. Paths are relative to directory /opt/jans/jetty/jans-auth/log : Source Destination file Engine jans-auth.log Log instructions jans-auth_script.log Foreign code jans-auth.log Depending on the specificity required, you may have to change the logging level so more or less details appear in the logs. This can be done by altering the loggingLevel property of the auth server configuration . DEBUG usually suffices for troubleshooting. The available levels for statements issued with the Log instruction are: Level name shortcut error e warn w info i debug d trace t For instance, these two instructions are equivalent: Log \"@e Universe collapsed\" and Log \"@error Universe collapsed\" The engine will use info when the level is not specified explicitly, as in Log \"Look ma!\" . RFAC and Callback URL # Engine's callback URL is https://<your-server-name>/jans-auth/fl/callback . This resource is only be available for a given browser session while RFAC is in execution. Once the callback is visited or the flow times out (whichever occurs first), subsequent requests will respond with an HTTP 404 error. The mechanism used for redirection is a \"302 Found\" HTTP redirect that entails a subsequent GET request to the external site. In cases where a POST is expected, the 3-param version of RRF can be useful. RRF, navigation, and assets handling # Understanding how RRF works in the engine is key to writing meaningful flows. This topic is fully covered here . Foreign calls # In the Jans Agama engine, Java or Groovy code can be called by means of the Call instruction. Specifically, public methods from public classes or static methods from public interfaces. Note Java language background is required for this section. The following exemplifies different kind of usages of Java from Agama code: Example Notes Call java.lang.Integer#parseInt \"FF\" 16 Invokes the parseInt method of Integer class passing the given arguments (i.e. conversion of hexadecimal string to a primitive int ). The returned value is ignored numbers = [ 2, -2, 0, 3, -3, 4 ] small = Call java.util.Collections#min numbers Invokes the min method of the Collections class. Supplies a list of numbers as argument. The smallest number is stored in variable small jLocale = Call java.util.Locale#getDefault localeName = jLocale.displayName Computes the display name of the JVM default locale car = { brand: \"Ford\", model: 1963 } sidecar = Call java.util.Map#copyOf car Makes a deep clone of a map number | E = Call java.lang.Integer#parseInt \"AGA\" 16 When E is not null Log \"An error occurred:\" E.message Similar to the first example. If an exception is thrown by the invocation, it's caught and assigned to variable E . Note both checked and unchecked exceptions are caught | E = Call com.acme.Worker#notifyExternalSystem //Do something with E //... If exception catching is required when calling a method that returns void , there is no need to put a variable before the pipe p1 = Call java.awt.Point#new p2 = Call java.awt.Point#new 1 3 Call p2 translate -1 1 Creates instances of class java.awt.Point with different constructors. For p1 the no-args constructor is used. Method translate is invoked on the p2 instance. Note usage of a space here instead of hash ( # ) cls1 = Call java.lang.CharSequence#class cls2 = Call java.lang.Integer#class Call cls2 parseInt \"FF\" 16 Stores in cls1 a reference to interface class CharSequence.class . Stores in cls2 a reference to Integer.class . The 3rd line statement achieves the same effect of Call java.lang.Integer#parseInt \"FF\" 16 L = [ \"A\", \"B\", \"C\" ] S = Call java.util.Set#of 0 2 4 6 map = { numbers: S, letters: L } hasOne = Call map.numbers contains 1 Calls the contains method of the java.util.Set object stored in map.numbers passing 1 as argument and storing the result in hasOne The usage of a hash sign (or spaces) before a method name helps disambiguate whether the invocation is on a static class method or an object method. This is so because an expression like hey.You may reference the class You on package hey , or the value of key You in a map named hey . Highlights # Any method that meets the conditions mentioned (public or interface static) and that is reachable in the JVM classpath can be called; developers are not restricted solely to java.* packages. When using Call , the method to execute is picked based on the name (e.g. after the # sign) and the number of arguments supplied. If a class/interface exhibits several methods with the same name and arity (number of parameters), the method that best matches the dataypes of the arguments with respect to its signature is selected. Sometimes this requires to perform arguments conversions and they may fail. In such case, the second best suited method is tried and so on. When all attempts fail or there are no candidate methods to choose from, the Call simply throws a NoSuchMethodException . For non-static method invocations, i.e. no hash sign, the class used for method lookup is that of the instance passed (the first parameter in the Call directive). This includes all associated superclasses too, as expected. When the instance does not hold a Java but an Agama value, the following is used to pick a class: Agama type Java class for method lookup string String boolean Boolean number Double list java.util.List map java.util.Map Limitations: list and map literals cannot be passed as arguments to method calls directly. This means the following is illegal: Call co.Utils#myMethod { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] . To achieve the same effect assign the literal value to a variable and pass that instead Call ing a method that mutates one or more of the arguments passed will not work properly if the corresponding parameters in the method signature have type information attached. For example, copying a list into another using java.util.Collections#copy\u200b(List<? super T> dest, List<? extends T> src) may not behave as expected. Conversely, calling java.lang.reflect.Array#set\u200b(Object array, int index, Object value) works fine because array does not have a parameterized type. The practice of mutating passed arguments is unusual and sometimes discouraged in programming Exception handling # As seen in the examples Agama engine can deal with Java exceptions, however, this feature should be used sparingly. When exception handling adds undesired complexity to your code, create wrapper methods in Java and do the processing there instead of delegating that to the DSL. Arguments conversion # Agama types do not match Java types. This means passing a \"native\" Agama value as parameter in a method Call requires some form of compatibility with the target (Java) type in the method signature. An argument (Agama value) is compatible with a method parameter if it can be \"converted\" successfully. As we'll see, conversion feels pretty natural in practice. If this process fails a java.lang.IllegalArgumentException is thrown and the flow will crash unless the exception is caught. Note however the recommended practice is to let flows crash . The following lists some of the most common successful conversions: Agama value Can be converted to string String or char[] boolean Boolean or primitive equivalent number Double / Float / Integer / Long / Short / Byte or primitive equivalent null Any non-primitive list Array or class implementing Collection<T> as long as items can be converted to type T map Class implementing Map<K, V> as long as keys and values can be converted to types K and V , respectively map Java bean. Unrecognized properties in Agama value are ignored The below table shows some examples of interesting and handy conversions: Agama value Param data type in target Java method Argument value (Agama) Received param value (in method) Notes Positive number having fractional part Integer / Long / Short / Byte or primitive equivalent 2.6 2 Integer part kept Negative number having fractional part Integer / Long / Short / Byte or primitive equivalent -2.4 2 Integer part kept Integer number Float / Double or primitive equivalent 1 1.0 list of number s List<Integer> [1, 2.0, 3.1, -4.2] [1, 2, 3, -4] Only integer parts kept list of integer number s List<Float> / List<Double> [1, 2, 3, -4] [1.0, 2.0, 3.0, -4.0] string of length 1 Character or primitive equivalent a a Passing a zero, two, or more lengthed string will make the call fail When the argument is not an Agama but a Java object/primitive, the following rules apply: If the value can be cast to the target type, no conversion is needed, otherwise If it is an instance of java.lang.Number and the type is a numeric primitive or wrapper (e.g. Integer ), the value is truncated if required, otherwise The value is serialized to JSON - if possible - and then an attempt to create a Java instance based on the given JSON contents is made. For this purpose, the FasterXML Jackson library is used This is powerful because it allows to send data of similar shape/structure when data types do not necessarily match. Consider the following example: s = \"a man's gotta do what a man's gotta do\" jStrArr = Call s split \" \" words = Call java.util.Collections#unmodifiableSet jStrArr This Agama snippet creates the (Java) Set of different words found in a given (Agama) string . Note jStrArr is of type String[] and is passed directly to method unmodifiableSet which originally expects an instance of Set as parameter. From Java to Agama # We just saw how Agama values are treated in Java code. Here we make an analysis in the reverse direction: from Java to Agama where Java values are obtained through Call invocations. The following table relates Java types to Agama types: Java value ( x ) Agama equivalent Notes x is a Java array or implements java.util.List list Changing the list contents (includes updates on x.length) can only be achieved if the Java list is modifiable x implements java.util.Map and keys are of type java.lang.String map Changing the map contents can only be achieved if the Java map is modifiable x is a java.lang.(Double|Float|Long|Integer|Short|Byte) or an equivalent primitive number x is a (non-null) java.lang.Boolean or equivalent primitive boolean x is a java.lang.String string (limited) Neither indexing nor x.length can be used null null Except for maps, the following holds for a value x obtained through a Java Call : If x 's class has getters and/or setters for some fields, they can be called. As an example if age and name are available fields, x.age can be used to get the value of age Likewise, setting a value is possible too: x.name = \"Larry\" (if a suitable setter exists) In general, a no-args method starting with get or is can be invoked. This is useful for instance to get the (Java) class name of your object ( x.class.name ) or determine if a list has no elements ( x.empty ) Classpath # A class/interface is accessible to Agama code as long as it is part of: jans-auth.war > WEB-INF/lib/*.jar or, jans-auth.war > WEB-INF/classes or, /opt/jans/jetty/jans-auth/custom/libs/*.jar (may require edition of jans-auth.xml descriptor) Additionally, it is possible to upload source code on the fly to augment the classpath. Any valid Java or Groovy file is accepted and must be located under /opt/jans/jetty/jans-auth/agama/scripts . For instance, a class named com.acme.Person must reside in folder /opt/jans/jetty/jans-auth/agama/scripts/com/acme . Important Only files with extensions .java or .groovy are accounted The scripts directory provides automatic \"hot\" reloading. This is a valuable time saver for developers because there is no need to restart the jans-auth webapp when sources are modified. This feature has some limitations which are explained in the following. Limitations of code added \"on the fly\" # Classes in scripts directory can only be accessed through Call directives. As an example suppose you added classes A and B to scripts , and A depends on B . Call s using class A will work and any change to files A and/or B will be picked automatically. On the contrary, trying to load this kind of classes using Class.forName either from a jar file in custom/libs or from Agama itself will degenerate in ClassNotFoundException . Note A and B can also depend on classes found at any of the locations listed at the beginning of this section. Note Java sources are actually interpreted as Groovy code. 99% of times this is not a concern since Groovy can be considered a superset of Java, however, there are some minor discrepancies that may exhibit unexpected behaviors. These differences are described here . We consider the following to be remarkable: Array literals in shorthand syntax not allowed, e.g. int[] array = {1, 2, 3} . Use int[] array = new int[] {1, 2, 3} instead String interpolation: \"hello $mark\" evaluates the value of variable mark and prepends hello to it!. To avoid this use a backslash, like in \"hello \\$mark\" . Learn more about interpolation here . In general, prepend ocurrences of $ in your string literals with a \\ Usage of == operator actually calls the equals method. Most of times this is fine but can be a problem when you are overriding equals in your class and make use of == . This will introduce a recursive call in your implementation and may degenerate in a stack overflow. If possible, use the === operator or the is method in these cases OOP prose warning # See the recommended practices to learn more about this topic.", "title": "Agama engine"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#janssen-agama-engine", "text": "", "title": "Janssen Agama Engine"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#introduction", "text": "The Janssen Server implements the Agama framework through several components bundled in its authentication server (AS): The engine: the piece of software that actually runs the flows and interacts with the user's browser - sort of a small web application. As expected, these flows are mainly targetted at user authentication A transpiler: code written in Agama language is transpiled to an intermediate representation which can then be interpreted at runtime by the engine The bridge: since the engine itself does not implement an authentication protocol, another piece is required to put flows in the context of a standard authorization framework like OpenId Connect. This is what the bridge does The deployer: a piece of software capable of deploying Agama projects to the engine. The rest of this document describes implementation-specific details of the engine bundled with the Jans Server. These details give shape to the requirements abstractly defined for an Agama-compliant engine . Note Ensure both the Agama engine and the bridge are enabled in the Janssen server to effectively use engine's features", "title": "Introduction"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#launching-flows", "text": "Flows can be launched by sending an (OpenId Connect) authentication request to the user's browser. This usually boils down to making a redirection to a URL looking like https://<jans-server-name>/jans-auth/restv1/authorize?acr_values=agama_flowQname&scope=...&response_type=...&redirect_uri=https...&client_id=...&state=... . Check the OpenId Connect spec for more details. Note Jans Server is spec-compliant. Things to highlight: The acr_values parameter carries the qualified name (identifier) of the flow to launch prefixed with the string agama_ , for example acr_values=agama_test.acme.co If the flow to call receives input parameters, this data can be appended to the acr_values parameter: use a hyphen to separate the flow name and the parameters expressed in Base64 URL encoded format. For example, if the flow had inputs height and color , you would encode the string {\"height\": 190, \"color\": \"blue\"} and the resulting value would be agama_test.acme.co-eyJoZWlnaHQiOiAxOTAsICJjb2xvciI6ICJibHVlIn0 . When a given input variable is not provided, the engine will assign a null value automatically", "title": "Launching flows"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#authentication-and-finish", "text": "When a top-level flow (i.e. one with no parents) finishes successfully, the selection of the user to authenticate is driven by the userId passed in data , as in obj = { success: true, data: { userId: \"john_doe\" } } // map literals cannot be passed directly to Finish - a variable can be used instead Finish obj By default userId maps to the uid attribute that generally all user entries already have in the database of Jans Server, in other words, the \"user name\". This attribute is configurable though via property finish_userid_db_attribute of the bridge script . In some cases, you would like to change that to mail in order to pass things like { success: true, data: { userId: \"john_doe@jd.me\" } } for instance. Important If the database lookup does not produce exactly one user entry, this is treated as a failed authentication attempt by the authentication server. When the authentication succeeds, the whole contents of data are stored in the authentication server's session of the given user under the key agamaData . Contents are serialized to a JSON string previously.", "title": "Authentication and Finish"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#crashes-timeouts-and-failures", "text": "Execution rules define several possible flow states . For crashed, timed out, and finished failed flows, the engine will present proper error pages to users. These are configurable by properties crashErrorPage , interruptionErrorPage , and finishedFlowPage respectively, of the engine-configuration .", "title": "Crashes, timeouts, and failures"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#how-timeouts-work", "text": "Authentication flows are normally short-lived. They usually span no more than a few minutes. In Agama, the maximum amount of time an end-user can take to fully complete a flow is driven by the configuration of the authentication server , specifically the sessionIdUnauthenticatedUnusedLifetime property which is measured in seconds. As an example, if this value is 120, any attempt to authenticate taking more than two minutes will throw the given error page. Moreover, when a flow specifies its own timeout in the header the effective timeout is the smallest value between sessionIdUnauthenticatedUnusedLifetime and the value in the header. Depending on specific needs, sessionIdUnauthenticatedUnusedLifetime may have to be set to a higher value than the server's default. This may be the case where flows send e-mail notifications with temporary codes, for instance.", "title": "How timeouts work"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#logging", "text": "There are three relevant sources of log data: The engine. It emits information related to flows transpilation, projects deployment, and flow crashes - generally low-level information Log instructions. These are statements originated directly from the Agama code Call directives. Foreign code can issue logging statements as well as any other code a Call may depend on. See the FAQ The following table details the location of log data. Paths are relative to directory /opt/jans/jetty/jans-auth/log : Source Destination file Engine jans-auth.log Log instructions jans-auth_script.log Foreign code jans-auth.log Depending on the specificity required, you may have to change the logging level so more or less details appear in the logs. This can be done by altering the loggingLevel property of the auth server configuration . DEBUG usually suffices for troubleshooting. The available levels for statements issued with the Log instruction are: Level name shortcut error e warn w info i debug d trace t For instance, these two instructions are equivalent: Log \"@e Universe collapsed\" and Log \"@error Universe collapsed\" The engine will use info when the level is not specified explicitly, as in Log \"Look ma!\" .", "title": "Logging"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#rfac-and-callback-url", "text": "Engine's callback URL is https://<your-server-name>/jans-auth/fl/callback . This resource is only be available for a given browser session while RFAC is in execution. Once the callback is visited or the flow times out (whichever occurs first), subsequent requests will respond with an HTTP 404 error. The mechanism used for redirection is a \"302 Found\" HTTP redirect that entails a subsequent GET request to the external site. In cases where a POST is expected, the 3-param version of RRF can be useful.", "title": "RFAC and Callback URL"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#rrf-navigation-and-assets-handling", "text": "Understanding how RRF works in the engine is key to writing meaningful flows. This topic is fully covered here .", "title": "RRF, navigation, and assets handling"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#foreign-calls", "text": "In the Jans Agama engine, Java or Groovy code can be called by means of the Call instruction. Specifically, public methods from public classes or static methods from public interfaces. Note Java language background is required for this section. The following exemplifies different kind of usages of Java from Agama code: Example Notes Call java.lang.Integer#parseInt \"FF\" 16 Invokes the parseInt method of Integer class passing the given arguments (i.e. conversion of hexadecimal string to a primitive int ). The returned value is ignored numbers = [ 2, -2, 0, 3, -3, 4 ] small = Call java.util.Collections#min numbers Invokes the min method of the Collections class. Supplies a list of numbers as argument. The smallest number is stored in variable small jLocale = Call java.util.Locale#getDefault localeName = jLocale.displayName Computes the display name of the JVM default locale car = { brand: \"Ford\", model: 1963 } sidecar = Call java.util.Map#copyOf car Makes a deep clone of a map number | E = Call java.lang.Integer#parseInt \"AGA\" 16 When E is not null Log \"An error occurred:\" E.message Similar to the first example. If an exception is thrown by the invocation, it's caught and assigned to variable E . Note both checked and unchecked exceptions are caught | E = Call com.acme.Worker#notifyExternalSystem //Do something with E //... If exception catching is required when calling a method that returns void , there is no need to put a variable before the pipe p1 = Call java.awt.Point#new p2 = Call java.awt.Point#new 1 3 Call p2 translate -1 1 Creates instances of class java.awt.Point with different constructors. For p1 the no-args constructor is used. Method translate is invoked on the p2 instance. Note usage of a space here instead of hash ( # ) cls1 = Call java.lang.CharSequence#class cls2 = Call java.lang.Integer#class Call cls2 parseInt \"FF\" 16 Stores in cls1 a reference to interface class CharSequence.class . Stores in cls2 a reference to Integer.class . The 3rd line statement achieves the same effect of Call java.lang.Integer#parseInt \"FF\" 16 L = [ \"A\", \"B\", \"C\" ] S = Call java.util.Set#of 0 2 4 6 map = { numbers: S, letters: L } hasOne = Call map.numbers contains 1 Calls the contains method of the java.util.Set object stored in map.numbers passing 1 as argument and storing the result in hasOne The usage of a hash sign (or spaces) before a method name helps disambiguate whether the invocation is on a static class method or an object method. This is so because an expression like hey.You may reference the class You on package hey , or the value of key You in a map named hey .", "title": "Foreign calls"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#highlights", "text": "Any method that meets the conditions mentioned (public or interface static) and that is reachable in the JVM classpath can be called; developers are not restricted solely to java.* packages. When using Call , the method to execute is picked based on the name (e.g. after the # sign) and the number of arguments supplied. If a class/interface exhibits several methods with the same name and arity (number of parameters), the method that best matches the dataypes of the arguments with respect to its signature is selected. Sometimes this requires to perform arguments conversions and they may fail. In such case, the second best suited method is tried and so on. When all attempts fail or there are no candidate methods to choose from, the Call simply throws a NoSuchMethodException . For non-static method invocations, i.e. no hash sign, the class used for method lookup is that of the instance passed (the first parameter in the Call directive). This includes all associated superclasses too, as expected. When the instance does not hold a Java but an Agama value, the following is used to pick a class: Agama type Java class for method lookup string String boolean Boolean number Double list java.util.List map java.util.Map Limitations: list and map literals cannot be passed as arguments to method calls directly. This means the following is illegal: Call co.Utils#myMethod { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] . To achieve the same effect assign the literal value to a variable and pass that instead Call ing a method that mutates one or more of the arguments passed will not work properly if the corresponding parameters in the method signature have type information attached. For example, copying a list into another using java.util.Collections#copy\u200b(List<? super T> dest, List<? extends T> src) may not behave as expected. Conversely, calling java.lang.reflect.Array#set\u200b(Object array, int index, Object value) works fine because array does not have a parameterized type. The practice of mutating passed arguments is unusual and sometimes discouraged in programming", "title": "Highlights"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#exception-handling", "text": "As seen in the examples Agama engine can deal with Java exceptions, however, this feature should be used sparingly. When exception handling adds undesired complexity to your code, create wrapper methods in Java and do the processing there instead of delegating that to the DSL.", "title": "Exception handling"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#arguments-conversion", "text": "Agama types do not match Java types. This means passing a \"native\" Agama value as parameter in a method Call requires some form of compatibility with the target (Java) type in the method signature. An argument (Agama value) is compatible with a method parameter if it can be \"converted\" successfully. As we'll see, conversion feels pretty natural in practice. If this process fails a java.lang.IllegalArgumentException is thrown and the flow will crash unless the exception is caught. Note however the recommended practice is to let flows crash . The following lists some of the most common successful conversions: Agama value Can be converted to string String or char[] boolean Boolean or primitive equivalent number Double / Float / Integer / Long / Short / Byte or primitive equivalent null Any non-primitive list Array or class implementing Collection<T> as long as items can be converted to type T map Class implementing Map<K, V> as long as keys and values can be converted to types K and V , respectively map Java bean. Unrecognized properties in Agama value are ignored The below table shows some examples of interesting and handy conversions: Agama value Param data type in target Java method Argument value (Agama) Received param value (in method) Notes Positive number having fractional part Integer / Long / Short / Byte or primitive equivalent 2.6 2 Integer part kept Negative number having fractional part Integer / Long / Short / Byte or primitive equivalent -2.4 2 Integer part kept Integer number Float / Double or primitive equivalent 1 1.0 list of number s List<Integer> [1, 2.0, 3.1, -4.2] [1, 2, 3, -4] Only integer parts kept list of integer number s List<Float> / List<Double> [1, 2, 3, -4] [1.0, 2.0, 3.0, -4.0] string of length 1 Character or primitive equivalent a a Passing a zero, two, or more lengthed string will make the call fail When the argument is not an Agama but a Java object/primitive, the following rules apply: If the value can be cast to the target type, no conversion is needed, otherwise If it is an instance of java.lang.Number and the type is a numeric primitive or wrapper (e.g. Integer ), the value is truncated if required, otherwise The value is serialized to JSON - if possible - and then an attempt to create a Java instance based on the given JSON contents is made. For this purpose, the FasterXML Jackson library is used This is powerful because it allows to send data of similar shape/structure when data types do not necessarily match. Consider the following example: s = \"a man's gotta do what a man's gotta do\" jStrArr = Call s split \" \" words = Call java.util.Collections#unmodifiableSet jStrArr This Agama snippet creates the (Java) Set of different words found in a given (Agama) string . Note jStrArr is of type String[] and is passed directly to method unmodifiableSet which originally expects an instance of Set as parameter.", "title": "Arguments conversion"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#from-java-to-agama", "text": "We just saw how Agama values are treated in Java code. Here we make an analysis in the reverse direction: from Java to Agama where Java values are obtained through Call invocations. The following table relates Java types to Agama types: Java value ( x ) Agama equivalent Notes x is a Java array or implements java.util.List list Changing the list contents (includes updates on x.length) can only be achieved if the Java list is modifiable x implements java.util.Map and keys are of type java.lang.String map Changing the map contents can only be achieved if the Java map is modifiable x is a java.lang.(Double|Float|Long|Integer|Short|Byte) or an equivalent primitive number x is a (non-null) java.lang.Boolean or equivalent primitive boolean x is a java.lang.String string (limited) Neither indexing nor x.length can be used null null Except for maps, the following holds for a value x obtained through a Java Call : If x 's class has getters and/or setters for some fields, they can be called. As an example if age and name are available fields, x.age can be used to get the value of age Likewise, setting a value is possible too: x.name = \"Larry\" (if a suitable setter exists) In general, a no-args method starting with get or is can be invoked. This is useful for instance to get the (Java) class name of your object ( x.class.name ) or determine if a list has no elements ( x.empty )", "title": "From Java to Agama"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#classpath", "text": "A class/interface is accessible to Agama code as long as it is part of: jans-auth.war > WEB-INF/lib/*.jar or, jans-auth.war > WEB-INF/classes or, /opt/jans/jetty/jans-auth/custom/libs/*.jar (may require edition of jans-auth.xml descriptor) Additionally, it is possible to upload source code on the fly to augment the classpath. Any valid Java or Groovy file is accepted and must be located under /opt/jans/jetty/jans-auth/agama/scripts . For instance, a class named com.acme.Person must reside in folder /opt/jans/jetty/jans-auth/agama/scripts/com/acme . Important Only files with extensions .java or .groovy are accounted The scripts directory provides automatic \"hot\" reloading. This is a valuable time saver for developers because there is no need to restart the jans-auth webapp when sources are modified. This feature has some limitations which are explained in the following.", "title": "Classpath"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#limitations-of-code-added-on-the-fly", "text": "Classes in scripts directory can only be accessed through Call directives. As an example suppose you added classes A and B to scripts , and A depends on B . Call s using class A will work and any change to files A and/or B will be picked automatically. On the contrary, trying to load this kind of classes using Class.forName either from a jar file in custom/libs or from Agama itself will degenerate in ClassNotFoundException . Note A and B can also depend on classes found at any of the locations listed at the beginning of this section. Note Java sources are actually interpreted as Groovy code. 99% of times this is not a concern since Groovy can be considered a superset of Java, however, there are some minor discrepancies that may exhibit unexpected behaviors. These differences are described here . We consider the following to be remarkable: Array literals in shorthand syntax not allowed, e.g. int[] array = {1, 2, 3} . Use int[] array = new int[] {1, 2, 3} instead String interpolation: \"hello $mark\" evaluates the value of variable mark and prepends hello to it!. To avoid this use a backslash, like in \"hello \\$mark\" . Learn more about interpolation here . In general, prepend ocurrences of $ in your string literals with a \\ Usage of == operator actually calls the equals method. Most of times this is fine but can be a problem when you are overriding equals in your class and make use of == . This will introduce a recursive call in your implementation and may degenerate in a stack overflow. If possible, use the === operator or the is method in these cases", "title": "Limitations of code added \"on the fly\""}, {"location": "janssen-server/developer/agama/jans-agama-engine/#oop-prose-warning", "text": "See the recommended practices to learn more about this topic.", "title": "OOP prose warning"}, {"location": "janssen-server/developer/agama/native-applications/", "tags": ["developer", "agama", "native apps", "challenge endpoint"], "text": "Agama flows in native applications # Agama is a framework primarily focused on web flows, however, with the Authorization Challenge endpoint of Jans Server, developers can now run their flows outside the browser. This makes possible to offer secure, multi-step authentication flows from desktop and mobile applications without resorting to mechanisms like Web Views that substantially degrade the user experience. Additionally, the same already-familiar tools for authoring and deploying Agama projects can be used for the job. Moreover, the flows built for the web can be run in the native world without modification, requiring only to code the respective native UI and the logic that interacts with the Authorization Challenge endpoint, called \"the endpoint\" hereafter. In this document, we present an overview of how the endpoint works to make your Agama flows run without a web browser. Preliminar acquaintance with the following topics is recommended: Agama DSL and .gama format Agama projects deployment in the Janssen Server Execution rules in the Jans Agama engine A basic understanding of OAuth 2.0 for First-Party Applications How do flows actually run? # Before getting into the technicalities, let's cover some key preliminar concepts. The engine - the piece of software that actually runs flows - is eminently driven by HTTP requests. This is unsurprising because the main \"consumers\" of the engine are web browsers. When targetting native apps, the engine remains the same, and flows still run at the server side. This means native apps won't hold any business logic, or make computations of significance. The RRF (render-reply-fetch) Agama instruction is of paramount importance in flows. In a regular web setting, it involves three steps: Injecting some data to a UI template in order to generate HTML markup. This is known as rendering Reply the markup to the web browser - this will display a web page At the server side, retrieve data the user may have provided in his interaction with the page. This is, fetch In a native setting no HTML markup is suppossed to be generated and replied - it's the app that is in charge of displaying the UI now. For this purpose, it will receive (from the endpoint) the data that would be originally injected into the template. Most of times, this will carry information gathered at earlier stages of the flow and that is relevant to properly show or update the UI. Likewise, the \"data submission\" for the fetch phase of RRF is performed by the app too. In this case, the relevant data grabbed from the user interaction is sent to the server side (via challenge endpoint) and becomes the result of the RRF (the value for the variable on the left-hand side of the instruction). Note both the input (\"injected\" data) and the output (result) is specified in JSON format. Once the fetch occurs, the flow proceeds its execution until another RRF instruction is hit, where the procedure described above takes place again. Note this approach has two big benefits: Regular web flows can be reused in the native world without modifications The mindset for flows design remain the same There is a subtle exception regarding the first statement and has to do with flows containing RFAC instructions. RFAC is used to redirect to external sites, and as such, it requires a web browser. In the case of native apps, flows will crash once an RFAC instruction is hit. Inversion of control in apps # The above concepts bring an important constraint to app design that should be accounted before undertaking any project: control is inverted. Normally, an app \"knows\" exactly what to do at each step of its workflow, and eventually delegates data retrieval tasks to the server side. When using the endpoint, the server side drives the logic: the app does not \"take decisions\" and instead \"reacts\" to the received data. This will be demostrated later through a practical example. About the example: OTP via e-mail # To avoid a rather abstract explanation, we'll use an example to illustrate the steps required to run a flow from a native app. Suppose an authentication flow operating in the following manner: A username is prompted If the corresponding user has no e-mail associated to his account, the flow ends with an error message If the user has exactly one e-mail in his profile, a random one-time passcode (OTP) is sent to his registered address If the user has more than one e-mail, a screen is shown to pick the address where he would like the OTP be sent to The user is prompted to enter the passcode sent. If supplied correctly, the flow ends and the user is authenticated, otherwise the flow ends with an error This hypothetical flow is simple but will give you a good idea on how to interact with the endpoint. The flow code # The below depicts the implementation: Flow co.acme.flows.emailOtp is self-explanatory and does not require further insight. Note the templates referenced in RRF directives don't necessarily have to exist, however, the template names will be included in the output of the endpoint as the flow executes. This serves as a hint or reference for the app to know the current point of execution and determine what should be shown in the UI. It will be more clearly seen in the next section. Running the flow # Requisites # To be able to run an Agama flow from a native app using the endpoint, it is required to register an OAuth Client in the Jans server with at least the authorization_challenge scope. The process of client registration is beyond the scope of this document. All HTTP requests exemplified here make use of curl . Ensure this tool is familiar to you. Workflow # Requests to the endpoint are all issued to the URL https://<jans-hostname>/jans-auth/restv1/authorize-challenge using the POST verb. Responses will contain JSON content whose structure will vary depending on the result of the operation as we will see. Once the first request is sent, the flow will start and all instructions will be executed until an RRF is found. Here the flow will be paused, and the endpoint will respond with the data that was passed to RRF: the template path and the \"injected\" data. Let's start issuing real requests now. Initial request # In the first request, at least the following parameters must be passed: Name Value acr_values agama_challenge use_auth_session true client_id The client identifier of a previously registered client flow_name The qualified name of the flow to launch So in our example, it may look like: curl -i -d acr_values=agama_challenge -d use_auth_session=true -d flow_name=co.acme.flows.emailOtp -d client_id=<client-id> https://<jans-hostname>/jans-auth/restv1/authorize-challenge Note This command, as all others following has been split into several lines for better readability. The response will look like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"username-prompt.ftl\" }, \"auth_session\": \"BmAiCeArLdAa0\", } While this may look like something wrong happened, it is not really the case. This is derived from the spec the endpoint adheres to, where the authorization server must report every intermediate response as an error with a 401 status code. The value of the error property references a section that contains the template path. Here it corresponds to the first RRF instruction reached in the execution (line 4 in the flow's code). Particularly this RRF was not invoked passing two parameters, so there is only one property inside the flow_paused JSON object. Note the presence of auth_session . This value allows the authorization server to associate subsequent requests issued by the app with this specific flow execution. Based on this response, the app should render UI elements in order to capture the username. Here, username-prompt.ftl serves as a hint for the app to know the point of execution the flow is at currently. Subsequent requests # From here onwards, requests must contain the following parameters: Name Value use_auth_session true auth_session The value obtained in the previous request data A JSON object value which will become the result of the RRF instruction the flow is paused at Note Whenever a request is missing the auth_session param, it is assumed the inital request is being attempted. Let's assume the user entered Joan as username in the app. A request like the below can then be issued so the variable obj at line 4 is assigned a value: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"username\": \"Joan\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge This will make the flow advance until the next RRF is reached. Suppose the user Joan was found to have two e-mail addresses: joan@doe.com and joan@deere.com . This will make the flow hit line 23. The response will look as follows: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"email-prompt.ftl\", \"addresses\": [ \"joan@doe.com\", \"joan@deere.com\" ] }, \"auth_session\": \"BmAiCeArLdAa0\", } Note the flow_paused section has the contents of the object prepared in line 22. Based on this response, now the app should show a selection list for the user to pick one of these addresses. Once the selection is made, a new request can be issued: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"email\": \"joan@doe.com\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge The flow will continue and the hypothetical message will be sent to joan@doe.com (line 28). Then the next RRF is reached (line 32) and we get as response: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"passcode-prompt.ftl\" }, \"auth_session\": \"BmAiCeArLdAa0\", } The app must now update the UI so the passcode is prompted. When ready, a new request comes: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"otp\": \"123456\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge Assuming the entered code (123456) was correct, the response would look like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_finished\", \"flow_finished\": { \"data\": { \"userId\": \"Joan\" }, \"success\": true }, \"auth_session\": \"efb10525-6c43-4e50-88ab-92461c258526\" } This means we have hit line 37. When a Finish instruction is reached it is fully executed and the error reported in the response changes to flow_finished . What is left now is binding the user identified by userId (Joan) to the authorization request we have been handling ( BmAiCeArLdAa0 ). This is how the user actually gets authenticated. Final request # To authenticate the user, we issue one last request: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true https://<jans-hostname>/jans-auth/restv1/authorize-challenge Note parameter data is not needed. As response we obtain: HTTP/1.1 200 OK Content-Type: application/json ... { \"authorization_code\" : \"SplxlOBeZQQYbYS6WxSbIA\" } Once an authorization code has been obtained, the app can request an access token. This topic is beyond the scope of this document. At this point, the app can update the UI giving the user access to the actual app contents. No more requests are expected to be received by the endpoint with the given auth_session value. Understanding errors # So far we have been following the \"happy\" path in the example flow where all assumptions are met. This is unrealistic so here we offer an overview of how the endpoint behaves when abnormal conditions come up. Note In this section, we stick to the terminology found here . Missing parameters # Assume the following request is issued: curl -i -d use_auth_session=true -d acr_values=agama_challenge -d client_id=<client-id> https://<jans-hostname>/jans-auth/restv1/authorize-challenge This lacks the name of the flow to launch. The response is: HTTP/1.1 400 Bad Request Content-Type: application/json ... { \"error\": \"missing_param\", \"missing_param\": { \"description\": \"Parameter 'flow_name' missing in request\" } } Failed flows # Many times, flows simply fail as a way to reject access. This is achived in Agama by using code like: obj = { success: false, error: \"You are too suspicious\" } Finish obj In this case, the response looks like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_finished\", \"flow_finished\": { \"success\": false, \"error\": \"You are too suspicious\" } } Note auth_session is not replied. As such, no more requests to the endpoint should be made passing the auth_session value obtained earlier. Engine errors # There are several conditions under which the engine produces errors. In these cases, the HTTP error emitted by the engine is included in the endpoint response. As in previous error scenarios, no auth_session is replied. Flow timeout # With native apps, timeout of flows obeys the same rules of the web scenario. The only difference is the server property employed for the timeout calculation, namely, authorizationChallengeSessionLifetimeInSeconds . If absent, it defaults to one day. Here is how a flow timeout is reported: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"message\": \"You have exceeded the amount of time required to complete your authentication\", \"timeout\": true }, \"contentType\": \"application/json\", \"status\": 410 } } Crashed flow # When a flow crashes, the error is reported in similar way the timeout is reported. Here are some examples: An attempt to access a property or index of a null variable in Agama code HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"TypeError: Cannot read property \\\"x\\\" from null\" }, \"contentType\": \"application/json\", \"status\": 500 } } A variable does not meet the expected shape for a given Agama directive HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"TypeError: Data passed to RRF was not a map or Java equivalent\" }, \"contentType\": \"application/json\", \"status\": 500 } } Indexing a string in Java beyond length HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"String index out of range: 100\" }, \"contentType\": \"application/json\", \"status\": 500 } } Other errors # There are a variety of miscelaneous errors. Here we describe the most common. Finished flows with problems of user identification # When a Finish instruction does not include a reference to a user identifier, or if the referenced user does not exist, the endpoint responds like: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"unexpected_error\", \"unexpected_error\": { \"description\": \"Unable to determine identity of user\" } } Attempt to launch an unknown flow # If the initial request references an inexisting flow or one that has been flagged as not launchable directly by clients. HTTP/1.1 500 Server Error Content-Type: application/json ... { \"unexpected_error\": {\"description\": \"Flow ... does not exist or cannot be launched an application\"}, \"error\": \"unexpected_error\" } Agama is disabled # If the Agama engine is disabled, the following is generated upon the first request: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"unexpected_error\", \"unexpected_error\": { \"description\": \"Agama engine is disabled\" } }", "title": "Agama flows in native applications"}, {"location": "janssen-server/developer/agama/native-applications/#agama-flows-in-native-applications", "text": "Agama is a framework primarily focused on web flows, however, with the Authorization Challenge endpoint of Jans Server, developers can now run their flows outside the browser. This makes possible to offer secure, multi-step authentication flows from desktop and mobile applications without resorting to mechanisms like Web Views that substantially degrade the user experience. Additionally, the same already-familiar tools for authoring and deploying Agama projects can be used for the job. Moreover, the flows built for the web can be run in the native world without modification, requiring only to code the respective native UI and the logic that interacts with the Authorization Challenge endpoint, called \"the endpoint\" hereafter. In this document, we present an overview of how the endpoint works to make your Agama flows run without a web browser. Preliminar acquaintance with the following topics is recommended: Agama DSL and .gama format Agama projects deployment in the Janssen Server Execution rules in the Jans Agama engine A basic understanding of OAuth 2.0 for First-Party Applications", "title": "Agama flows in native applications"}, {"location": "janssen-server/developer/agama/native-applications/#how-do-flows-actually-run", "text": "Before getting into the technicalities, let's cover some key preliminar concepts. The engine - the piece of software that actually runs flows - is eminently driven by HTTP requests. This is unsurprising because the main \"consumers\" of the engine are web browsers. When targetting native apps, the engine remains the same, and flows still run at the server side. This means native apps won't hold any business logic, or make computations of significance. The RRF (render-reply-fetch) Agama instruction is of paramount importance in flows. In a regular web setting, it involves three steps: Injecting some data to a UI template in order to generate HTML markup. This is known as rendering Reply the markup to the web browser - this will display a web page At the server side, retrieve data the user may have provided in his interaction with the page. This is, fetch In a native setting no HTML markup is suppossed to be generated and replied - it's the app that is in charge of displaying the UI now. For this purpose, it will receive (from the endpoint) the data that would be originally injected into the template. Most of times, this will carry information gathered at earlier stages of the flow and that is relevant to properly show or update the UI. Likewise, the \"data submission\" for the fetch phase of RRF is performed by the app too. In this case, the relevant data grabbed from the user interaction is sent to the server side (via challenge endpoint) and becomes the result of the RRF (the value for the variable on the left-hand side of the instruction). Note both the input (\"injected\" data) and the output (result) is specified in JSON format. Once the fetch occurs, the flow proceeds its execution until another RRF instruction is hit, where the procedure described above takes place again. Note this approach has two big benefits: Regular web flows can be reused in the native world without modifications The mindset for flows design remain the same There is a subtle exception regarding the first statement and has to do with flows containing RFAC instructions. RFAC is used to redirect to external sites, and as such, it requires a web browser. In the case of native apps, flows will crash once an RFAC instruction is hit.", "title": "How do flows actually run?"}, {"location": "janssen-server/developer/agama/native-applications/#inversion-of-control-in-apps", "text": "The above concepts bring an important constraint to app design that should be accounted before undertaking any project: control is inverted. Normally, an app \"knows\" exactly what to do at each step of its workflow, and eventually delegates data retrieval tasks to the server side. When using the endpoint, the server side drives the logic: the app does not \"take decisions\" and instead \"reacts\" to the received data. This will be demostrated later through a practical example.", "title": "Inversion of control in apps"}, {"location": "janssen-server/developer/agama/native-applications/#about-the-example-otp-via-e-mail", "text": "To avoid a rather abstract explanation, we'll use an example to illustrate the steps required to run a flow from a native app. Suppose an authentication flow operating in the following manner: A username is prompted If the corresponding user has no e-mail associated to his account, the flow ends with an error message If the user has exactly one e-mail in his profile, a random one-time passcode (OTP) is sent to his registered address If the user has more than one e-mail, a screen is shown to pick the address where he would like the OTP be sent to The user is prompted to enter the passcode sent. If supplied correctly, the flow ends and the user is authenticated, otherwise the flow ends with an error This hypothetical flow is simple but will give you a good idea on how to interact with the endpoint.", "title": "About the example: OTP via e-mail"}, {"location": "janssen-server/developer/agama/native-applications/#the-flow-code", "text": "The below depicts the implementation: Flow co.acme.flows.emailOtp is self-explanatory and does not require further insight. Note the templates referenced in RRF directives don't necessarily have to exist, however, the template names will be included in the output of the endpoint as the flow executes. This serves as a hint or reference for the app to know the current point of execution and determine what should be shown in the UI. It will be more clearly seen in the next section.", "title": "The flow code"}, {"location": "janssen-server/developer/agama/native-applications/#running-the-flow", "text": "", "title": "Running the flow"}, {"location": "janssen-server/developer/agama/native-applications/#requisites", "text": "To be able to run an Agama flow from a native app using the endpoint, it is required to register an OAuth Client in the Jans server with at least the authorization_challenge scope. The process of client registration is beyond the scope of this document. All HTTP requests exemplified here make use of curl . Ensure this tool is familiar to you.", "title": "Requisites"}, {"location": "janssen-server/developer/agama/native-applications/#workflow", "text": "Requests to the endpoint are all issued to the URL https://<jans-hostname>/jans-auth/restv1/authorize-challenge using the POST verb. Responses will contain JSON content whose structure will vary depending on the result of the operation as we will see. Once the first request is sent, the flow will start and all instructions will be executed until an RRF is found. Here the flow will be paused, and the endpoint will respond with the data that was passed to RRF: the template path and the \"injected\" data. Let's start issuing real requests now.", "title": "Workflow"}, {"location": "janssen-server/developer/agama/native-applications/#initial-request", "text": "In the first request, at least the following parameters must be passed: Name Value acr_values agama_challenge use_auth_session true client_id The client identifier of a previously registered client flow_name The qualified name of the flow to launch So in our example, it may look like: curl -i -d acr_values=agama_challenge -d use_auth_session=true -d flow_name=co.acme.flows.emailOtp -d client_id=<client-id> https://<jans-hostname>/jans-auth/restv1/authorize-challenge Note This command, as all others following has been split into several lines for better readability. The response will look like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"username-prompt.ftl\" }, \"auth_session\": \"BmAiCeArLdAa0\", } While this may look like something wrong happened, it is not really the case. This is derived from the spec the endpoint adheres to, where the authorization server must report every intermediate response as an error with a 401 status code. The value of the error property references a section that contains the template path. Here it corresponds to the first RRF instruction reached in the execution (line 4 in the flow's code). Particularly this RRF was not invoked passing two parameters, so there is only one property inside the flow_paused JSON object. Note the presence of auth_session . This value allows the authorization server to associate subsequent requests issued by the app with this specific flow execution. Based on this response, the app should render UI elements in order to capture the username. Here, username-prompt.ftl serves as a hint for the app to know the point of execution the flow is at currently.", "title": "Initial request"}, {"location": "janssen-server/developer/agama/native-applications/#subsequent-requests", "text": "From here onwards, requests must contain the following parameters: Name Value use_auth_session true auth_session The value obtained in the previous request data A JSON object value which will become the result of the RRF instruction the flow is paused at Note Whenever a request is missing the auth_session param, it is assumed the inital request is being attempted. Let's assume the user entered Joan as username in the app. A request like the below can then be issued so the variable obj at line 4 is assigned a value: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"username\": \"Joan\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge This will make the flow advance until the next RRF is reached. Suppose the user Joan was found to have two e-mail addresses: joan@doe.com and joan@deere.com . This will make the flow hit line 23. The response will look as follows: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"email-prompt.ftl\", \"addresses\": [ \"joan@doe.com\", \"joan@deere.com\" ] }, \"auth_session\": \"BmAiCeArLdAa0\", } Note the flow_paused section has the contents of the object prepared in line 22. Based on this response, now the app should show a selection list for the user to pick one of these addresses. Once the selection is made, a new request can be issued: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"email\": \"joan@doe.com\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge The flow will continue and the hypothetical message will be sent to joan@doe.com (line 28). Then the next RRF is reached (line 32) and we get as response: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"passcode-prompt.ftl\" }, \"auth_session\": \"BmAiCeArLdAa0\", } The app must now update the UI so the passcode is prompted. When ready, a new request comes: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"otp\": \"123456\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge Assuming the entered code (123456) was correct, the response would look like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_finished\", \"flow_finished\": { \"data\": { \"userId\": \"Joan\" }, \"success\": true }, \"auth_session\": \"efb10525-6c43-4e50-88ab-92461c258526\" } This means we have hit line 37. When a Finish instruction is reached it is fully executed and the error reported in the response changes to flow_finished . What is left now is binding the user identified by userId (Joan) to the authorization request we have been handling ( BmAiCeArLdAa0 ). This is how the user actually gets authenticated.", "title": "Subsequent requests"}, {"location": "janssen-server/developer/agama/native-applications/#final-request", "text": "To authenticate the user, we issue one last request: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true https://<jans-hostname>/jans-auth/restv1/authorize-challenge Note parameter data is not needed. As response we obtain: HTTP/1.1 200 OK Content-Type: application/json ... { \"authorization_code\" : \"SplxlOBeZQQYbYS6WxSbIA\" } Once an authorization code has been obtained, the app can request an access token. This topic is beyond the scope of this document. At this point, the app can update the UI giving the user access to the actual app contents. No more requests are expected to be received by the endpoint with the given auth_session value.", "title": "Final request"}, {"location": "janssen-server/developer/agama/native-applications/#understanding-errors", "text": "So far we have been following the \"happy\" path in the example flow where all assumptions are met. This is unrealistic so here we offer an overview of how the endpoint behaves when abnormal conditions come up. Note In this section, we stick to the terminology found here .", "title": "Understanding errors"}, {"location": "janssen-server/developer/agama/native-applications/#missing-parameters", "text": "Assume the following request is issued: curl -i -d use_auth_session=true -d acr_values=agama_challenge -d client_id=<client-id> https://<jans-hostname>/jans-auth/restv1/authorize-challenge This lacks the name of the flow to launch. The response is: HTTP/1.1 400 Bad Request Content-Type: application/json ... { \"error\": \"missing_param\", \"missing_param\": { \"description\": \"Parameter 'flow_name' missing in request\" } }", "title": "Missing parameters"}, {"location": "janssen-server/developer/agama/native-applications/#failed-flows", "text": "Many times, flows simply fail as a way to reject access. This is achived in Agama by using code like: obj = { success: false, error: \"You are too suspicious\" } Finish obj In this case, the response looks like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_finished\", \"flow_finished\": { \"success\": false, \"error\": \"You are too suspicious\" } } Note auth_session is not replied. As such, no more requests to the endpoint should be made passing the auth_session value obtained earlier.", "title": "Failed flows"}, {"location": "janssen-server/developer/agama/native-applications/#engine-errors", "text": "There are several conditions under which the engine produces errors. In these cases, the HTTP error emitted by the engine is included in the endpoint response. As in previous error scenarios, no auth_session is replied.", "title": "Engine errors"}, {"location": "janssen-server/developer/agama/native-applications/#flow-timeout", "text": "With native apps, timeout of flows obeys the same rules of the web scenario. The only difference is the server property employed for the timeout calculation, namely, authorizationChallengeSessionLifetimeInSeconds . If absent, it defaults to one day. Here is how a flow timeout is reported: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"message\": \"You have exceeded the amount of time required to complete your authentication\", \"timeout\": true }, \"contentType\": \"application/json\", \"status\": 410 } }", "title": "Flow timeout"}, {"location": "janssen-server/developer/agama/native-applications/#crashed-flow", "text": "When a flow crashes, the error is reported in similar way the timeout is reported. Here are some examples: An attempt to access a property or index of a null variable in Agama code HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"TypeError: Cannot read property \\\"x\\\" from null\" }, \"contentType\": \"application/json\", \"status\": 500 } } A variable does not meet the expected shape for a given Agama directive HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"TypeError: Data passed to RRF was not a map or Java equivalent\" }, \"contentType\": \"application/json\", \"status\": 500 } } Indexing a string in Java beyond length HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"String index out of range: 100\" }, \"contentType\": \"application/json\", \"status\": 500 } }", "title": "Crashed flow"}, {"location": "janssen-server/developer/agama/native-applications/#other-errors", "text": "There are a variety of miscelaneous errors. Here we describe the most common.", "title": "Other errors"}, {"location": "janssen-server/developer/agama/native-applications/#finished-flows-with-problems-of-user-identification", "text": "When a Finish instruction does not include a reference to a user identifier, or if the referenced user does not exist, the endpoint responds like: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"unexpected_error\", \"unexpected_error\": { \"description\": \"Unable to determine identity of user\" } }", "title": "Finished flows with problems of user identification"}, {"location": "janssen-server/developer/agama/native-applications/#attempt-to-launch-an-unknown-flow", "text": "If the initial request references an inexisting flow or one that has been flagged as not launchable directly by clients. HTTP/1.1 500 Server Error Content-Type: application/json ... { \"unexpected_error\": {\"description\": \"Flow ... does not exist or cannot be launched an application\"}, \"error\": \"unexpected_error\" }", "title": "Attempt to launch an unknown flow"}, {"location": "janssen-server/developer/agama/native-applications/#agama-is-disabled", "text": "If the Agama engine is disabled, the following is generated upon the first request: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"unexpected_error\", \"unexpected_error\": { \"description\": \"Agama engine is disabled\" } }", "title": "Agama is disabled"}, {"location": "janssen-server/developer/agama/projects-deployment/", "tags": ["administration", "developer", "agama"], "text": "Agama projects deployment # The Agama framework defines a file format to package and distribute Agama projects. Here we describe the process of deployment in the Jans Agama engine. Workflow # Deployment occurs through a REST API. Here is a typical workflow once a .gama file is ready: Send (POST) the archive contents to the deployment endpoint. Normally a 202 response should be obtained meaning a task has been queued for processing Poll (via GET) the status of the deployment. When the archive has been effectively deployed a status of 200 should be obtained. It may take up to 30 seconds for the process to complete once the archive is sent. This time may extend if there is another deployment in course Optionally supply configuration properties for flows if needed. This is done via PUT to the /configs endpoint. The response of the previous step may contain descriptive/sample configurations that can be used as a guide Test the deployed flows and adjust the archive for any changes required Go to point 1 if needed. If configuration properties were previously set and no changes are required in this regard, step 3 can be skipped If desired, a request can be sent to undeploy the flows (via DELETE) The following tables summarize the available endpoints. All URLs are relative to /jans-config-api/api/v1 . An OpenAPI document is also available here . Endpoint -> /agama-deployment Purpose Retrieve a list of deployments in the server. This is not a search, just a paged listing Method GET Query params start and count helps paginating results. start is 0-index based. Both params optional Output Existing deployments (regardless they are thoroughly processed or still being deployed). They are listed and sorted by deployment date Sample output {\"start\":...,\"totalEntriesCount\":...,\"entriesCount\":...,\"entries\":[ ... ]} Status 200 (OK) Endpoint -> /agama-deployment/{name} Purpose Retrieve details of a single deployment by name Method GET Path params name Sample output The structure of a deployment is explained below Status 200 (deployment task is finished), 204 (task still in course), 404 (project unknown) Deployment structure Notes Example dn Distinguished name jansId=123,ou=deployments,ou=agama,o=jans id Identifier of deployment (generated automatically) 115276 createdAt Datetime (in UTC) of the instant the deployment task was created (POSTed) 2022-12-07T21:47:42 taskActive Boolean value indicating if the deployment task is being currently processed, ie. the gama file is being scanned, flows analysed, etc. false finishedAt Datetime (in UTC) representing the instant when the deployment task was finished, or null if it hasn't ended 2022-12-07T21:48:42 details Extra details, see below Deployment details structure Notes Example projectMetadata Includes author, type, description, project's name, and example configuration - as supplied when the deployment task was created error A general description of the error (if presented) when processing the task, otherwise null Archive missing web and/or code subdirectories flowsError A mapping of the errors obtained per flow found in the archive. The keys correspond to qualified names. A null value indicates the flow was successfully added { \"co.acme.example\": \"Syntax error on line 4\", \"io.jans.test\": null } libs A listing of paths to java , groovy , or jar files included in the project archive Endpoint -> /agama-deployment/{name} Purpose Add or replace an Agama project to the server Method POST Path params name (the project's name) Body The binary contents of a .gama file; example here . Ensure to use header Content-Type: application/zip Query params autoconfigure - passing true will make this project be configured with the sample configurations found in the provided binary archive ( configs section of project.json ). This param should rarely be passed: use only in controlled environments where the archive is not shared with third parties Output Textual explanation, e.g. A deployment task for project XXX has been queued. Use the GET endpoint to poll status Status 202 (the task was created and scheduled for deployment), 409 (there is a task already for this project and it hasn't finished yet), 400 (a param is missing) Endpoint -> /agama-deployment/configs/{name} Purpose Retrieve the configurations associated to flows that belong to the project of interest. The project must have been already processed fully Method GET Path params name (the project's name) Output A JSON object whose properties are flow names and values correspond to configuration properties defined (JSON objects too) Status 200 (successful response), 204 (this project is still in course of deployment), 404 (unknown project) Endpoint -> /agama-deployment/configs/{name} Purpose Set or replace the configurations associated to flows that belong to the project of interest. The project must have been already processed fully Method PUT Path params name (the project's name) Body JSON payload Output A JSON object whose properties are flow names and values correspond to a boolean indicating the success of the update for the given flow Status 200 (successful response), 204 (this project is still in course of deployment), 404 (unknown project), 400 (a param is missing) Endpoint -> /agama-deployment/{name} Purpose Undeploy an Agama project from the server. Entails removing flows and assets initally supplied Method DELETE Path params name (the project's name) Status 204 (scheduled for removal), 409 (the project is being deployed currently), 404 (unknown project) Endpoints access # API operations are protected by Oauth2 scopes this way: GET: https://jans.io/oauth/config/agama.readonly POST: https://jans.io/oauth/config/agama.write DELETE: https://jans.io/oauth/config/agama.delete Internals of deployment # This section offers details on how the server deploys a .gama file. In summary five steps take place once the deployment task is picked up: Input payload validation Flows transpilation Transfer of libraries Transfer of assets and source files Task finalization After the initial validation of structure takes place, the code directory is scanned for flow files and every flow is transpiled and added to the database if its transpilation was successful. Next, jar files found are transferred to the server's custom libs directory - this only applies for VM-based installations. Then a transfer of templates and assets from web directory followed by copying Groovy/Java sources (from lib ) takes place. Finally the deployment task is marked as finalized and a status summary saved to database for later retrieval. Notes: Developers are required to restart the authentication server for the classes in jar files to be effectively picked up Steps 3 and 4 are carried out only if all flows passed transpilation successfully In Cloud Native environments only one node takes charge of processing a given deployment thoroughly. Other nodes will automatically sync with regards to the files of step 4. The API also offers undeployment capabilities. Here is how it works: Directories holding templates and assets are removed Source files and jar files are removed, if any Flows are removed from database The above applies only for the artifacts originally part of the deployment, of course. Again, nodes in Cloud Native installations will sync accordingly.", "title": "Projects deployment"}, {"location": "janssen-server/developer/agama/projects-deployment/#agama-projects-deployment", "text": "The Agama framework defines a file format to package and distribute Agama projects. Here we describe the process of deployment in the Jans Agama engine.", "title": "Agama projects deployment"}, {"location": "janssen-server/developer/agama/projects-deployment/#workflow", "text": "Deployment occurs through a REST API. Here is a typical workflow once a .gama file is ready: Send (POST) the archive contents to the deployment endpoint. Normally a 202 response should be obtained meaning a task has been queued for processing Poll (via GET) the status of the deployment. When the archive has been effectively deployed a status of 200 should be obtained. It may take up to 30 seconds for the process to complete once the archive is sent. This time may extend if there is another deployment in course Optionally supply configuration properties for flows if needed. This is done via PUT to the /configs endpoint. The response of the previous step may contain descriptive/sample configurations that can be used as a guide Test the deployed flows and adjust the archive for any changes required Go to point 1 if needed. If configuration properties were previously set and no changes are required in this regard, step 3 can be skipped If desired, a request can be sent to undeploy the flows (via DELETE) The following tables summarize the available endpoints. All URLs are relative to /jans-config-api/api/v1 . An OpenAPI document is also available here . Endpoint -> /agama-deployment Purpose Retrieve a list of deployments in the server. This is not a search, just a paged listing Method GET Query params start and count helps paginating results. start is 0-index based. Both params optional Output Existing deployments (regardless they are thoroughly processed or still being deployed). They are listed and sorted by deployment date Sample output {\"start\":...,\"totalEntriesCount\":...,\"entriesCount\":...,\"entries\":[ ... ]} Status 200 (OK) Endpoint -> /agama-deployment/{name} Purpose Retrieve details of a single deployment by name Method GET Path params name Sample output The structure of a deployment is explained below Status 200 (deployment task is finished), 204 (task still in course), 404 (project unknown) Deployment structure Notes Example dn Distinguished name jansId=123,ou=deployments,ou=agama,o=jans id Identifier of deployment (generated automatically) 115276 createdAt Datetime (in UTC) of the instant the deployment task was created (POSTed) 2022-12-07T21:47:42 taskActive Boolean value indicating if the deployment task is being currently processed, ie. the gama file is being scanned, flows analysed, etc. false finishedAt Datetime (in UTC) representing the instant when the deployment task was finished, or null if it hasn't ended 2022-12-07T21:48:42 details Extra details, see below Deployment details structure Notes Example projectMetadata Includes author, type, description, project's name, and example configuration - as supplied when the deployment task was created error A general description of the error (if presented) when processing the task, otherwise null Archive missing web and/or code subdirectories flowsError A mapping of the errors obtained per flow found in the archive. The keys correspond to qualified names. A null value indicates the flow was successfully added { \"co.acme.example\": \"Syntax error on line 4\", \"io.jans.test\": null } libs A listing of paths to java , groovy , or jar files included in the project archive Endpoint -> /agama-deployment/{name} Purpose Add or replace an Agama project to the server Method POST Path params name (the project's name) Body The binary contents of a .gama file; example here . Ensure to use header Content-Type: application/zip Query params autoconfigure - passing true will make this project be configured with the sample configurations found in the provided binary archive ( configs section of project.json ). This param should rarely be passed: use only in controlled environments where the archive is not shared with third parties Output Textual explanation, e.g. A deployment task for project XXX has been queued. Use the GET endpoint to poll status Status 202 (the task was created and scheduled for deployment), 409 (there is a task already for this project and it hasn't finished yet), 400 (a param is missing) Endpoint -> /agama-deployment/configs/{name} Purpose Retrieve the configurations associated to flows that belong to the project of interest. The project must have been already processed fully Method GET Path params name (the project's name) Output A JSON object whose properties are flow names and values correspond to configuration properties defined (JSON objects too) Status 200 (successful response), 204 (this project is still in course of deployment), 404 (unknown project) Endpoint -> /agama-deployment/configs/{name} Purpose Set or replace the configurations associated to flows that belong to the project of interest. The project must have been already processed fully Method PUT Path params name (the project's name) Body JSON payload Output A JSON object whose properties are flow names and values correspond to a boolean indicating the success of the update for the given flow Status 200 (successful response), 204 (this project is still in course of deployment), 404 (unknown project), 400 (a param is missing) Endpoint -> /agama-deployment/{name} Purpose Undeploy an Agama project from the server. Entails removing flows and assets initally supplied Method DELETE Path params name (the project's name) Status 204 (scheduled for removal), 409 (the project is being deployed currently), 404 (unknown project)", "title": "Workflow"}, {"location": "janssen-server/developer/agama/projects-deployment/#endpoints-access", "text": "API operations are protected by Oauth2 scopes this way: GET: https://jans.io/oauth/config/agama.readonly POST: https://jans.io/oauth/config/agama.write DELETE: https://jans.io/oauth/config/agama.delete", "title": "Endpoints access"}, {"location": "janssen-server/developer/agama/projects-deployment/#internals-of-deployment", "text": "This section offers details on how the server deploys a .gama file. In summary five steps take place once the deployment task is picked up: Input payload validation Flows transpilation Transfer of libraries Transfer of assets and source files Task finalization After the initial validation of structure takes place, the code directory is scanned for flow files and every flow is transpiled and added to the database if its transpilation was successful. Next, jar files found are transferred to the server's custom libs directory - this only applies for VM-based installations. Then a transfer of templates and assets from web directory followed by copying Groovy/Java sources (from lib ) takes place. Finally the deployment task is marked as finalized and a status summary saved to database for later retrieval. Notes: Developers are required to restart the authentication server for the classes in jar files to be effectively picked up Steps 3 and 4 are carried out only if all flows passed transpilation successfully In Cloud Native environments only one node takes charge of processing a given deployment thoroughly. Other nodes will automatically sync with regards to the files of step 4. The API also offers undeployment capabilities. Here is how it works: Directories holding templates and assets are removed Source files and jar files are removed, if any Flows are removed from database The above applies only for the artifacts originally part of the deployment, of course. Again, nodes in Cloud Native installations will sync accordingly.", "title": "Internals of deployment"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/", "tags": ["administration", "developer", "agama", "agama lab"], "text": "Quick Start Using Agama Lab # In this quick start guide, we will build, deploy and test a simple password-based authentication flow using Agama and Agama Lab . Agama Lab is an online visual editor to build authentication flows. A flow built on Agama Lab is packaged as a .gama project file. .gama package needs to be manually deployed on Janssen Server where the Agama engine will execute the flow when an authentication request is received. Major Steps involved in this process are: Create Agama project using Agama Lab Deploying .gama package on Janssen Server Testing the authentication flow This guide covers these steps in the following sections. Prerequisites # Janssen Server instance A public GitHub repository with at least one prior commit Create Agama Project # We will use Agama Lab to create a simple username-password based user authentication flow. This involves defining the authentication steps, designing the user interface to capture user inputs, and lastly, releasing the flow as an Agama project. Defining The Authentication Flow # Log Into Agama Lab # Go to Agama Lab login page. Authenticate on the GitHub authentication page. Input the name of the repository where Agama Lab should release the project artifacts. Click Next Project listing page will be shown. All the existing projects for your GitHub user are listed here. Projects can be created, edited, and deleted from the project listing page. Create A New Project # To create a new project, click on the New Project button on the project listing page above. Enter the name and the description for the new project and click the Create button. This will create a new project and it'll be listed on the project listing page. Create The Authentication Flow # Create A Flow File Click on The flow authoring view will open with a blank canvas. To start creating the flow, we need to create a Flow File . To do that, Right-click on code and then select New > Flow File Give name and description for the flow file and then click Create A newly created flow file has one block in it by default. Clicking on the block will allow you to add further blocks using or to edit the existing block using . Create AuthenticationService Call block Click on the block and then . Then select call A new Call block should appear with a link to Start block Click Call block and then click to open the configuration screen. Add configuration values as shown below. This will create a new instance of AuthenticationService class. This instance will be used to authenticate the user. The new instance will be stored in a variable called authService . Create CdiUtil Call block To perform authentication we will also need a bean instance of CdiUtil class. This bean instance takes AuthenticationService instance that we created in the previous step as an argument. Click the New Authentication Service block and then click on . Then click Call Click on the newly created Call block and by clicking open the configuration page. Input values as shown below in the configuration screen Create Assignment(s) block Next, we need to create an empty variable that the flow will use in the future to store authentication results. Click on New CdiUtil Object and then click . Select Assignment(s) Click on the newly created Assign block. Click . Input values as shown below in the configuration screen Create repeat block Repeat block represents the Repeat instruction of Agama DSL. Repeat block creates a loop to iterate over certain steps(blocks). We will create a repeat loop that allows 3 retries if the authentication fails. Click on the Result Object block and then click . Select Repeat . Click on the newly created Repeat block. Click . Input values as shown below in the configuration screen Create An RRF block RRF block represents the RRF instruction of Agama DSL. Click on the Repeat block. Click . Check the In Repeat Block and then click on RRF . Click on the newly created Repeat block. Click . Input values as shown below in the configuration screen Since we have checked the In Repeat Block at the time of adding the RRF block, the RRF block as well as all the blocks that we add to the RRF block iterated blocks. At this stage, let's save the flow. Click Save on the flow canvas. Create a CdiUtil Call block Create a Call block to process the username and password received from the user (in RRF) and validate them. The result of validation should be stored in a variable. Click on the RRF block. Click . Click on Call . Click on the newly created Call block. Click . Input values as shown below in the configuration screen Create An Assignment block In case of authentication failure, we want to show the username to the user while reentering the password on the web page. For this, we will save the username in a variable using the Assignment(s) block. Click on the Call block. Click . Click on Assignment(s) . Click on the newly created Call block. Click . Input values as shown below in the configuration screen Create A Conditional When block When block represents the When instruction of Agama DSL. Create a conditional check using the When block to check if the authentication (validated in validate credentials block) has been successful. Click on Assignment(s) block. Click . Click on When . Click on the newly created When block. Click . Input values as shown below in the configuration screen Create finish blocks The Finish block represents the Flow finish instruction of Agama DSL. If the authentication was successful then the flow should finish and return the username. This will be achieved by adding a Finish block to the When block. And if authentication fails after 3 attempts, we need another Finish block following the Repeat block. Click on the When block. Click . Click on Condition met and then click Finish Click on the newly created Finish block. Click . Input values as shown below in the configuration screen Click on the Repeat block. Click . Click Finish Click on the newly created Finish block. Click . Input values as shown below in the configuration screen and click Save . Save the flow using the Save button on flow canvas. The completed flow looks like below: Check Generated code Agama Lab flow gets translated in Agama DSL . Click the Code button to see the code generated by the flow. Flow co.acme.password Basepath \"\" authService = Call io.jans.as.server.service.AuthenticationService#class cdiUtil = Call io.jans.service.cdi.util.CdiUtil#bean authService authResult = {} Repeat 3 times max creds = RRF \"login.ftlh\" authResult authResult.success = Call cdiUtil authenticate creds.username creds.password authResult.uid = creds.username When authResult.success is true Finish authResult.uid Finish false Design User Interface # In the RRF configuration step, we mentioned login.ftlh to render the login page elements. We need to add login.ftlh to the Agama project so that the flow can use during the flow execution. Use the steps below to create the page. Create a template file On the left project explorer menu, click on web > New > Freemarker Template Select + Create under the New Blank Template Give Name and Description as shown below and click Create Use the visual editor This opens a visual editor to create a freemarker template. Use this visual editor to create a template as per the need. For this article, we will use the code below. Click Edit HTML . This opens a text editor. Remove existing code in the editor and paste the code shown below. <!doctype html> < html xmlns = \"http://www.w3.org/1999/xhtml\" > < head > < title > Jans Agama Basic Auth flow </ title > </ head > < body > < h2 > Welcome </ h2 > < hr /> [#if !(success!true)] < p class = \"fs-6 text-danger mb-3\" > ${msgs[\"login.errorMessage\"]} </ p > [/#if] < hr /> < form method = \"post\" enctype = \"application/x-www-form-urlencoded\" > < div > Username: < input type = \"text\" class = \"form-control\" name = \"username\" id = \"username\" value = \"${uid!}\" required > </ div > < div > Password: < input type = \"password\" class = \"form-control\" id = \"password\" name = \"password\" > </ div > < div > < input type = \"submit\" class = \"btn btn-success px-4\" value = \"Login\" > </ div > </ form > </ body > < style > input { border : 1 px solid #000000 ; } </ style > </ html > Click Save changes This will render the page in the visual editor . Release The Project # To use the flow for authentication in the Janssen Server, the flow needs to be released. Agama Lab releases the flow and the related artifacts (like template) in the form of a .gama file in the GitHub repository. To release the project, click on any of the files in the left project explorer, and click Release Project . Enter a desired version number and click Save Upon successful release, Agama Lab Releases dashboard is shown. It lists all projects that are released. Click on the project name to go to the GitHub repository release page where .gama file has been released Download the .gama file from here to deploy on to the Janssen Server. Deploy Agama Project # Note Please ensure that Agama engine and scripts are enabled in Janssen Server deployment Download the .gama file from the GitHub repository Open TUI using following commands on Janssen Server Command jans tui Navigate to Auth Server > Agama > Upload Project . Select the .gama file to upload. Test # Setup Janssen Tent Change the configuration as given below in config.py ACR_VALUES = \"agama_co.acme.password.flow\" Run the Tent test by accessing it via the browser", "title": "Quick Start Using Agama Lab"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#quick-start-using-agama-lab", "text": "In this quick start guide, we will build, deploy and test a simple password-based authentication flow using Agama and Agama Lab . Agama Lab is an online visual editor to build authentication flows. A flow built on Agama Lab is packaged as a .gama project file. .gama package needs to be manually deployed on Janssen Server where the Agama engine will execute the flow when an authentication request is received. Major Steps involved in this process are: Create Agama project using Agama Lab Deploying .gama package on Janssen Server Testing the authentication flow This guide covers these steps in the following sections.", "title": "Quick Start Using Agama Lab"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#prerequisites", "text": "Janssen Server instance A public GitHub repository with at least one prior commit", "title": "Prerequisites"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#create-agama-project", "text": "We will use Agama Lab to create a simple username-password based user authentication flow. This involves defining the authentication steps, designing the user interface to capture user inputs, and lastly, releasing the flow as an Agama project.", "title": "Create Agama Project"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#defining-the-authentication-flow", "text": "", "title": "Defining The Authentication Flow"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#log-into-agama-lab", "text": "Go to Agama Lab login page. Authenticate on the GitHub authentication page. Input the name of the repository where Agama Lab should release the project artifacts. Click Next Project listing page will be shown. All the existing projects for your GitHub user are listed here. Projects can be created, edited, and deleted from the project listing page.", "title": "Log Into Agama Lab"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#create-a-new-project", "text": "To create a new project, click on the New Project button on the project listing page above. Enter the name and the description for the new project and click the Create button. This will create a new project and it'll be listed on the project listing page.", "title": "Create A New Project"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#create-the-authentication-flow", "text": "Create A Flow File Click on The flow authoring view will open with a blank canvas. To start creating the flow, we need to create a Flow File . To do that, Right-click on code and then select New > Flow File Give name and description for the flow file and then click Create A newly created flow file has one block in it by default. Clicking on the block will allow you to add further blocks using or to edit the existing block using . Create AuthenticationService Call block Click on the block and then . Then select call A new Call block should appear with a link to Start block Click Call block and then click to open the configuration screen. Add configuration values as shown below. This will create a new instance of AuthenticationService class. This instance will be used to authenticate the user. The new instance will be stored in a variable called authService . Create CdiUtil Call block To perform authentication we will also need a bean instance of CdiUtil class. This bean instance takes AuthenticationService instance that we created in the previous step as an argument. Click the New Authentication Service block and then click on . Then click Call Click on the newly created Call block and by clicking open the configuration page. Input values as shown below in the configuration screen Create Assignment(s) block Next, we need to create an empty variable that the flow will use in the future to store authentication results. Click on New CdiUtil Object and then click . Select Assignment(s) Click on the newly created Assign block. Click . Input values as shown below in the configuration screen Create repeat block Repeat block represents the Repeat instruction of Agama DSL. Repeat block creates a loop to iterate over certain steps(blocks). We will create a repeat loop that allows 3 retries if the authentication fails. Click on the Result Object block and then click . Select Repeat . Click on the newly created Repeat block. Click . Input values as shown below in the configuration screen Create An RRF block RRF block represents the RRF instruction of Agama DSL. Click on the Repeat block. Click . Check the In Repeat Block and then click on RRF . Click on the newly created Repeat block. Click . Input values as shown below in the configuration screen Since we have checked the In Repeat Block at the time of adding the RRF block, the RRF block as well as all the blocks that we add to the RRF block iterated blocks. At this stage, let's save the flow. Click Save on the flow canvas. Create a CdiUtil Call block Create a Call block to process the username and password received from the user (in RRF) and validate them. The result of validation should be stored in a variable. Click on the RRF block. Click . Click on Call . Click on the newly created Call block. Click . Input values as shown below in the configuration screen Create An Assignment block In case of authentication failure, we want to show the username to the user while reentering the password on the web page. For this, we will save the username in a variable using the Assignment(s) block. Click on the Call block. Click . Click on Assignment(s) . Click on the newly created Call block. Click . Input values as shown below in the configuration screen Create A Conditional When block When block represents the When instruction of Agama DSL. Create a conditional check using the When block to check if the authentication (validated in validate credentials block) has been successful. Click on Assignment(s) block. Click . Click on When . Click on the newly created When block. Click . Input values as shown below in the configuration screen Create finish blocks The Finish block represents the Flow finish instruction of Agama DSL. If the authentication was successful then the flow should finish and return the username. This will be achieved by adding a Finish block to the When block. And if authentication fails after 3 attempts, we need another Finish block following the Repeat block. Click on the When block. Click . Click on Condition met and then click Finish Click on the newly created Finish block. Click . Input values as shown below in the configuration screen Click on the Repeat block. Click . Click Finish Click on the newly created Finish block. Click . Input values as shown below in the configuration screen and click Save . Save the flow using the Save button on flow canvas. The completed flow looks like below: Check Generated code Agama Lab flow gets translated in Agama DSL . Click the Code button to see the code generated by the flow. Flow co.acme.password Basepath \"\" authService = Call io.jans.as.server.service.AuthenticationService#class cdiUtil = Call io.jans.service.cdi.util.CdiUtil#bean authService authResult = {} Repeat 3 times max creds = RRF \"login.ftlh\" authResult authResult.success = Call cdiUtil authenticate creds.username creds.password authResult.uid = creds.username When authResult.success is true Finish authResult.uid Finish false", "title": "Create The Authentication Flow"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#design-user-interface", "text": "In the RRF configuration step, we mentioned login.ftlh to render the login page elements. We need to add login.ftlh to the Agama project so that the flow can use during the flow execution. Use the steps below to create the page. Create a template file On the left project explorer menu, click on web > New > Freemarker Template Select + Create under the New Blank Template Give Name and Description as shown below and click Create Use the visual editor This opens a visual editor to create a freemarker template. Use this visual editor to create a template as per the need. For this article, we will use the code below. Click Edit HTML . This opens a text editor. Remove existing code in the editor and paste the code shown below. <!doctype html> < html xmlns = \"http://www.w3.org/1999/xhtml\" > < head > < title > Jans Agama Basic Auth flow </ title > </ head > < body > < h2 > Welcome </ h2 > < hr /> [#if !(success!true)] < p class = \"fs-6 text-danger mb-3\" > ${msgs[\"login.errorMessage\"]} </ p > [/#if] < hr /> < form method = \"post\" enctype = \"application/x-www-form-urlencoded\" > < div > Username: < input type = \"text\" class = \"form-control\" name = \"username\" id = \"username\" value = \"${uid!}\" required > </ div > < div > Password: < input type = \"password\" class = \"form-control\" id = \"password\" name = \"password\" > </ div > < div > < input type = \"submit\" class = \"btn btn-success px-4\" value = \"Login\" > </ div > </ form > </ body > < style > input { border : 1 px solid #000000 ; } </ style > </ html > Click Save changes This will render the page in the visual editor .", "title": "Design User Interface"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#release-the-project", "text": "To use the flow for authentication in the Janssen Server, the flow needs to be released. Agama Lab releases the flow and the related artifacts (like template) in the form of a .gama file in the GitHub repository. To release the project, click on any of the files in the left project explorer, and click Release Project . Enter a desired version number and click Save Upon successful release, Agama Lab Releases dashboard is shown. It lists all projects that are released. Click on the project name to go to the GitHub repository release page where .gama file has been released Download the .gama file from here to deploy on to the Janssen Server.", "title": "Release The Project"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#deploy-agama-project", "text": "Note Please ensure that Agama engine and scripts are enabled in Janssen Server deployment Download the .gama file from the GitHub repository Open TUI using following commands on Janssen Server Command jans tui Navigate to Auth Server > Agama > Upload Project . Select the .gama file to upload.", "title": "Deploy Agama Project"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#test", "text": "Setup Janssen Tent Change the configuration as given below in config.py ACR_VALUES = \"agama_co.acme.password.flow\" Run the Tent test by accessing it via the browser", "title": "Test"}, {"location": "janssen-server/developer/customization/custom-client-logs/", "tags": ["administration", "developer", "customization"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Custom client logs"}, {"location": "janssen-server/developer/customization/custom-client-logs/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/developer/customization/custom-client-logs/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/developer/customization/custom-client-logs/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/developer/customization/customize-web-pages/", "tags": ["administration", "developer", "customization", "internationalization", "i18n", "locale", "css", "images", "header", "footer", "template"], "text": "Customization Using Custom Assets # Janssen Server allows customization and extension of current web page designs, images, web templates etc. For example, extending the list of languages supported by Janssen Server or maybe customizing the login page to show the organization's logo and align styling to meet the branding of the organization. All of the above need some amount of custom assets, like custom CSS stylesheets, logo images, etc to be available on the Janssen Server. All these are called Custom Assets . Custom Assets Accepted by Module # Listing of custom asset types that each Janssen Server module accepts: Config-API # Path Asset Type /opt/jans/jetty/jans-config-api/custom/config *.xml /opt/jans/jetty/jans-config-api/custom/i18n *.properties /opt/jans/jetty/jans-config-api/custom/libs *.jar /opt/jans/jetty/jans-config-api/custom/pages *.xhtml /opt/jans/jetty/jans-config-api/custom/static .js, .css, .png, .gif, .jpg, .jpeg Auth-Server # Path Asset Type /opt/jans/jetty/jans-auth/custom/i18n *.properties /opt/jans/jetty/jans-auth/custom/libs *.jars /opt/jans/jetty/jans-auth/custom/pages *.xhtml /opt/jans/jetty/jans-auth/custom/static .js, .css, .png, .gif, .jpg, .jpeg /etc/certs/jans-auth-keys.pkcs12 *.pkcs12 Casa # Path Asset Type /opt/jans/jetty/jans-casa/plugins *.jar /opt/jans/jetty/jans-casa/static .js, .css, .png, .gif, .jpg, .jpeg Agama # Path Asset Type /opt/jans/jetty/jans-auth/agama engine templates /opt/jans/jetty/jans-auth/agama/fl .js, .css, .png, .gif, .jpg, .jpeg /opt/jans/jetty/jans-auth/agama/ftl .ftl, .ftlh /opt/jans/jetty/jans-auth/agama/scripts .java .groovy, .gvy, .gy, *.gsh Fido2 # Path Asset Type /etc/jans/conf/fido2/authenticator_cert .pem, .crt /etc/jans/conf/fido2/mds/cert *.crt /etc/jans/conf/fido2/mds/toc *.jwt /etc/jans/conf/fido2/server_metadata *.json Lock # Path Asset Type /opt/jans/jetty/jans-lock/custom-libs *.jar KeyCloak-link # Path Asset Type /opt/jans/jetty/jans-keycloak-link/custom/libs/ *.jar /var/jans/keycloak-link-snapshots/ *.txt Link # Path Asset Type /opt/jans/jetty/jans-link/custom-libs *.jar /var/jans/link-snapshots/ *.txt Managing Custom Assets # Janssen Server configuration tools like CLI and TUI provide the ability to add, update, and delete custom assets. Refer to the custom assets configuration guide to learn how to manage custom assets. Customizing Web Pages # Janssen Server uses xhtml pages to render the web interface needed in interactive web-flows. For example, password authentication flow. It is possible to override the built-in xhtml pages or to add completely new pages. Customizing Built-in Web Pages # In order to customize built-in web pages, follow the steps below: Create a new xhtml page as a copy of the relevant built-in xhtml page Make changes to the code of the new page according to the need Override the built-in page with the new page To override the built-in page with the new page, add the new page as a custom asset and make sure that the new page has the same name and extension as the built-in page. The Janssen Server will automatically use the custom page instead of the built-in page. For example, the default login web page is rendered using login.xhtml . To override this page, add a new custom login.xhtml . Same can be done for other built-in pages like authorization page , logout page , error page . Adding New Web Pages # If the authentication/authorization flow requires new web pages, the same can be added as custom asset and then can be referenced using a relative path. For instance, if enterOTP.xhtml is your webpage for step 2 of the authentication flow that is being implemented using a custom script, then upload page as a custom asset under the relevant Janssen service and then reference it in the custom script as follows: def getPageForStep(self, configurationAttributes, step): # Used to specify the page you want to return for a given step if (step == 1): return \"/auth/login.xhtml\" if (step == 2) return \"/auth/enterOTP.xhtml\" Reference login pages: # Here you will find several login pages for different authentication methods. Customized resource bundles: # Janssen Server provides language translation support using a set of built-in resource bundles . To override the defaults, the custom .properties files should be uploaded as custom assets . If the file name matches the existing resource bundle, then the custom bundle will override the built-in resource bundle. Examples of file names are: jans-auth_en.properties jans-auth_bg.properties To add translations for a language that is not yet supported, create a new properties file and name it jans-auth_[language_code].properties. Then add it to the Janssen Server as custom asset . Janssen Server will automatically add the support for new language using the new resource bundle. Custom CSS files: # Upload the custom CSS files as custom assets and then reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/stylesheet/theme.css or /jans-auth/ext/resources/stylesheet/theme.css Custom image files: # Upload the custom image files as custom assets and then reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/img/fileName.png or /jans-auth/ext/resources/img/fileName.jpg . Page layout, header, footer (xhtml Template) customization # Templates refer to the common interface layout and style. For example, a banner, logo in the common header, and copyright information in the footer. Upload the custom template template.xhtml file as custom assets .This file will automatically override the built-in default template file .", "title": "Customize Web pages"}, {"location": "janssen-server/developer/customization/customize-web-pages/#customization-using-custom-assets", "text": "Janssen Server allows customization and extension of current web page designs, images, web templates etc. For example, extending the list of languages supported by Janssen Server or maybe customizing the login page to show the organization's logo and align styling to meet the branding of the organization. All of the above need some amount of custom assets, like custom CSS stylesheets, logo images, etc to be available on the Janssen Server. All these are called Custom Assets .", "title": "Customization Using Custom Assets"}, {"location": "janssen-server/developer/customization/customize-web-pages/#custom-assets-accepted-by-module", "text": "Listing of custom asset types that each Janssen Server module accepts:", "title": "Custom Assets Accepted by Module"}, {"location": "janssen-server/developer/customization/customize-web-pages/#config-api", "text": "Path Asset Type /opt/jans/jetty/jans-config-api/custom/config *.xml /opt/jans/jetty/jans-config-api/custom/i18n *.properties /opt/jans/jetty/jans-config-api/custom/libs *.jar /opt/jans/jetty/jans-config-api/custom/pages *.xhtml /opt/jans/jetty/jans-config-api/custom/static .js, .css, .png, .gif, .jpg, .jpeg", "title": "Config-API"}, {"location": "janssen-server/developer/customization/customize-web-pages/#auth-server", "text": "Path Asset Type /opt/jans/jetty/jans-auth/custom/i18n *.properties /opt/jans/jetty/jans-auth/custom/libs *.jars /opt/jans/jetty/jans-auth/custom/pages *.xhtml /opt/jans/jetty/jans-auth/custom/static .js, .css, .png, .gif, .jpg, .jpeg /etc/certs/jans-auth-keys.pkcs12 *.pkcs12", "title": "Auth-Server"}, {"location": "janssen-server/developer/customization/customize-web-pages/#casa", "text": "Path Asset Type /opt/jans/jetty/jans-casa/plugins *.jar /opt/jans/jetty/jans-casa/static .js, .css, .png, .gif, .jpg, .jpeg", "title": "Casa"}, {"location": "janssen-server/developer/customization/customize-web-pages/#agama", "text": "Path Asset Type /opt/jans/jetty/jans-auth/agama engine templates /opt/jans/jetty/jans-auth/agama/fl .js, .css, .png, .gif, .jpg, .jpeg /opt/jans/jetty/jans-auth/agama/ftl .ftl, .ftlh /opt/jans/jetty/jans-auth/agama/scripts .java .groovy, .gvy, .gy, *.gsh", "title": "Agama"}, {"location": "janssen-server/developer/customization/customize-web-pages/#fido2", "text": "Path Asset Type /etc/jans/conf/fido2/authenticator_cert .pem, .crt /etc/jans/conf/fido2/mds/cert *.crt /etc/jans/conf/fido2/mds/toc *.jwt /etc/jans/conf/fido2/server_metadata *.json", "title": "Fido2"}, {"location": "janssen-server/developer/customization/customize-web-pages/#lock", "text": "Path Asset Type /opt/jans/jetty/jans-lock/custom-libs *.jar", "title": "Lock"}, {"location": "janssen-server/developer/customization/customize-web-pages/#keycloak-link", "text": "Path Asset Type /opt/jans/jetty/jans-keycloak-link/custom/libs/ *.jar /var/jans/keycloak-link-snapshots/ *.txt", "title": "KeyCloak-link"}, {"location": "janssen-server/developer/customization/customize-web-pages/#link", "text": "Path Asset Type /opt/jans/jetty/jans-link/custom-libs *.jar /var/jans/link-snapshots/ *.txt", "title": "Link"}, {"location": "janssen-server/developer/customization/customize-web-pages/#managing-custom-assets", "text": "Janssen Server configuration tools like CLI and TUI provide the ability to add, update, and delete custom assets. Refer to the custom assets configuration guide to learn how to manage custom assets.", "title": "Managing Custom Assets"}, {"location": "janssen-server/developer/customization/customize-web-pages/#customizing-web-pages", "text": "Janssen Server uses xhtml pages to render the web interface needed in interactive web-flows. For example, password authentication flow. It is possible to override the built-in xhtml pages or to add completely new pages.", "title": "Customizing Web Pages"}, {"location": "janssen-server/developer/customization/customize-web-pages/#customizing-built-in-web-pages", "text": "In order to customize built-in web pages, follow the steps below: Create a new xhtml page as a copy of the relevant built-in xhtml page Make changes to the code of the new page according to the need Override the built-in page with the new page To override the built-in page with the new page, add the new page as a custom asset and make sure that the new page has the same name and extension as the built-in page. The Janssen Server will automatically use the custom page instead of the built-in page. For example, the default login web page is rendered using login.xhtml . To override this page, add a new custom login.xhtml . Same can be done for other built-in pages like authorization page , logout page , error page .", "title": "Customizing Built-in Web Pages"}, {"location": "janssen-server/developer/customization/customize-web-pages/#adding-new-web-pages", "text": "If the authentication/authorization flow requires new web pages, the same can be added as custom asset and then can be referenced using a relative path. For instance, if enterOTP.xhtml is your webpage for step 2 of the authentication flow that is being implemented using a custom script, then upload page as a custom asset under the relevant Janssen service and then reference it in the custom script as follows: def getPageForStep(self, configurationAttributes, step): # Used to specify the page you want to return for a given step if (step == 1): return \"/auth/login.xhtml\" if (step == 2) return \"/auth/enterOTP.xhtml\"", "title": "Adding New Web Pages"}, {"location": "janssen-server/developer/customization/customize-web-pages/#reference-login-pages", "text": "Here you will find several login pages for different authentication methods.", "title": "Reference login pages:"}, {"location": "janssen-server/developer/customization/customize-web-pages/#customized-resource-bundles", "text": "Janssen Server provides language translation support using a set of built-in resource bundles . To override the defaults, the custom .properties files should be uploaded as custom assets . If the file name matches the existing resource bundle, then the custom bundle will override the built-in resource bundle. Examples of file names are: jans-auth_en.properties jans-auth_bg.properties To add translations for a language that is not yet supported, create a new properties file and name it jans-auth_[language_code].properties. Then add it to the Janssen Server as custom asset . Janssen Server will automatically add the support for new language using the new resource bundle.", "title": "Customized resource bundles:"}, {"location": "janssen-server/developer/customization/customize-web-pages/#custom-css-files", "text": "Upload the custom CSS files as custom assets and then reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/stylesheet/theme.css or /jans-auth/ext/resources/stylesheet/theme.css", "title": "Custom CSS files:"}, {"location": "janssen-server/developer/customization/customize-web-pages/#custom-image-files", "text": "Upload the custom image files as custom assets and then reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/img/fileName.png or /jans-auth/ext/resources/img/fileName.jpg .", "title": "Custom image files:"}, {"location": "janssen-server/developer/customization/customize-web-pages/#page-layout-header-footer-xhtml-template-customization", "text": "Templates refer to the common interface layout and style. For example, a banner, logo in the common header, and copyright information in the footer. Upload the custom template template.xhtml file as custom assets .This file will automatically override the built-in default template file .", "title": "Page layout, header, footer (xhtml Template) customization"}, {"location": "janssen-server/fido/bluetooth-authn/", "tags": ["administration", "fido"], "text": "Troubleshooting notes: # Enable the Bluetooth Device Permissions in Chrome Settings https://support.google.com/accounts/answer/9289445?hl=en&co=GENIE.Platform%3DAndroid", "title": "Bluetooth Authenticator Support"}, {"location": "janssen-server/fido/bluetooth-authn/#troubleshooting-notes", "text": "Enable the Bluetooth Device Permissions in Chrome Settings https://support.google.com/accounts/answer/9289445?hl=en&co=GENIE.Platform%3DAndroid", "title": "Troubleshooting notes:"}, {"location": "janssen-server/fido/config/", "tags": ["administration", "fido2"], "text": "Configuration Parameters of Janssen's FIDO2 server: # Field named Example Description issuer https://my-jans-server.jans.io URL using the https scheme with no query or fragment component. The OP asserts this as its Issuer Identifier baseEndpoint https://my-jans-server/jans-fido2/restv1 Base URL of the FIDO2 server Endpoints webAuthnEndpoint https://FQDN/jans-fido2/restv1/webauthn/configuration Base URL of the FIDO2 Web Authn Server Endpoint which return RP Origins cleanServiceInterval 60 Time interval for the Clean Service in seconds. cleanServiceBatchChunkSize 10000 Each clean up iteration fetches chunk of expired data per base dn and removes it from storage. useLocalCache true Boolean value specifying whether to enable local in-memory cache for attributes, scopes, clients and organization configuration disableJdkLogger true Boolean value specifying whether to enable JDK Loggers loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for FIDO2 server loggingLayout \"text\" or \"json\" Contents of logs as plain text or json format externalLoggerConfiguration Path to external log4j2 logging configuration metricReporterInterval 300 The interval for metric reporter in seconds. metricReporterKeepDataDays 15 The number of days to retain metric reported data in the system metricReporterEnabled true Boolean value specifying whether to enable Metric Reporter fido2Configuration See JSON contents in the below example FIDO2 Configuration Fido2Configuration structure # Field named Example Description authenticatorCertsFolder /etc/jans/conf/fido2/authenticator_cert Authenticators certificates fodler. mdsCertsFolder /etc/jans/conf/fido2/mds/cert MDS TOC root certificates folder. mdsTocsFolder /etc/jans/conf/fido2/mds/toc MDS TOC files folder. serverMetadataFolder /etc/jans/conf/fido2/server_metadata Authenticators metadata in json format. Example: virtual devices. metadataUrlsProvider https://mds3.fido.tools String value to provide source of URLs with external metadata. enabledFidoAlgorithms [\"RS256\",\"ES256\"] rp [{\"id\":\"https://my-jans-server.jans.io\",\"origins\":[\"my-jans-server.jans.io\"]}] Requested party id. debugUserAutoEnrollment false Allow to enroll users on enrollment/authentication requests. (Useful while running tests) unfinishedRequestExpiration 180 Expiration time in seconds for pending enrollment/authentication requests authenticationHistoryExpiration 1296000 Expiration time in seconds for approved authentication requests. disableMetadataService false Boolean value indicating whether the MDS download should be omitted attestationMode \"monitor\" Enum value indicating whether MDS validation should be omitted during attestation assertionOptionsGenerateEndpointEnabled false Boolean value indicating whether the assertion custom endpoint (used especially in passkey) is enabled. Configuring the FIDO2 server: # 1. Read Configuration parameters: # Use the following command to obtain configuration parameters: jans cli --operation-id get-properties-fido2 Response: { \"issuer\": \"https://my.jans.server\", \"baseEndpoint\": \"https://my.jans.server/jans-fido2/restv1\", \"cleanServiceInterval\": 60, \"cleanServiceBatchChunkSize\": 10000, \"useLocalCache\": true, \"disableJdkLogger\": true, \"loggingLevel\": \"DEBUG\", \"loggingLayout\": \"text\", \"metricReporterInterval\": 300, \"metricReporterKeepDataDays\": 15, \"metricReporterEnabled\": true, \"personCustomObjectClassList\": [ \"jansCustomPerson\", \"jansPerson\" ], \"sessionIdPersistInCache\": false, \"fido2Configuration\": { \"authenticatorCertsFolder\": \"/etc/jans/conf/fido2/authenticator_cert\", \"mdsCertsFolder\": \"/etc/jans/conf/fido2/mds/cert\", \"mdsTocsFolder\": \"/etc/jans/conf/fido2/mds/toc\", \"checkU2fAttestations\": false, \"debugUserAutoEnrollment\": false, \"unfinishedRequestExpiration\": 180, \"authenticationHistoryExpiration\": 1296000, \"serverMetadataFolder\": \"/etc/jans/conf/fido2/server_metadata\", \"metadataUrlsProvider\": \"\", \"disableMetadataService\": false, \"attestationMode\": \"monitor\", \"assertionOptionsGenerateEndpointEnabled\":true, \"enabledFidoAlgorithms\": [ \"RS256\", \"ES256\" ], \"rp\": [ { \"id\": \"https://my.jans.server\", \"origins\": [ \"my.jans.server\" ] } ] } } 2. Update configuration parameters: # Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1 B. Use the following command jans cli --operation-id post-config-scripts --data /tmp/config_values.json 3. Change log level of FIDO2 server # Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1. Edit loggingLevel to TRACE or DEBUG or INFO B. Use the following command jans cli --operation-id put-properties-fido --data /tmp/config_values.json 4. Locating FIDO2 configuration in Persistence Layer # While it is not recommended that an administrator directly edits a configuration at the persistence layer, it may be useful information for a developer. 5. WebAuthn Endpoint # A. The WebAuthn Endpoints retrieve the list of RP (Relying Party) Origins configured for FIDO2 authentication. B. Endpoints: https://FQDN/restv1/webauthn/configuration && https://FQDN/.well-known/webauthn MySQL # erDiagram jansAppConf { string doc_id PK \"\" string ou \"jans-fido2\" string jansConfDyn \"json configuration for the app\" }", "title": "Configuration"}, {"location": "janssen-server/fido/config/#configuration-parameters-of-janssens-fido2-server", "text": "Field named Example Description issuer https://my-jans-server.jans.io URL using the https scheme with no query or fragment component. The OP asserts this as its Issuer Identifier baseEndpoint https://my-jans-server/jans-fido2/restv1 Base URL of the FIDO2 server Endpoints webAuthnEndpoint https://FQDN/jans-fido2/restv1/webauthn/configuration Base URL of the FIDO2 Web Authn Server Endpoint which return RP Origins cleanServiceInterval 60 Time interval for the Clean Service in seconds. cleanServiceBatchChunkSize 10000 Each clean up iteration fetches chunk of expired data per base dn and removes it from storage. useLocalCache true Boolean value specifying whether to enable local in-memory cache for attributes, scopes, clients and organization configuration disableJdkLogger true Boolean value specifying whether to enable JDK Loggers loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for FIDO2 server loggingLayout \"text\" or \"json\" Contents of logs as plain text or json format externalLoggerConfiguration Path to external log4j2 logging configuration metricReporterInterval 300 The interval for metric reporter in seconds. metricReporterKeepDataDays 15 The number of days to retain metric reported data in the system metricReporterEnabled true Boolean value specifying whether to enable Metric Reporter fido2Configuration See JSON contents in the below example FIDO2 Configuration", "title": "Configuration Parameters of Janssen's FIDO2 server:"}, {"location": "janssen-server/fido/config/#fido2configuration-structure", "text": "Field named Example Description authenticatorCertsFolder /etc/jans/conf/fido2/authenticator_cert Authenticators certificates fodler. mdsCertsFolder /etc/jans/conf/fido2/mds/cert MDS TOC root certificates folder. mdsTocsFolder /etc/jans/conf/fido2/mds/toc MDS TOC files folder. serverMetadataFolder /etc/jans/conf/fido2/server_metadata Authenticators metadata in json format. Example: virtual devices. metadataUrlsProvider https://mds3.fido.tools String value to provide source of URLs with external metadata. enabledFidoAlgorithms [\"RS256\",\"ES256\"] rp [{\"id\":\"https://my-jans-server.jans.io\",\"origins\":[\"my-jans-server.jans.io\"]}] Requested party id. debugUserAutoEnrollment false Allow to enroll users on enrollment/authentication requests. (Useful while running tests) unfinishedRequestExpiration 180 Expiration time in seconds for pending enrollment/authentication requests authenticationHistoryExpiration 1296000 Expiration time in seconds for approved authentication requests. disableMetadataService false Boolean value indicating whether the MDS download should be omitted attestationMode \"monitor\" Enum value indicating whether MDS validation should be omitted during attestation assertionOptionsGenerateEndpointEnabled false Boolean value indicating whether the assertion custom endpoint (used especially in passkey) is enabled.", "title": "Fido2Configuration structure"}, {"location": "janssen-server/fido/config/#configuring-the-fido2-server", "text": "", "title": "Configuring the FIDO2 server:"}, {"location": "janssen-server/fido/config/#1-read-configuration-parameters", "text": "Use the following command to obtain configuration parameters: jans cli --operation-id get-properties-fido2 Response: { \"issuer\": \"https://my.jans.server\", \"baseEndpoint\": \"https://my.jans.server/jans-fido2/restv1\", \"cleanServiceInterval\": 60, \"cleanServiceBatchChunkSize\": 10000, \"useLocalCache\": true, \"disableJdkLogger\": true, \"loggingLevel\": \"DEBUG\", \"loggingLayout\": \"text\", \"metricReporterInterval\": 300, \"metricReporterKeepDataDays\": 15, \"metricReporterEnabled\": true, \"personCustomObjectClassList\": [ \"jansCustomPerson\", \"jansPerson\" ], \"sessionIdPersistInCache\": false, \"fido2Configuration\": { \"authenticatorCertsFolder\": \"/etc/jans/conf/fido2/authenticator_cert\", \"mdsCertsFolder\": \"/etc/jans/conf/fido2/mds/cert\", \"mdsTocsFolder\": \"/etc/jans/conf/fido2/mds/toc\", \"checkU2fAttestations\": false, \"debugUserAutoEnrollment\": false, \"unfinishedRequestExpiration\": 180, \"authenticationHistoryExpiration\": 1296000, \"serverMetadataFolder\": \"/etc/jans/conf/fido2/server_metadata\", \"metadataUrlsProvider\": \"\", \"disableMetadataService\": false, \"attestationMode\": \"monitor\", \"assertionOptionsGenerateEndpointEnabled\":true, \"enabledFidoAlgorithms\": [ \"RS256\", \"ES256\" ], \"rp\": [ { \"id\": \"https://my.jans.server\", \"origins\": [ \"my.jans.server\" ] } ] } }", "title": "1. Read Configuration parameters:"}, {"location": "janssen-server/fido/config/#2-update-configuration-parameters", "text": "Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1 B. Use the following command jans cli --operation-id post-config-scripts --data /tmp/config_values.json", "title": "2. Update configuration parameters:"}, {"location": "janssen-server/fido/config/#3-change-log-level-of-fido2-server", "text": "Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1. Edit loggingLevel to TRACE or DEBUG or INFO B. Use the following command jans cli --operation-id put-properties-fido --data /tmp/config_values.json", "title": "3. Change log level of FIDO2 server"}, {"location": "janssen-server/fido/config/#4-locating-fido2-configuration-in-persistence-layer", "text": "While it is not recommended that an administrator directly edits a configuration at the persistence layer, it may be useful information for a developer.", "title": "4. Locating FIDO2 configuration in Persistence Layer"}, {"location": "janssen-server/fido/config/#5-webauthn-endpoint", "text": "A. The WebAuthn Endpoints retrieve the list of RP (Relying Party) Origins configured for FIDO2 authentication. B. Endpoints: https://FQDN/restv1/webauthn/configuration && https://FQDN/.well-known/webauthn", "title": "5. WebAuthn Endpoint"}, {"location": "janssen-server/fido/config/#mysql", "text": "erDiagram jansAppConf { string doc_id PK \"\" string ou \"jans-fido2\" string jansConfDyn \"json configuration for the app\" }", "title": "MySQL"}, {"location": "janssen-server/fido/key-mgt/", "tags": ["administration", "fido"], "text": "Attestation types # Basic attestation:", "title": "Key Management/Rotation"}, {"location": "janssen-server/fido/key-mgt/#attestation-types", "text": "Basic attestation:", "title": "Attestation types"}, {"location": "janssen-server/fido/logs/", "tags": ["administration", "fido"], "text": "Log level and Logging Layout Parameters of Janssen's FIDO2 server: # Field named Example Description loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for FIDO2 server loggingLayout \"text\" or \"json\" Contents of logs as plain text or json format 1. Read Configuration parameters: # Use the following command to obtain configuration parameters: jans cli --operation-id get-properties-fido2 Response: { \"issuer\":\"https://.jans.io\", \"baseEndpoint\":\"https://my-jans-server.jans.io/jans-fido2/restv1\", \"cleanServiceInterval\":60, \"cleanServiceBatchChunkSize\":10000, \"useLocalCache\":true, \"disableJdkLogger\":true, \"loggingLevel\":\"INFO\", \"loggingLayout\":\"text\", \"externalLoggerConfiguration\":\"\", \"metricReporterInterval\":300, \"metricReporterKeepDataDays\":15, \"metricReporterEnabled\":true, \"personCustomObjectClassList\":[ \"jansCustomPerson\", \"jansPerson\" ], \"fido2Configuration\":{ \"authenticatorCertsFolder\":\"/etc/jans/conf/fido2/authenticator_cert\", \"mdsCertsFolder\":\"/etc/jans/conf/fido2/mds/cert\", \"mdsTocsFolder\":\"/etc/jans/conf/fido2/mds/toc\", \"serverMetadataFolder\":\"/etc/jans/conf/fido2/server_metadata\", \"enabledFidoAlgorithms\":[ \"RS256\", \"ES256\" ], \"rp\":[ { \"id\":\"https://my-jans-server.jans.io\", \"origins\":[ \"my-jans-server.jans.io\" ] } ], \"debugUserAutoEnrollment\":false, \"unfinishedRequestExpiration\":180, \"authenticationHistoryExpiration\":1296000 } } 2. Update loggingLevel or loggingLayout : # Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1 and - edit loggingLevel to TRACE or DEBUG or INFO - edit loggingLayout to text or json B. Use the following command to update the logging level jans cli --operation-id post-config-scripts --data /tmp/config_values.json C. restart jans-fido2 service fido2 restart or systemctl restart fido2 Location of logs in FIDO2 server: # Logs can be found at /opt/jans/jetty/jans-fido2/logs", "title": "Logs"}, {"location": "janssen-server/fido/logs/#log-level-and-logging-layout-parameters-of-janssens-fido2-server", "text": "Field named Example Description loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for FIDO2 server loggingLayout \"text\" or \"json\" Contents of logs as plain text or json format", "title": "Log level and Logging Layout Parameters of Janssen's FIDO2 server:"}, {"location": "janssen-server/fido/logs/#1-read-configuration-parameters", "text": "Use the following command to obtain configuration parameters: jans cli --operation-id get-properties-fido2 Response: { \"issuer\":\"https://.jans.io\", \"baseEndpoint\":\"https://my-jans-server.jans.io/jans-fido2/restv1\", \"cleanServiceInterval\":60, \"cleanServiceBatchChunkSize\":10000, \"useLocalCache\":true, \"disableJdkLogger\":true, \"loggingLevel\":\"INFO\", \"loggingLayout\":\"text\", \"externalLoggerConfiguration\":\"\", \"metricReporterInterval\":300, \"metricReporterKeepDataDays\":15, \"metricReporterEnabled\":true, \"personCustomObjectClassList\":[ \"jansCustomPerson\", \"jansPerson\" ], \"fido2Configuration\":{ \"authenticatorCertsFolder\":\"/etc/jans/conf/fido2/authenticator_cert\", \"mdsCertsFolder\":\"/etc/jans/conf/fido2/mds/cert\", \"mdsTocsFolder\":\"/etc/jans/conf/fido2/mds/toc\", \"serverMetadataFolder\":\"/etc/jans/conf/fido2/server_metadata\", \"enabledFidoAlgorithms\":[ \"RS256\", \"ES256\" ], \"rp\":[ { \"id\":\"https://my-jans-server.jans.io\", \"origins\":[ \"my-jans-server.jans.io\" ] } ], \"debugUserAutoEnrollment\":false, \"unfinishedRequestExpiration\":180, \"authenticationHistoryExpiration\":1296000 } }", "title": "1. Read Configuration parameters:"}, {"location": "janssen-server/fido/logs/#2-update-logginglevel-or-logginglayout", "text": "Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1 and - edit loggingLevel to TRACE or DEBUG or INFO - edit loggingLayout to text or json B. Use the following command to update the logging level jans cli --operation-id post-config-scripts --data /tmp/config_values.json C. restart jans-fido2 service fido2 restart or systemctl restart fido2", "title": "2. Update loggingLevel or loggingLayout:"}, {"location": "janssen-server/fido/logs/#location-of-logs-in-fido2-server", "text": "Logs can be found at /opt/jans/jetty/jans-fido2/logs", "title": "Location of logs in FIDO2 server:"}, {"location": "janssen-server/fido/monitoring/", "tags": ["administration", "fido"], "text": "Monitoring # FIDO Devices # A FIDO device represents a user credential stored in the Jans Server database that is compliant with the FIDO standard. These devices are used as a second factor in a setting of strong authentication. FIDO devices were superseded by FIDO 2 devices in Jans Server. FIDO2 devices # FIDO2 devices are credentials that adhere to the more current Fido 2.0 initiative (WebAuthn + CTAP). Examples of FIDO2 devices are USB security keys and Super Gluu devices. The SCIM endpoints for FIDO 2 allow application developers to query, update and delete already existing devices. Addition of devices do not take place through the service since this process requires direct end-user interaction, ie. device enrolling. The schema attributes for a device of this kind can be found by hitting the URL https://<jans-server>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:Fido2Device To distinguish between regular FIDO2 and SuperGluu devices, note only SuperGluu entries have the attribute deviceData populated (i.e. not null) Example: Querying Enrolled Devices # Say we are interested in having a list of Super Gluu devices users have enrolled and whose operating system is iOS. We may issue a query like this: curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=deviceData co \"ios\"' -d count=10 https://<jans-server>/jans-scim/restv1/v2/Fido2Devices The response will be like: { \"totalResults\": ..., \"itemsPerPage\": ..., \"startIndex\": 1, \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"Resources\": [ { \"id\": \"...\", \"meta\": {...}, \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:Fido2Device\"], \"userId\": \"...\", ... \"deviceData\": \"{...}\", \"displayName\": ..., }, ... ] }", "title": "Monitoring"}, {"location": "janssen-server/fido/monitoring/#monitoring", "text": "", "title": "Monitoring"}, {"location": "janssen-server/fido/monitoring/#fido-devices", "text": "A FIDO device represents a user credential stored in the Jans Server database that is compliant with the FIDO standard. These devices are used as a second factor in a setting of strong authentication. FIDO devices were superseded by FIDO 2 devices in Jans Server.", "title": "FIDO Devices"}, {"location": "janssen-server/fido/monitoring/#fido2-devices", "text": "FIDO2 devices are credentials that adhere to the more current Fido 2.0 initiative (WebAuthn + CTAP). Examples of FIDO2 devices are USB security keys and Super Gluu devices. The SCIM endpoints for FIDO 2 allow application developers to query, update and delete already existing devices. Addition of devices do not take place through the service since this process requires direct end-user interaction, ie. device enrolling. The schema attributes for a device of this kind can be found by hitting the URL https://<jans-server>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:Fido2Device To distinguish between regular FIDO2 and SuperGluu devices, note only SuperGluu entries have the attribute deviceData populated (i.e. not null)", "title": "FIDO2 devices"}, {"location": "janssen-server/fido/monitoring/#example-querying-enrolled-devices", "text": "Say we are interested in having a list of Super Gluu devices users have enrolled and whose operating system is iOS. We may issue a query like this: curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=deviceData co \"ios\"' -d count=10 https://<jans-server>/jans-scim/restv1/v2/Fido2Devices The response will be like: { \"totalResults\": ..., \"itemsPerPage\": ..., \"startIndex\": 1, \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"Resources\": [ { \"id\": \"...\", \"meta\": {...}, \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:Fido2Device\"], \"userId\": \"...\", ... \"deviceData\": \"{...}\", \"displayName\": ..., }, ... ] }", "title": "Example: Querying Enrolled Devices"}, {"location": "janssen-server/fido/platform-authn/", "tags": ["administration", "fido"], "text": "Apple Anonymous Attestation is first of its kind, providing a service like an Anonymization CA, where the authenticator works with a cloud operated CA owned by its manufacturer to dynamically generate per-credential attestation certificates such that no identification information of the authenticator will be revealed to websites in the attestation statement. Furthermore, among data relevant to the registration ceremony, only the public key of the credential along with a hash of the concatenated authenticator data and client data are sent to the CA for attestation, and the CA will not store any of these. This approach makes the whole attestation process privacy preserving. In addition, this approach avoids the security pitfall of Basic Attestation that the compromising of a single device results in revoking certificates from all devices with the same attestation certificate. https://medium.com/webauthnworks/webauthn-fido2-verifying-apple-anonymous-attestation-5eaff334c849", "title": "Platform Authenticator Support"}, {"location": "janssen-server/fido/usb-authn/", "tags": ["administration", "fido"], "text": "This page will be the landing page for the Janssen Project admin documentation", "title": "USB Authenticator Support"}, {"location": "janssen-server/fido/vendor-metadata/", "tags": ["administration", "fido2", "metadata Service", "attestation"], "text": "Metadata Service: # The metadata service is a centralized, trusted database of FIDO authenticators. It is used by the Relying Party to validate authenticators i.e. attest the genuine-ness of a device. If implemented in organizations like government, federal agencies, banking and healthcare organizations for example) and/or organizations handling sensitive data (media companies, R&D institutions, corporations, etc), this information can help protect organizations against security vulnerabilities. 1. Local metadata service: # Janssen's FIDO server has a configuration parameter called serverMetadataFolder which by default points to a directory location /etc/jans/conf/fido2/server_metadata where the administrator can (obtain from a vendor and ) place authenticator metadata in json format. Example of authenticator metadata: { \"aaguid\": \"83c44309-....-8be444b573cb\", \"metadataStatement\": { \"legalHeader\": \"Submission of this statement and retrieval and use of this statement indicates acceptance of the appropriate agreement located at https://fidoalliance.org/metadata/metadata-legal-terms/.\", \"aaguid\": \"83c44309-....-8be444b573cb\", \"description\": \"Just an example\", \"authenticatorVersion\": 448962, \"protocolFamily\": \"fido2\", \"schema\": 3, \"upv\": [ { \"major\": 1, \"minor\": 0 }, { \"major\": 1, \"minor\": 1 } ], \"authenticationAlgorithms\": [ \"ed25519_eddsa_sha512_raw\", \"secp256r1_ecdsa_sha256_raw\" ], \"publicKeyAlgAndEncodings\": [ \"cose\" ], \"attestationTypes\": [ \"basic_full\" ], \"userVerificationDetails\": [ [ { \"userVerificationMethod\": \"passcode_external\", \"caDesc\": { \"base\": 64, \"minLength\": 4, \"maxRetries\": 8, \"blockSlowdown\": 0 } }, { \"userVerificationMethod\": \"presence_internal\" } ], [ { \"userVerificationMethod\": \"passcode_external\", \"caDesc\": { \"base\": 64, \"minLength\": 4, \"maxRetries\": 8, \"blockSlowdown\": 0 } } ], [ { \"userVerificationMethod\": \"fingerprint_internal\", \"baDesc\": { \"selfAttestedFRR\": 0, \"selfAttestedFAR\": 0, \"maxTemplates\": 5, \"maxRetries\": 5, \"blockSlowdown\": 0 } }, { \"userVerificationMethod\": \"presence_internal\" } ], [ { \"userVerificationMethod\": \"none\" } ], [ { \"userVerificationMethod\": \"fingerprint_internal\", \"baDesc\": { \"selfAttestedFRR\": 0, \"selfAttestedFAR\": 0, \"maxTemplates\": 5, \"maxRetries\": 5, \"blockSlowdown\": 0 } } ], [ { \"userVerificationMethod\": \"presence_internal\" } ] ], \"keyProtection\": [ \"hardware\", \"secure_element\" ], \"matcherProtection\": [ \"on_chip\" ], \"cryptoStrength\": 128, \"attachmentHint\": [ \"external\", \"wired\" ], \"tcDisplay\": [], \"attestationRootCertificates\": [ \"MII....psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==\" ], \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAA....k5+36hF7vXAAAAAElFTkSuQmCC\", \"authenticatorGetInfo\": { \"versions\": [ \"FIDO_2_0\", \"FIDO_2_1_PRE\", \"FIDO_2_1\" ], \"extensions\": [ \"credProtect\", \"hmac-secret\", \"largeBlobKey\", \"credBlob\", \"minPinLength\" ], \"aaguid\": \"83c.....73cb\", \"options\": { \"plat\": false, \"rk\": true, \"clientPin\": true, \"up\": true, \"uv\": false, \"pinUvAuthToken\": true, \"largeBlobs\": true, \"ep\": false, \"bioEnroll\": false, \"userVerificationMgmtPreview\": false, \"authnrCfg\": true, \"credMgmt\": true, \"credentialMgmtPreview\": true, \"setMinPINLength\": true, \"makeCredUvNotRqd\": false, \"alwaysUv\": true }, \"maxMsgSize\": 1200, \"pinUvAuthProtocols\": [ 2, 1 ], \"maxCredentialCountInList\": 8, \"maxCredentialIdLength\": 128, \"transports\": [ \"usb\" ], \"algorithms\": [ { \"type\": \"public-key\", \"alg\": -7 }, { \"type\": \"public-key\", \"alg\": -8 } ], \"maxSerializedLargeBlobArray\": 1024, \"forcePINChange\": false, \"minPINLength\": 4, \"firmwareVersion\": 328965, \"maxCredBlobLength\": 32, \"maxRPIDsForSetMinPINLength\": 1, \"preferredPlatformUvAttempts\": 3, \"uvModality\": 2, \"remainingDiscoverableCredentials\": 25 } }, \"statusReports\": [ { \"status\": \"FIDO_CERTIFIED_L1\", \"effectiveDate\": \"2021-08-06\", \"url\": \"www.yubico.com\", \"certificationDescriptor\": \"An example\", \"certificateNumber\": \"FIDO2.....001\", \"certificationPolicyVersion\": \"1.3\", \"certificationRequirementsVersion\": \"1.4\" }, { \"status\": \"FIDO_CERTIFIED\", \"effectiveDate\": \"2021-08-06\" } ], \"timeOfLastStatusChange\": \"2021-08-16\" } 2. Metadata service for authenticators approved by FIDO Alliance (MDS3) # Metadata entries for trusted authenticators registered with FIDO Alliance can be found on - https://fidoalliance.org/certification/fido-certified-products/ Draw.io reference for image: <?xml version=\"1.0\" encoding=\"UTF-8\"?> <mxfile host=\"app.diagrams.net\" modified=\"2022-11-03T13:17:35.619Z\" agent=\"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.52\" etag=\"MPAHjBuOoBSpVro-BGSI\" version=\"20.5.1\" type=\"google\"><diagram id=\"An1oD0C01MiJfx2t8ul6\" name=\"Page-1\">7Vlbc6M2FP41nrYPyXAx2Hl07HUv052kdWe7fVRAAU0EokLEdn/9noOEsQBnva6ZnZ3ZJ3M+ISG+79yEJ/4y2/0sSZG+FzHlE8+JdxN/NfE8158F8IPIXiOzYKqBRLLY3NQCG/YfNaBj0IrFtLRuVEJwxQobjESe00hZGJFSbO3bngW3n1qQhPaATUR4H/2bxSrV6DxwWvwXypK0ebLrmJGMNDcboExJLLZHkP9u4i+lEEpfZbsl5Uhew4uetz4xetiYpLk6Z0L6cRW7f/0ZB+E2cD9U+8dy+ceNUeeV8Mq88G8kL2/Wv64eEN9Q+Uql2b/aN6SUW5ZxkoN1/yxyZVRz52Cb9ahUdHdyo+7h9cFvqMioknu4xUyY+oYx4zJzY25b/g9Yesx9aEBiNE8OS7e0wIVh5gtY8nssIUGALDhnJI/oDyUY76kiMVGk5ooomuH7wm7yGJ1WVqW2olQMMJqSAi9zoZDVbcoU3RQkQmwLkQVYqjKOLMPlE4leEimqPH6oFGc5NXhM5MsDzGIKqXNuneBcRU47x0mZvMBSaRr0VLoL+iLNg5E0mvY0+l1AGNu6bFpdvn0B3FlHgbCnwGxAgdlYCsx6CvRYpnm8wKQMVsRJWbLI5rWmlOJDnJO5hca9jH0ZjUc8BQPppMEk5USxV/uZQ+SZJzwKVsf9zqbbiORNO0mqFJWMqJl0nL7fXsf1O+soIhOqeuvUSh5e+nJxwy9NgVg6GISPF3KFEQM5L0zw6sdUKSzeC9yjt35msSBmjVshE9zdYZX1Tz0Xsl3kM3E6QnUKHLs6+d655amr/NUCbz4QeJp1fH+LvvDfSjQDN2XNDOjguF6xq+lpxhuxoGPJuSBIOPZYBWw2JBmynD+Vhb6R6wlr/TA9rycbEK5sbQhnSY6JAIiHHsO/R1kYpOyFGchYHOP0e0lhp+SpXgpFL9DJaxKD+0mwwrUqJUqjM5ilkuKFLgWHSospXXcqjPMuNL57eGHfPVxvwD1G8467/+8d8xPe0aSASqVAD2insLU5zyEujmPvOkK5ri3UoXE/Fmo2FMfeWEo1OxqvggI3cv/RDNbGP3WfEjTmanc8uNo31o4pnObeOk5obD0TD3jabqeicTzzkUoGDGGQ19gZddxAuji+RZlpzXX1+1z9+lo9gD/r1Iy7C5uAqddZqJs1Ru4CXHd0D208zfKyt33siv5091XdZN6pHe6lbtI5QfdOxmO7iTdeR7JQiuLxmon8e+9hlzS/W9L8fkkb6kxHaz3c/oeTq/UenabD+QB559vpPuzDnD/UJA4pNR9Nqf7nk6tFLLCiyAvFLUDIOsNNoxNhBD6jeRTZ7amxe+7QX9UkTViJEYzUAXOH1ZsT5fcU0el65x3PG/q4OlTiLvi2Cmb7dVuXlvY/Av/dJw==</diagram></mxfile> Janssen's FIDO2 server - Downloads, verifies and caches metadata BLOBs from the FIDO Metadata Service. Re-downloads the metadata BLOB when it expires. Provides trust root certificates for verifying attestation statements during credential registrations. 3. Skip metadata validation # Metadata validation is recommended but not mandatory as per FIDO2 specifications. In FIDO2 we can disable this validation by setting the attestionMode parameter (default is monitor). It should look something like this: \"fido2Configuration\": { ..., \"attestationMode\": \"disabled\", ... } 4. How Apple does it differently # If you check attStmt and it contains x5c , it is a FULL attestation. FULL basically means that it is a certificate that is chained to the vendor. It's signed by a batch private key whose public key is in a batch certificate that is chained to the Apple attestation root certificate. Usually certificates have an authorityInfoAccess extension that helps locate the root, but Apple chose not to do that. Nevertheless, a quick google give us the needed root certificate https://www.apple.com/certificateauthority/Apple_WebAuthn_Root_CA.pem. This certificate is downloaded to the path /etc/jans/conf/fido2/authenticator_cert . You can see more details of the implementation in this link from https://medium.com/webauthnworks/webauthn-fido2-verifying-apple-anonymous-attestation-5eaff334c849. References: # https://fidoalliance.org/announcing-the-new-streamlined-and-simplified-metadata-service-for-authenticator-vendors-and-customers/", "title": "Vendor Metadata Management"}, {"location": "janssen-server/fido/vendor-metadata/#metadata-service", "text": "The metadata service is a centralized, trusted database of FIDO authenticators. It is used by the Relying Party to validate authenticators i.e. attest the genuine-ness of a device. If implemented in organizations like government, federal agencies, banking and healthcare organizations for example) and/or organizations handling sensitive data (media companies, R&D institutions, corporations, etc), this information can help protect organizations against security vulnerabilities.", "title": "Metadata Service:"}, {"location": "janssen-server/fido/vendor-metadata/#1-local-metadata-service", "text": "Janssen's FIDO server has a configuration parameter called serverMetadataFolder which by default points to a directory location /etc/jans/conf/fido2/server_metadata where the administrator can (obtain from a vendor and ) place authenticator metadata in json format. Example of authenticator metadata: { \"aaguid\": \"83c44309-....-8be444b573cb\", \"metadataStatement\": { \"legalHeader\": \"Submission of this statement and retrieval and use of this statement indicates acceptance of the appropriate agreement located at https://fidoalliance.org/metadata/metadata-legal-terms/.\", \"aaguid\": \"83c44309-....-8be444b573cb\", \"description\": \"Just an example\", \"authenticatorVersion\": 448962, \"protocolFamily\": \"fido2\", \"schema\": 3, \"upv\": [ { \"major\": 1, \"minor\": 0 }, { \"major\": 1, \"minor\": 1 } ], \"authenticationAlgorithms\": [ \"ed25519_eddsa_sha512_raw\", \"secp256r1_ecdsa_sha256_raw\" ], \"publicKeyAlgAndEncodings\": [ \"cose\" ], \"attestationTypes\": [ \"basic_full\" ], \"userVerificationDetails\": [ [ { \"userVerificationMethod\": \"passcode_external\", \"caDesc\": { \"base\": 64, \"minLength\": 4, \"maxRetries\": 8, \"blockSlowdown\": 0 } }, { \"userVerificationMethod\": \"presence_internal\" } ], [ { \"userVerificationMethod\": \"passcode_external\", \"caDesc\": { \"base\": 64, \"minLength\": 4, \"maxRetries\": 8, \"blockSlowdown\": 0 } } ], [ { \"userVerificationMethod\": \"fingerprint_internal\", \"baDesc\": { \"selfAttestedFRR\": 0, \"selfAttestedFAR\": 0, \"maxTemplates\": 5, \"maxRetries\": 5, \"blockSlowdown\": 0 } }, { \"userVerificationMethod\": \"presence_internal\" } ], [ { \"userVerificationMethod\": \"none\" } ], [ { \"userVerificationMethod\": \"fingerprint_internal\", \"baDesc\": { \"selfAttestedFRR\": 0, \"selfAttestedFAR\": 0, \"maxTemplates\": 5, \"maxRetries\": 5, \"blockSlowdown\": 0 } } ], [ { \"userVerificationMethod\": \"presence_internal\" } ] ], \"keyProtection\": [ \"hardware\", \"secure_element\" ], \"matcherProtection\": [ \"on_chip\" ], \"cryptoStrength\": 128, \"attachmentHint\": [ \"external\", \"wired\" ], \"tcDisplay\": [], \"attestationRootCertificates\": [ \"MII....psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==\" ], \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAA....k5+36hF7vXAAAAAElFTkSuQmCC\", \"authenticatorGetInfo\": { \"versions\": [ \"FIDO_2_0\", \"FIDO_2_1_PRE\", \"FIDO_2_1\" ], \"extensions\": [ \"credProtect\", \"hmac-secret\", \"largeBlobKey\", \"credBlob\", \"minPinLength\" ], \"aaguid\": \"83c.....73cb\", \"options\": { \"plat\": false, \"rk\": true, \"clientPin\": true, \"up\": true, \"uv\": false, \"pinUvAuthToken\": true, \"largeBlobs\": true, \"ep\": false, \"bioEnroll\": false, \"userVerificationMgmtPreview\": false, \"authnrCfg\": true, \"credMgmt\": true, \"credentialMgmtPreview\": true, \"setMinPINLength\": true, \"makeCredUvNotRqd\": false, \"alwaysUv\": true }, \"maxMsgSize\": 1200, \"pinUvAuthProtocols\": [ 2, 1 ], \"maxCredentialCountInList\": 8, \"maxCredentialIdLength\": 128, \"transports\": [ \"usb\" ], \"algorithms\": [ { \"type\": \"public-key\", \"alg\": -7 }, { \"type\": \"public-key\", \"alg\": -8 } ], \"maxSerializedLargeBlobArray\": 1024, \"forcePINChange\": false, \"minPINLength\": 4, \"firmwareVersion\": 328965, \"maxCredBlobLength\": 32, \"maxRPIDsForSetMinPINLength\": 1, \"preferredPlatformUvAttempts\": 3, \"uvModality\": 2, \"remainingDiscoverableCredentials\": 25 } }, \"statusReports\": [ { \"status\": \"FIDO_CERTIFIED_L1\", \"effectiveDate\": \"2021-08-06\", \"url\": \"www.yubico.com\", \"certificationDescriptor\": \"An example\", \"certificateNumber\": \"FIDO2.....001\", \"certificationPolicyVersion\": \"1.3\", \"certificationRequirementsVersion\": \"1.4\" }, { \"status\": \"FIDO_CERTIFIED\", \"effectiveDate\": \"2021-08-06\" } ], \"timeOfLastStatusChange\": \"2021-08-16\" }", "title": "1. Local metadata service:"}, {"location": "janssen-server/fido/vendor-metadata/#2-metadata-service-for-authenticators-approved-by-fido-alliance-mds3", "text": "Metadata entries for trusted authenticators registered with FIDO Alliance can be found on - https://fidoalliance.org/certification/fido-certified-products/ Draw.io reference for image: <?xml version=\"1.0\" encoding=\"UTF-8\"?> <mxfile host=\"app.diagrams.net\" modified=\"2022-11-03T13:17:35.619Z\" agent=\"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.52\" etag=\"MPAHjBuOoBSpVro-BGSI\" version=\"20.5.1\" type=\"google\"><diagram id=\"An1oD0C01MiJfx2t8ul6\" name=\"Page-1\">7Vlbc6M2FP41nrYPyXAx2Hl07HUv052kdWe7fVRAAU0EokLEdn/9noOEsQBnva6ZnZ3ZJ3M+ISG+79yEJ/4y2/0sSZG+FzHlE8+JdxN/NfE8158F8IPIXiOzYKqBRLLY3NQCG/YfNaBj0IrFtLRuVEJwxQobjESe00hZGJFSbO3bngW3n1qQhPaATUR4H/2bxSrV6DxwWvwXypK0ebLrmJGMNDcboExJLLZHkP9u4i+lEEpfZbsl5Uhew4uetz4xetiYpLk6Z0L6cRW7f/0ZB+E2cD9U+8dy+ceNUeeV8Mq88G8kL2/Wv64eEN9Q+Uql2b/aN6SUW5ZxkoN1/yxyZVRz52Cb9ahUdHdyo+7h9cFvqMioknu4xUyY+oYx4zJzY25b/g9Yesx9aEBiNE8OS7e0wIVh5gtY8nssIUGALDhnJI/oDyUY76kiMVGk5ooomuH7wm7yGJ1WVqW2olQMMJqSAi9zoZDVbcoU3RQkQmwLkQVYqjKOLMPlE4leEimqPH6oFGc5NXhM5MsDzGIKqXNuneBcRU47x0mZvMBSaRr0VLoL+iLNg5E0mvY0+l1AGNu6bFpdvn0B3FlHgbCnwGxAgdlYCsx6CvRYpnm8wKQMVsRJWbLI5rWmlOJDnJO5hca9jH0ZjUc8BQPppMEk5USxV/uZQ+SZJzwKVsf9zqbbiORNO0mqFJWMqJl0nL7fXsf1O+soIhOqeuvUSh5e+nJxwy9NgVg6GISPF3KFEQM5L0zw6sdUKSzeC9yjt35msSBmjVshE9zdYZX1Tz0Xsl3kM3E6QnUKHLs6+d655amr/NUCbz4QeJp1fH+LvvDfSjQDN2XNDOjguF6xq+lpxhuxoGPJuSBIOPZYBWw2JBmynD+Vhb6R6wlr/TA9rycbEK5sbQhnSY6JAIiHHsO/R1kYpOyFGchYHOP0e0lhp+SpXgpFL9DJaxKD+0mwwrUqJUqjM5ilkuKFLgWHSospXXcqjPMuNL57eGHfPVxvwD1G8467/+8d8xPe0aSASqVAD2insLU5zyEujmPvOkK5ri3UoXE/Fmo2FMfeWEo1OxqvggI3cv/RDNbGP3WfEjTmanc8uNo31o4pnObeOk5obD0TD3jabqeicTzzkUoGDGGQ19gZddxAuji+RZlpzXX1+1z9+lo9gD/r1Iy7C5uAqddZqJs1Ru4CXHd0D208zfKyt33siv5091XdZN6pHe6lbtI5QfdOxmO7iTdeR7JQiuLxmon8e+9hlzS/W9L8fkkb6kxHaz3c/oeTq/UenabD+QB559vpPuzDnD/UJA4pNR9Nqf7nk6tFLLCiyAvFLUDIOsNNoxNhBD6jeRTZ7amxe+7QX9UkTViJEYzUAXOH1ZsT5fcU0el65x3PG/q4OlTiLvi2Cmb7dVuXlvY/Av/dJw==</diagram></mxfile> Janssen's FIDO2 server - Downloads, verifies and caches metadata BLOBs from the FIDO Metadata Service. Re-downloads the metadata BLOB when it expires. Provides trust root certificates for verifying attestation statements during credential registrations.", "title": "2. Metadata service for authenticators approved by FIDO Alliance (MDS3)"}, {"location": "janssen-server/fido/vendor-metadata/#3-skip-metadata-validation", "text": "Metadata validation is recommended but not mandatory as per FIDO2 specifications. In FIDO2 we can disable this validation by setting the attestionMode parameter (default is monitor). It should look something like this: \"fido2Configuration\": { ..., \"attestationMode\": \"disabled\", ... }", "title": "3. Skip metadata validation"}, {"location": "janssen-server/fido/vendor-metadata/#4-how-apple-does-it-differently", "text": "If you check attStmt and it contains x5c , it is a FULL attestation. FULL basically means that it is a certificate that is chained to the vendor. It's signed by a batch private key whose public key is in a batch certificate that is chained to the Apple attestation root certificate. Usually certificates have an authorityInfoAccess extension that helps locate the root, but Apple chose not to do that. Nevertheless, a quick google give us the needed root certificate https://www.apple.com/certificateauthority/Apple_WebAuthn_Root_CA.pem. This certificate is downloaded to the path /etc/jans/conf/fido2/authenticator_cert . You can see more details of the implementation in this link from https://medium.com/webauthnworks/webauthn-fido2-verifying-apple-anonymous-attestation-5eaff334c849.", "title": "4. How Apple does it differently"}, {"location": "janssen-server/fido/vendor-metadata/#references", "text": "https://fidoalliance.org/announcing-the-new-streamlined-and-simplified-metadata-service-for-authenticator-vendors-and-customers/", "title": "References:"}, {"location": "janssen-server/install/install-faq/", "tags": ["administration", "installation", "faq"], "text": "Janssen Server Installation FAQs # After installation, how do I verify that the Janssen Server is up and running? # Health and status of Janssen Server and its various processes can be verified in multiple ways: Use the Janssen Server Health Check endpoint # Janssen Server provides a health check endpoint for Authentication module. It can be invoked from commandline using CURL as below: curl -k https://janssen-host-name/jans-auth/sys/health-check For a healthy server, this option will return output as below: Please wait while retrieving data ... { \"status\": \"running\", \"db_status\": \"online\" } Access .well-known endpoints # Janssen Server exposes .well-known endpoint for openid configuration as per the OpenIDConnect RFC . Successful response from this endpoint is also an indicator of healthy authentication module. From command-line interface, use CURL to access this endpoint. For example: curl https://janssen-host-name/jans-auth/.well-known/openid-configuration This should return JSON response from Janssen Server as per OpenId specification. Sample below: { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://janssen-host-name\", \"userinfo_encryption_enc_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"authorization_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"user_name\", \"formatted\", \"phone_mobile_number\", \"preferred_username\", \"inum\", \"locale\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"FORM_POST\", \"QUERY_JWT\", \"FRAGMENT_JWT\", \"FORM_POST_JWT\", \"QUERY\", \"FRAGMENT\", \"JWT\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/token\", \"response_types_supported\" : [ \"id_token token\", \"id_token\", \"code\", \"code token\", \"id_token code token\", \"id_token code\", \"token\" ], \"acr_mappings\" : {\"alias1\": \"acr1\"}, \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"RESOURCE_OWNER_PASSWORD_CREDENTIALS\", \"CLIENT_CREDENTIALS\", \"OXAUTH_UMA_TICKET\", \"AUTHORIZATION_CODE\", \"DEVICE_CODE\", \"REFRESH_TOKEN\", \"IMPLICIT\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/userinfo\", \"op_tos_uri\" : \"http://www.jans.io/doku.php?id=jans:tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"session_revocation_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/revoke_session\", \"global_token_revocation_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/global-token-revocation\", \"check_session_iframe\" : \"https://janssen-host-name/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"https://jans.io/scim/all-resources.search\", \"address\", \"user_name\", \"clientinfo\", \"openid\", \"https://jans.io/scim/fido2.write\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/fido.read\", \"https://jans.io/scim/users.write\", \"https://jans.io/scim/groups.read\", \"revoke_session\", \"global_token_revocation\", \"https://jans.io/scim/fido.write\", \"https://jans.io/scim/bulk\", \"https://jans.io/scim/users.read\", \"phone\", \"mobile_phone\", \"offline_access\", \"https://jans.io/scim/groups.write\", \"email\", \"https://jans.io/scim/fido2.read\", \"jans_client_api\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], ... ... Check OS Services # Check the OS platform Janssen Services and their status Check Logs # Check logs for errors How can I see status of Janssen OS platform services? # Ubuntu # systemctl list-units --all \"jans*\" Command above should list services along with its current status. UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed. Note Some process listed above may not be available in every installation based on options selected during installation. Where can I find Janssen Server logs? # During installation, Janssen Server produces setup logs under following location: /opt/jans/jans-setup/logs/ Individual modules of the Janssen Server will continue to write their operational logs under respective directory at path below: /opt/jans/jetty/<module-name>/logs/ How do I check the version of Janssen server? # /opt/jans/bin/show_version.py Alternatively, TUI can be used to get this information: Open TUI Navigate to Jans TUI menu item on top menu bar Navigate to Application Versions Hit enter This will show version of each Janssen Server modules: After installation, what's next? # After successful installation of the Janssen Server, start configuring Janssen Server to fulfil your organizational requirements and authentication flows you intend to implement. Use the Text-based UI or command-line interface to configure the Janssen Server. Does the Janssen Server uninstall process remove the data store as well? # No. For all persistence options, the Janssen server uninstall steps ( this for instance) will only remove the Janssen Server software and it'll keep the data store untouched. Removing the data store is at the discretion of the administrator and it is a manual step. If not removed before attempting a reinstall of the Janssen Server, the installer would fail due to the existence of the previous data store.", "title": "FAQ"}, {"location": "janssen-server/install/install-faq/#janssen-server-installation-faqs", "text": "", "title": "Janssen Server Installation FAQs"}, {"location": "janssen-server/install/install-faq/#after-installation-how-do-i-verify-that-the-janssen-server-is-up-and-running", "text": "Health and status of Janssen Server and its various processes can be verified in multiple ways:", "title": "After installation, how do I verify that the Janssen Server is up and running?"}, {"location": "janssen-server/install/install-faq/#use-the-janssen-server-health-check-endpoint", "text": "Janssen Server provides a health check endpoint for Authentication module. It can be invoked from commandline using CURL as below: curl -k https://janssen-host-name/jans-auth/sys/health-check For a healthy server, this option will return output as below: Please wait while retrieving data ... { \"status\": \"running\", \"db_status\": \"online\" }", "title": "Use the Janssen Server Health Check endpoint"}, {"location": "janssen-server/install/install-faq/#access-well-known-endpoints", "text": "Janssen Server exposes .well-known endpoint for openid configuration as per the OpenIDConnect RFC . Successful response from this endpoint is also an indicator of healthy authentication module. From command-line interface, use CURL to access this endpoint. For example: curl https://janssen-host-name/jans-auth/.well-known/openid-configuration This should return JSON response from Janssen Server as per OpenId specification. Sample below: { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://janssen-host-name\", \"userinfo_encryption_enc_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"authorization_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"user_name\", \"formatted\", \"phone_mobile_number\", \"preferred_username\", \"inum\", \"locale\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"FORM_POST\", \"QUERY_JWT\", \"FRAGMENT_JWT\", \"FORM_POST_JWT\", \"QUERY\", \"FRAGMENT\", \"JWT\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/token\", \"response_types_supported\" : [ \"id_token token\", \"id_token\", \"code\", \"code token\", \"id_token code token\", \"id_token code\", \"token\" ], \"acr_mappings\" : {\"alias1\": \"acr1\"}, \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"RESOURCE_OWNER_PASSWORD_CREDENTIALS\", \"CLIENT_CREDENTIALS\", \"OXAUTH_UMA_TICKET\", \"AUTHORIZATION_CODE\", \"DEVICE_CODE\", \"REFRESH_TOKEN\", \"IMPLICIT\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/userinfo\", \"op_tos_uri\" : \"http://www.jans.io/doku.php?id=jans:tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"session_revocation_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/revoke_session\", \"global_token_revocation_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/global-token-revocation\", \"check_session_iframe\" : \"https://janssen-host-name/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"https://jans.io/scim/all-resources.search\", \"address\", \"user_name\", \"clientinfo\", \"openid\", \"https://jans.io/scim/fido2.write\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/fido.read\", \"https://jans.io/scim/users.write\", \"https://jans.io/scim/groups.read\", \"revoke_session\", \"global_token_revocation\", \"https://jans.io/scim/fido.write\", \"https://jans.io/scim/bulk\", \"https://jans.io/scim/users.read\", \"phone\", \"mobile_phone\", \"offline_access\", \"https://jans.io/scim/groups.write\", \"email\", \"https://jans.io/scim/fido2.read\", \"jans_client_api\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], ... ...", "title": "Access .well-known endpoints"}, {"location": "janssen-server/install/install-faq/#check-os-services", "text": "Check the OS platform Janssen Services and their status", "title": "Check OS Services"}, {"location": "janssen-server/install/install-faq/#check-logs", "text": "Check logs for errors", "title": "Check Logs"}, {"location": "janssen-server/install/install-faq/#how-can-i-see-status-of-janssen-os-platform-services", "text": "", "title": "How can I see status of Janssen OS platform services?"}, {"location": "janssen-server/install/install-faq/#ubuntu", "text": "systemctl list-units --all \"jans*\" Command above should list services along with its current status. UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed. Note Some process listed above may not be available in every installation based on options selected during installation.", "title": "Ubuntu"}, {"location": "janssen-server/install/install-faq/#where-can-i-find-janssen-server-logs", "text": "During installation, Janssen Server produces setup logs under following location: /opt/jans/jans-setup/logs/ Individual modules of the Janssen Server will continue to write their operational logs under respective directory at path below: /opt/jans/jetty/<module-name>/logs/", "title": "Where can I find Janssen Server logs?"}, {"location": "janssen-server/install/install-faq/#how-do-i-check-the-version-of-janssen-server", "text": "/opt/jans/bin/show_version.py Alternatively, TUI can be used to get this information: Open TUI Navigate to Jans TUI menu item on top menu bar Navigate to Application Versions Hit enter This will show version of each Janssen Server modules:", "title": "How do I check the version of Janssen server?"}, {"location": "janssen-server/install/install-faq/#after-installation-whats-next", "text": "After successful installation of the Janssen Server, start configuring Janssen Server to fulfil your organizational requirements and authentication flows you intend to implement. Use the Text-based UI or command-line interface to configure the Janssen Server.", "title": "After installation, what's next?"}, {"location": "janssen-server/install/install-faq/#does-the-janssen-server-uninstall-process-remove-the-data-store-as-well", "text": "No. For all persistence options, the Janssen server uninstall steps ( this for instance) will only remove the Janssen Server software and it'll keep the data store untouched. Removing the data store is at the discretion of the administrator and it is a manual step. If not removed before attempting a reinstall of the Janssen Server, the installer would fail due to the existence of the previous data store.", "title": "Does the Janssen Server uninstall process remove the data store as well?"}, {"location": "janssen-server/install/setup/", "tags": ["administration", "installation", "setup"], "text": "Janssen Setup Script # Running Setup # After installation, executing setup.py will launch the SETUP Command Line by default. To run the script, run the following command: python3 /opt/jans/jans-setup/setup.py A warning will pop up if the free disk space is less than the recommended 40 GB. The installer will check that all dependant packages are installed or not, and if missing it will ask to install. When prompted Y/y at the command prompt will install all required packages. The installer will detect which operating system, init type, and Apache version are currently on the server. The setup script will bring up a prompt to provide information for certificates as well as the IP Address and the hostname for the Janssen Authorization Server. Hit Enter to accept the default values. Enter IP Address: Enter hostname: Enter your city or locality: Enter your state or province two letter code: Enter two letter Country Code Enter Organization name: Enter email address for support at your organization: Enter maximum RAM for applications in MB: Enter Password for Admin User: Next, pick a persistence mechanism. Choose from MySQL, PGSql that can be installed locally or remotely. Next, pick which services should be installed for this deployment: bash Install Jans Config API? [Yes] : Install Scim Server? [Yes] : Install Fido2 Server? [Yes] : Install Jans Link Server? [Yes] : Install Gluu Casa? [No] : Finally, review the summary screen that gives an overview of the selections made during the setup process. Note! After setup completed, you will be prompted to remove setup files (directories /opt/dist and /opt/jans/jans-setup ). If you are not going to do any post-setup operations, type yes to remove setup files. If you don't respond in 10 seconds, setup files will be preserved. Avoiding common issues # Avoid setup issues by acknowledging the following: IP Address: Do not use localhost for either the IP address or hostname. Hostname: Make sure to choose the hostname carefully. Changing the hostname after installation is not a simple task. Use a real hostname--this can always be managed via host file entries if adding a DNS entry is too much work for testing. For clustered deployments, use the hostname of the cluster that will be used by applications connecting to Janssen Authorization Server. Warning Use a FQDN (fully qualified domain name) as hostname and refrain from using 127.0.0.1 as IP address or usage of private IP is not supported and not recommended. Script Command Line Options # To check usage of this script run help command python3 /opt/jans/jans-setup/setup.py --help usage: jans_setup.py [-h] [--version] [-c] [-d D] [-f F] [-n] [-N] [-u] [-csx] [-encode-salt ENCODE_SALT] [-remote-rdbm {mysql,pgsql} | -local-rdbm {mysql,pgsql}] [-ip-address IP_ADDRESS] [-host-name HOST_NAME] [-org-name ORG_NAME] [-email EMAIL] [-city CITY] [-state STATE] [-country COUNTRY] [-rdbm-user RDBM_USER] [-rdbm-password RDBM_PASSWORD] [-rdbm-port RDBM_PORT] [-rdbm-db RDBM_DB] [-rdbm-host RDBM_HOST] [--reset-rdbm-db] [--shell] [--dump-config-on-error] [--no-progress] [-admin-password ADMIN_PASSWORD] [-jans-max-mem JANS_MAX_MEM] [-properties-password PROPERTIES_PASSWORD] [-approved-issuer APPROVED_ISSUER] [--force-download] [--download-exit] [-jans-app-version JANS_APP_VERSION] [-jans-build JANS_BUILD] [-setup-branch SETUP_BRANCH] [--disable-config-api-security] [--cli-test-client] [--import-ldif IMPORT_LDIF] [-enable-script ENABLE_SCRIPT] [-disable-script DISABLE_SCRIPT] [-java-version {11,17}] [-stm] [-w] [-t] [-x] [--allow-pre-released-features] [--no-data] [--no-jsauth] [--no-config-api] [--no-scim] [--no-fido2] [--install-jans-ldap-link] [--install-jans-keycloak-link] [--with-casa] [--install-jans-saml] [--install-jans-lock] [--install-opa] [--load-config-api-test] [-config-patch-creds CONFIG_PATCH_CREDS] [-test-client-id TEST_CLIENT_ID] [-test-client-pw TEST_CLIENT_PW] [-test-client-redirect-uri TEST_CLIENT_REDIRECT_URI] [--test-client-trusted] Use this script to configure your Jans Server and to add initial data. If setup.properties is found in this folder, these properties will automatically be used instead of the interactive setup. Below are the optional arguments: Argument Description -h, --help show this help message and exit --version show program's version number and exit -c Use command line instead of TUI -d D Installation directory -f F Specify setup.properties file -n No interactive prompt before install starts. Run with -f -N, --no-httpd No apache httpd server -u Update hosts file with IP address / hostname -csx Collect setup properties, save and exit -remote-rdbm Enables using remote RDBM server -local-rdbm Enables installing/configuring local RDBM server -ip-address IP_ADDRESS Used primarily by Apache httpd for the Listen directive -host-name HOST_NAME Internet-facing FQDN that is used to generate certificates and metadata. -org-name ORG_NAME Organization name field used for generating X.509 certificates -email EMAIL Email address for support at your organization used for generating X.509 certificates -city CITY City field used for generating X.509 certificates -state STATE State field used for generating X.509 certificates -country COUNTRY Two letters country coude used for generating X.509 certificates -rdbm-user RDBM_USER RDBM username -rdbm-password RDBM_PASSWORD RDBM password -rdbm-port RDBM_PORT RDBM port -rdbm-db RDBM_DB RDBM database -rdbm-host RDBM_HOST RDBM host --reset-rdbm-db Deletes all tables on target database. Warning! You will lose all data on target database. --shell Drop into interactive shell before starting installation --dump-config-on-error Dump configuration on error --no-progress Use simple progress -admin-password ADMIN_PASSWORD Used as the Administrator password -jans-max-mem JANS_MAX_MEM Total memory (in KB) to be used by Jannsen Server -properties-password PROPERTIES_PASSWORD Encoded setup.properties file password -approved-issuer APPROVED_ISSUER Api Approved Issuer --force-download Force downloading files --download-exit Download files and exits -jans-app-version JANS_APP_VERSION Version for Jannsen applications -jans-build JANS_BUILD Build version for Janssen applications -setup-branch SETUP_BRANCH Jannsen setup github branch --disable-config-api-security Turn off oauth2 security validation for jans-config-api --cli-test-client Use config api test client for CLI --import-ldif IMPORT_LDIF Render ldif templates from directory and import them in Database -enable-script ENABLE_SCRIPT inum of script to enable -disable-script DISABLE_SCRIPT inum of script to disable -disable-selinux Disable SELinux -stm, --enable-scim-test-mode Enable Scim Test Mode -w Get the development head war files -t Load test data -x Load test data and exit --allow-pre-released-features Enable options to install experimental features, not yet officially supported --no-data Do not import any data to database backend, used for clustering --no-jsauth Do not install OAuth2 Authorization Server --no-config-api Do not install Jans Auth Config Api --no-scim Do not install Scim Server --no-fido2 Do not install Fido2 Server --install-jans-ldap-link Install LDAP Link Server --with-casa Install Gluu/Flex Casa Server --load-config-api-test Load Config Api Test Data --install-cache-refresh Install Cache Refresh Server -config-patch-creds CONFIG_PATCH_CREDS password:username for downloading auto test ciba password -test-client-id TEST_CLIENT_ID ID of test client which has all available scopes. Must be in UUID format. -test-client-pw TEST_CLIENT_PW Secret for test client -test-client-redirect-uri TEST_CLIENT_REDIRECT_URI Redirect URI for test client --test-client-trusted Make test client trusted", "title": "Setup Instructions"}, {"location": "janssen-server/install/setup/#janssen-setup-script", "text": "", "title": "Janssen Setup Script"}, {"location": "janssen-server/install/setup/#running-setup", "text": "After installation, executing setup.py will launch the SETUP Command Line by default. To run the script, run the following command: python3 /opt/jans/jans-setup/setup.py A warning will pop up if the free disk space is less than the recommended 40 GB. The installer will check that all dependant packages are installed or not, and if missing it will ask to install. When prompted Y/y at the command prompt will install all required packages. The installer will detect which operating system, init type, and Apache version are currently on the server. The setup script will bring up a prompt to provide information for certificates as well as the IP Address and the hostname for the Janssen Authorization Server. Hit Enter to accept the default values. Enter IP Address: Enter hostname: Enter your city or locality: Enter your state or province two letter code: Enter two letter Country Code Enter Organization name: Enter email address for support at your organization: Enter maximum RAM for applications in MB: Enter Password for Admin User: Next, pick a persistence mechanism. Choose from MySQL, PGSql that can be installed locally or remotely. Next, pick which services should be installed for this deployment: bash Install Jans Config API? [Yes] : Install Scim Server? [Yes] : Install Fido2 Server? [Yes] : Install Jans Link Server? [Yes] : Install Gluu Casa? [No] : Finally, review the summary screen that gives an overview of the selections made during the setup process. Note! After setup completed, you will be prompted to remove setup files (directories /opt/dist and /opt/jans/jans-setup ). If you are not going to do any post-setup operations, type yes to remove setup files. If you don't respond in 10 seconds, setup files will be preserved.", "title": "Running Setup"}, {"location": "janssen-server/install/setup/#avoiding-common-issues", "text": "Avoid setup issues by acknowledging the following: IP Address: Do not use localhost for either the IP address or hostname. Hostname: Make sure to choose the hostname carefully. Changing the hostname after installation is not a simple task. Use a real hostname--this can always be managed via host file entries if adding a DNS entry is too much work for testing. For clustered deployments, use the hostname of the cluster that will be used by applications connecting to Janssen Authorization Server. Warning Use a FQDN (fully qualified domain name) as hostname and refrain from using 127.0.0.1 as IP address or usage of private IP is not supported and not recommended.", "title": "Avoiding common issues"}, {"location": "janssen-server/install/setup/#script-command-line-options", "text": "To check usage of this script run help command python3 /opt/jans/jans-setup/setup.py --help usage: jans_setup.py [-h] [--version] [-c] [-d D] [-f F] [-n] [-N] [-u] [-csx] [-encode-salt ENCODE_SALT] [-remote-rdbm {mysql,pgsql} | -local-rdbm {mysql,pgsql}] [-ip-address IP_ADDRESS] [-host-name HOST_NAME] [-org-name ORG_NAME] [-email EMAIL] [-city CITY] [-state STATE] [-country COUNTRY] [-rdbm-user RDBM_USER] [-rdbm-password RDBM_PASSWORD] [-rdbm-port RDBM_PORT] [-rdbm-db RDBM_DB] [-rdbm-host RDBM_HOST] [--reset-rdbm-db] [--shell] [--dump-config-on-error] [--no-progress] [-admin-password ADMIN_PASSWORD] [-jans-max-mem JANS_MAX_MEM] [-properties-password PROPERTIES_PASSWORD] [-approved-issuer APPROVED_ISSUER] [--force-download] [--download-exit] [-jans-app-version JANS_APP_VERSION] [-jans-build JANS_BUILD] [-setup-branch SETUP_BRANCH] [--disable-config-api-security] [--cli-test-client] [--import-ldif IMPORT_LDIF] [-enable-script ENABLE_SCRIPT] [-disable-script DISABLE_SCRIPT] [-java-version {11,17}] [-stm] [-w] [-t] [-x] [--allow-pre-released-features] [--no-data] [--no-jsauth] [--no-config-api] [--no-scim] [--no-fido2] [--install-jans-ldap-link] [--install-jans-keycloak-link] [--with-casa] [--install-jans-saml] [--install-jans-lock] [--install-opa] [--load-config-api-test] [-config-patch-creds CONFIG_PATCH_CREDS] [-test-client-id TEST_CLIENT_ID] [-test-client-pw TEST_CLIENT_PW] [-test-client-redirect-uri TEST_CLIENT_REDIRECT_URI] [--test-client-trusted] Use this script to configure your Jans Server and to add initial data. If setup.properties is found in this folder, these properties will automatically be used instead of the interactive setup. Below are the optional arguments: Argument Description -h, --help show this help message and exit --version show program's version number and exit -c Use command line instead of TUI -d D Installation directory -f F Specify setup.properties file -n No interactive prompt before install starts. Run with -f -N, --no-httpd No apache httpd server -u Update hosts file with IP address / hostname -csx Collect setup properties, save and exit -remote-rdbm Enables using remote RDBM server -local-rdbm Enables installing/configuring local RDBM server -ip-address IP_ADDRESS Used primarily by Apache httpd for the Listen directive -host-name HOST_NAME Internet-facing FQDN that is used to generate certificates and metadata. -org-name ORG_NAME Organization name field used for generating X.509 certificates -email EMAIL Email address for support at your organization used for generating X.509 certificates -city CITY City field used for generating X.509 certificates -state STATE State field used for generating X.509 certificates -country COUNTRY Two letters country coude used for generating X.509 certificates -rdbm-user RDBM_USER RDBM username -rdbm-password RDBM_PASSWORD RDBM password -rdbm-port RDBM_PORT RDBM port -rdbm-db RDBM_DB RDBM database -rdbm-host RDBM_HOST RDBM host --reset-rdbm-db Deletes all tables on target database. Warning! You will lose all data on target database. --shell Drop into interactive shell before starting installation --dump-config-on-error Dump configuration on error --no-progress Use simple progress -admin-password ADMIN_PASSWORD Used as the Administrator password -jans-max-mem JANS_MAX_MEM Total memory (in KB) to be used by Jannsen Server -properties-password PROPERTIES_PASSWORD Encoded setup.properties file password -approved-issuer APPROVED_ISSUER Api Approved Issuer --force-download Force downloading files --download-exit Download files and exits -jans-app-version JANS_APP_VERSION Version for Jannsen applications -jans-build JANS_BUILD Build version for Janssen applications -setup-branch SETUP_BRANCH Jannsen setup github branch --disable-config-api-security Turn off oauth2 security validation for jans-config-api --cli-test-client Use config api test client for CLI --import-ldif IMPORT_LDIF Render ldif templates from directory and import them in Database -enable-script ENABLE_SCRIPT inum of script to enable -disable-script DISABLE_SCRIPT inum of script to disable -disable-selinux Disable SELinux -stm, --enable-scim-test-mode Enable Scim Test Mode -w Get the development head war files -t Load test data -x Load test data and exit --allow-pre-released-features Enable options to install experimental features, not yet officially supported --no-data Do not import any data to database backend, used for clustering --no-jsauth Do not install OAuth2 Authorization Server --no-config-api Do not install Jans Auth Config Api --no-scim Do not install Scim Server --no-fido2 Do not install Fido2 Server --install-jans-ldap-link Install LDAP Link Server --with-casa Install Gluu/Flex Casa Server --load-config-api-test Load Config Api Test Data --install-cache-refresh Install Cache Refresh Server -config-patch-creds CONFIG_PATCH_CREDS password:username for downloading auto test ciba password -test-client-id TEST_CLIENT_ID ID of test client which has all available scopes. Must be in UUID format. -test-client-pw TEST_CLIENT_PW Secret for test client -test-client-redirect-uri TEST_CLIENT_REDIRECT_URI Redirect URI for test client --test-client-trusted Make test client trusted", "title": "Script Command Line Options"}, {"location": "janssen-server/install/docker-install/compose/", "tags": ["administration", "installation", "quick-start", "docker compose", "docker image"], "text": "Warning This image is for testing and development purposes only. Use Janssen helm charts for production setups. Overview # Docker monolith image packaging for Janssen. This image packs janssen services including the auth-server, config-api, fido2, and scim. Pre-requisites # Docker Docker compose Environment Variables # Installation depends on the set of environment variables shown below. These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. ENV Description Default CN_HOSTNAME Hostname to install janssen with. demoexample.jans.io CN_ADMIN_PASS Password of the admin user. 1t5Fin3#security CN_ORG_NAME Organization name. Used for ssl cert generation. Janssen CN_EMAIL Email. Used for ssl cert generation. support@jans.io CN_CITY City. Used for ssl cert generation. Austin CN_STATE State. Used for ssl cert generation TX CN_COUNTRY Country. Used for ssl cert generation. US CN_INSTALL_MYSQL Install jans with mysql as the backend false CN_INSTALL_PGSQL Install jans with Postgres as the backend false CN_INSTALL_CONFIG_API Installs the Config API service. true CN_INSTALL_SCIM Installs the SCIM API service. true CN_INSTALL_FIDO2 Installs the FIDO2 API service. true RDBMS_DATABASE RDBMS jans database for MySQL or Postgres. jans RDBMS_USER RDBMS database user for MySQL or Postgres. jans RDBMS_PASSWORD RDBMS database user password for MySQL or Postgres. 1t5Fin3#security RDBMS_HOST RDBMS host for MySQL or Postgres. mysql which is the docker compose service name TEST_CLIENT_ID ID of test client in UUID which has all available scopes to access any jans API 9876baac-de39-4c23-8a78-674b59df8c09 TEST_CLIENT_SECRET Secret for test client 1t5Fin3#security TEST_CLIENT_TRUSTED Trust test client true TEST_CLIENT_REDIRECT_URI Not Implemented yet Redirect URI for test client. Multiple uri's with comma may be provided, if not provided redirect uris will be same as the config-api-client `` How to run # Download the compose file of your chosen persistence from mysql or postgres wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-mysql-compose.yml wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-postgres-compose.yml Download the script files wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/up.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/down.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/clean.sh Give execute permission to the scripts chmod u+x up.sh down.sh clean.sh This docker compose file runs two containers, the janssen monolith container and mysql container. To start the containers. ./up.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. To view the containers running docker compose -f jans-mysql-compose.yml ps To stop the containers. ./down.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. Configure Janssen Server # Access the Docker container shell using: docker compose -f jans-mysql-compose.yml exec jans /bin/bash #This opens a bash terminal in the running container You can grab client_id and client_pw (secret) pairs and other values from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Janssen as needed. For example you can run the TUI : python3 /opt/jans/jans-cli/config-cli-tui.py Access endpoints externally # Add to your /etc/hosts file the ip domain record which should be the ip of the instance docker is installed at and the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record you can hit endpoints such as https://demoexample.jans.io/.well-known/openid-configuration Clean up # Remove setup and volumes ./clean.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "Docker compose"}, {"location": "janssen-server/install/docker-install/compose/#overview", "text": "Docker monolith image packaging for Janssen. This image packs janssen services including the auth-server, config-api, fido2, and scim.", "title": "Overview"}, {"location": "janssen-server/install/docker-install/compose/#pre-requisites", "text": "Docker Docker compose", "title": "Pre-requisites"}, {"location": "janssen-server/install/docker-install/compose/#environment-variables", "text": "Installation depends on the set of environment variables shown below. These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. ENV Description Default CN_HOSTNAME Hostname to install janssen with. demoexample.jans.io CN_ADMIN_PASS Password of the admin user. 1t5Fin3#security CN_ORG_NAME Organization name. Used for ssl cert generation. Janssen CN_EMAIL Email. Used for ssl cert generation. support@jans.io CN_CITY City. Used for ssl cert generation. Austin CN_STATE State. Used for ssl cert generation TX CN_COUNTRY Country. Used for ssl cert generation. US CN_INSTALL_MYSQL Install jans with mysql as the backend false CN_INSTALL_PGSQL Install jans with Postgres as the backend false CN_INSTALL_CONFIG_API Installs the Config API service. true CN_INSTALL_SCIM Installs the SCIM API service. true CN_INSTALL_FIDO2 Installs the FIDO2 API service. true RDBMS_DATABASE RDBMS jans database for MySQL or Postgres. jans RDBMS_USER RDBMS database user for MySQL or Postgres. jans RDBMS_PASSWORD RDBMS database user password for MySQL or Postgres. 1t5Fin3#security RDBMS_HOST RDBMS host for MySQL or Postgres. mysql which is the docker compose service name TEST_CLIENT_ID ID of test client in UUID which has all available scopes to access any jans API 9876baac-de39-4c23-8a78-674b59df8c09 TEST_CLIENT_SECRET Secret for test client 1t5Fin3#security TEST_CLIENT_TRUSTED Trust test client true TEST_CLIENT_REDIRECT_URI Not Implemented yet Redirect URI for test client. Multiple uri's with comma may be provided, if not provided redirect uris will be same as the config-api-client ``", "title": "Environment Variables"}, {"location": "janssen-server/install/docker-install/compose/#how-to-run", "text": "Download the compose file of your chosen persistence from mysql or postgres wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-mysql-compose.yml wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-postgres-compose.yml Download the script files wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/up.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/down.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/clean.sh Give execute permission to the scripts chmod u+x up.sh down.sh clean.sh This docker compose file runs two containers, the janssen monolith container and mysql container. To start the containers. ./up.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. To view the containers running docker compose -f jans-mysql-compose.yml ps To stop the containers. ./down.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "How to run"}, {"location": "janssen-server/install/docker-install/compose/#configure-janssen-server", "text": "Access the Docker container shell using: docker compose -f jans-mysql-compose.yml exec jans /bin/bash #This opens a bash terminal in the running container You can grab client_id and client_pw (secret) pairs and other values from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Janssen as needed. For example you can run the TUI : python3 /opt/jans/jans-cli/config-cli-tui.py", "title": "Configure Janssen Server"}, {"location": "janssen-server/install/docker-install/compose/#access-endpoints-externally", "text": "Add to your /etc/hosts file the ip domain record which should be the ip of the instance docker is installed at and the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record you can hit endpoints such as https://demoexample.jans.io/.well-known/openid-configuration", "title": "Access endpoints externally"}, {"location": "janssen-server/install/docker-install/compose/#clean-up", "text": "Remove setup and volumes ./clean.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "Clean up"}, {"location": "janssen-server/install/docker-install/quick-start/", "tags": ["administration", "installation", "quick-start", "docker"], "text": "Warning This image is for testing and development purposes only. Use Janssen helm charts for production setups. Overview # The quickest way to get a Janssen Server up and running is to install a Docker container-based fully featured Janssen Server. System Requirements # System should meet minimum VM system requirements Install # Installation depends on a set of environment variables . These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. Run this command to start the installation: wget https://raw.githubusercontent.com/JanssenProject/jans/nightly/automation/startjanssenmonolithdemo.sh && chmod u+x startjanssenmonolithdemo.sh && sudo bash startjanssenmonolithdemo.sh demoexample.jans.io MYSQL \"\" main Console messages like below confirms the successful installation: [+] Running 3/3 \u283f Network docker-jans-monolith_cloud_bridge Created 0.0s \u283f Container docker-jans-monolith-mysql-1 Started 0.6s \u283f Container docker-jans-monolith-jans-1 Started 0.9s Waiting for the Janssen server to come up. Depending on the resources it may take 3-5 mins for the services to be up. Testing openid-configuration endpoint.. As can be seen, the install script also accesses the well-known endpoints to varify that Janssen Server is responsive. Verify Installation By Accessing Standard Endpoints # To access Janssen Server standard endpoints from outside of the Docker container, systems /etc/hosts file needs to be updated. Open the file and add the IP domain record which should be the IP of the instance docker is installed. And the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record, hit the standard endpoints such as https://demoexample.jans.io/.well-known/openid-configuration Configure Janssen Server # Access the Docker container shell using: docker exec -ti docker-jans-monolith-jans-1 bash Grab a pair of client_id and client_pw(secret) from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Janssen Server as needed. For example you can run the TUI : jans tui Uninstall / Remove the Janssen Server # This docker based installation uses docker compose under the hood to create containers. Hence uninstalling Janssen server involves invoking docker compose with appropriate yml file. Run command below to stop and remove containers. docker compose -f /tmp/jans/docker-jans-monolith/jans-mysql-compose.yml down && rm -rf jans-* Console messages like below confirms the successful removal: [+] Running 3/3 \u283f Container docker-jans-monolith-jans-1 Removed 10.5s \u283f Container docker-jans-monolith-mysql-1 Removed 0.9s \u283f Network docker-jans-monolith_cloud_bridge Removed 0.1s", "title": "Quick Start"}, {"location": "janssen-server/install/docker-install/quick-start/#overview", "text": "The quickest way to get a Janssen Server up and running is to install a Docker container-based fully featured Janssen Server.", "title": "Overview"}, {"location": "janssen-server/install/docker-install/quick-start/#system-requirements", "text": "System should meet minimum VM system requirements", "title": "System Requirements"}, {"location": "janssen-server/install/docker-install/quick-start/#install", "text": "Installation depends on a set of environment variables . These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. Run this command to start the installation: wget https://raw.githubusercontent.com/JanssenProject/jans/nightly/automation/startjanssenmonolithdemo.sh && chmod u+x startjanssenmonolithdemo.sh && sudo bash startjanssenmonolithdemo.sh demoexample.jans.io MYSQL \"\" main Console messages like below confirms the successful installation: [+] Running 3/3 \u283f Network docker-jans-monolith_cloud_bridge Created 0.0s \u283f Container docker-jans-monolith-mysql-1 Started 0.6s \u283f Container docker-jans-monolith-jans-1 Started 0.9s Waiting for the Janssen server to come up. Depending on the resources it may take 3-5 mins for the services to be up. Testing openid-configuration endpoint.. As can be seen, the install script also accesses the well-known endpoints to varify that Janssen Server is responsive.", "title": "Install"}, {"location": "janssen-server/install/docker-install/quick-start/#verify-installation-by-accessing-standard-endpoints", "text": "To access Janssen Server standard endpoints from outside of the Docker container, systems /etc/hosts file needs to be updated. Open the file and add the IP domain record which should be the IP of the instance docker is installed. And the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record, hit the standard endpoints such as https://demoexample.jans.io/.well-known/openid-configuration", "title": "Verify Installation By Accessing Standard Endpoints"}, {"location": "janssen-server/install/docker-install/quick-start/#configure-janssen-server", "text": "Access the Docker container shell using: docker exec -ti docker-jans-monolith-jans-1 bash Grab a pair of client_id and client_pw(secret) from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Janssen Server as needed. For example you can run the TUI : jans tui", "title": "Configure Janssen Server"}, {"location": "janssen-server/install/docker-install/quick-start/#uninstall-remove-the-janssen-server", "text": "This docker based installation uses docker compose under the hood to create containers. Hence uninstalling Janssen server involves invoking docker compose with appropriate yml file. Run command below to stop and remove containers. docker compose -f /tmp/jans/docker-jans-monolith/jans-mysql-compose.yml down && rm -rf jans-* Console messages like below confirms the successful removal: [+] Running 3/3 \u283f Container docker-jans-monolith-jans-1 Removed 10.5s \u283f Container docker-jans-monolith-mysql-1 Removed 0.9s \u283f Network docker-jans-monolith_cloud_bridge Removed 0.1s", "title": "Uninstall / Remove the Janssen Server"}, {"location": "janssen-server/install/helm-install/amazon-eks/", "tags": ["administration", "installation", "helm", "EKS", "Amazon Web Services", "AWS"], "text": "Install Janssen on EKS # System Requirements # The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0 Initial Setup # Install aws cli Configure your AWS user account using aws configure command. This makes you able to authenticate before creating the cluster. Note that this user account must have permissions to work with Amazon EKS IAM roles and service linked roles, AWS CloudFormation, and a VPC and related resources Install kubectl Install eksctl Create cluster using eksctl such as the following example: eksctl create cluster --name janssen-cluster --nodegroup-name jans-nodes --node-type NODE_TYPE --nodes 2 --managed --region REGION_CODE You can adjust node-type and nodes number as per your desired cluster size To be able to attach volumes to your pod, you need to install the Amazon EBS CSI driver Install Helm3 Create jans namespace where our resources will reside kubectl create namespace jans Jans Installation using Helm # Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer address: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].hostname}' Add the following yaml snippet to your override.yaml file: global : isFqdnRegistered : false config : configmap : lbAddr : http:// #Add LB address from previous command FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : lbAddr : http:// #Add LB address from previous command nginx : ingress : enabled : true path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Amazon RDS For testing purposes, you can deploy it on the EKS cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Amazon RDS For testing purposes, you can deploy it on the EKS cluster using the following commands: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : lbAddr : http:// #Add LB address from previous command cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml Configure Janssen # You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Amazon EKS"}, {"location": "janssen-server/install/helm-install/amazon-eks/#install-janssen-on-eks", "text": "", "title": "Install Janssen on EKS"}, {"location": "janssen-server/install/helm-install/amazon-eks/#system-requirements", "text": "The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0", "title": "System Requirements"}, {"location": "janssen-server/install/helm-install/amazon-eks/#initial-setup", "text": "Install aws cli Configure your AWS user account using aws configure command. This makes you able to authenticate before creating the cluster. Note that this user account must have permissions to work with Amazon EKS IAM roles and service linked roles, AWS CloudFormation, and a VPC and related resources Install kubectl Install eksctl Create cluster using eksctl such as the following example: eksctl create cluster --name janssen-cluster --nodegroup-name jans-nodes --node-type NODE_TYPE --nodes 2 --managed --region REGION_CODE You can adjust node-type and nodes number as per your desired cluster size To be able to attach volumes to your pod, you need to install the Amazon EBS CSI driver Install Helm3 Create jans namespace where our resources will reside kubectl create namespace jans", "title": "Initial Setup"}, {"location": "janssen-server/install/helm-install/amazon-eks/#jans-installation-using-helm", "text": "Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer address: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].hostname}' Add the following yaml snippet to your override.yaml file: global : isFqdnRegistered : false config : configmap : lbAddr : http:// #Add LB address from previous command FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : lbAddr : http:// #Add LB address from previous command nginx : ingress : enabled : true path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Amazon RDS For testing purposes, you can deploy it on the EKS cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Amazon RDS For testing purposes, you can deploy it on the EKS cluster using the following commands: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : lbAddr : http:// #Add LB address from previous command cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml", "title": "Jans Installation using Helm"}, {"location": "janssen-server/install/helm-install/amazon-eks/#configure-janssen", "text": "You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Configure Janssen"}, {"location": "janssen-server/install/helm-install/google-gke/", "tags": ["administration", "installation", "helm", "GKE", "Google Cloud", "GCP"], "text": "Install Janssen on GKE # System Requirements # The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0 Initial Setup # Enable GKE API if not enabled yet. If you are using Cloud Shell , you can skip to step 6. Install gcloud . Install kubectl using gcloud components install kubectl command. Install Helm3 . Create cluster using a command such as the following example: gcloud container clusters create janssen-cluster --num-nodes 2 --machine-type e2-standard-4 --zone us-west1-a You can adjust num-nodes and machine-type as per your desired cluster size Create jans namespace where our resources will reside kubectl create namespace jans Jans Installation using Helm # Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer IP: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].ip}' Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the Loadbalance IP from the previous command isFqdnRegistered : false FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the LoadBalancer IP from the previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Cloud SQL For testing purposes, you can deploy it on the GKE cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Cloud SQL For testing purposes, you can deploy it on the GKE cluster using the following command: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql lbIp : \"\" #Add the LoadBalancer IP from previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml Configure Janssen # You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Google GKE"}, {"location": "janssen-server/install/helm-install/google-gke/#install-janssen-on-gke", "text": "", "title": "Install Janssen on GKE"}, {"location": "janssen-server/install/helm-install/google-gke/#system-requirements", "text": "The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0", "title": "System Requirements"}, {"location": "janssen-server/install/helm-install/google-gke/#initial-setup", "text": "Enable GKE API if not enabled yet. If you are using Cloud Shell , you can skip to step 6. Install gcloud . Install kubectl using gcloud components install kubectl command. Install Helm3 . Create cluster using a command such as the following example: gcloud container clusters create janssen-cluster --num-nodes 2 --machine-type e2-standard-4 --zone us-west1-a You can adjust num-nodes and machine-type as per your desired cluster size Create jans namespace where our resources will reside kubectl create namespace jans", "title": "Initial Setup"}, {"location": "janssen-server/install/helm-install/google-gke/#jans-installation-using-helm", "text": "Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer IP: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].ip}' Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the Loadbalance IP from the previous command isFqdnRegistered : false FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the LoadBalancer IP from the previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Cloud SQL For testing purposes, you can deploy it on the GKE cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Cloud SQL For testing purposes, you can deploy it on the GKE cluster using the following command: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql lbIp : \"\" #Add the LoadBalancer IP from previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml", "title": "Jans Installation using Helm"}, {"location": "janssen-server/install/helm-install/google-gke/#configure-janssen", "text": "You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Configure Janssen"}, {"location": "janssen-server/install/helm-install/local/", "tags": ["administration", "installation", "helm"], "text": "Install Janssen Server Locally with minikube and MicroK8s # System Requirements # For local deployments like minikube and MicroK8s or cloud installations in demo mode, resources may be set to the minimum as below: 8 GB RAM 4 CPU cores 50 GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may increase or decrease. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0 Installation Steps # Start a fresh Ubuntu 18.04 / 20.04 / 22.04 VM with ports 443 and 80 open. Then execute the following: sudo su - wget https://raw.githubusercontent.com/JanssenProject/jans/nightly/automation/startjanssendemo.sh && chmod u+x startjanssendemo.sh && ./startjanssendemo.sh This will install Docker, Microk8s, Helm and Janssen with the default settings that can be found inside values.yaml . The installer will automatically add a record to your hosts record in the VM but if you want to access the endpoints outside the VM you must map the ip of the instance running Ubuntu to the FQDN you provided and then access the endpoints at your browser such in the example in the table below. Service Example endpoint Auth server https://FQDN/.well-known/openid-configuration fido2 https://FQDN/.well-known/fido2-configuration scim https://FQDN/.well-known/scim-configuration Configure Janssen # You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Local Kubernetes Cluster"}, {"location": "janssen-server/install/helm-install/local/#install-janssen-server-locally-with-minikube-and-microk8s", "text": "", "title": "Install Janssen Server Locally with minikube and MicroK8s"}, {"location": "janssen-server/install/helm-install/local/#system-requirements", "text": "For local deployments like minikube and MicroK8s or cloud installations in demo mode, resources may be set to the minimum as below: 8 GB RAM 4 CPU cores 50 GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may increase or decrease. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0", "title": "System Requirements"}, {"location": "janssen-server/install/helm-install/local/#installation-steps", "text": "Start a fresh Ubuntu 18.04 / 20.04 / 22.04 VM with ports 443 and 80 open. Then execute the following: sudo su - wget https://raw.githubusercontent.com/JanssenProject/jans/nightly/automation/startjanssendemo.sh && chmod u+x startjanssendemo.sh && ./startjanssendemo.sh This will install Docker, Microk8s, Helm and Janssen with the default settings that can be found inside values.yaml . The installer will automatically add a record to your hosts record in the VM but if you want to access the endpoints outside the VM you must map the ip of the instance running Ubuntu to the FQDN you provided and then access the endpoints at your browser such in the example in the table below. Service Example endpoint Auth server https://FQDN/.well-known/openid-configuration fido2 https://FQDN/.well-known/fido2-configuration scim https://FQDN/.well-known/scim-configuration", "title": "Installation Steps"}, {"location": "janssen-server/install/helm-install/local/#configure-janssen", "text": "You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Configure Janssen"}, {"location": "janssen-server/install/helm-install/microsoft-azure/", "tags": ["administration", "installation", "helm", "AKS", "Microsoft", "Azure"], "text": "Install Janssen on AKS # System Requirements # The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0 Initial Setup # Install Azure CLI Create a Resource Group az group create --name janssen-resource-group --location eastus Create an AKS cluster such as the following example: az aks create -g janssen-resource-group -n janssen-cluster --enable-managed-identity --node-vm-size NODE_TYPE --node-count 2 --enable-addons monitoring --enable-msi-auth-for-monitoring --generate-ssh-keys You can adjust node-count and node-vm-size as per your desired cluster size Connect to the cluster az aks install-cli az aks get-credentials --resource-group janssen-resource-group --name janssen-cluster Install Helm3 Create jans namespace where our resources will reside kubectl create namespace jans Jans Installation using Helm # Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer IP: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].ip}' Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the Loadbalance IP from the previous command isFqdnRegistered : false FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the LoadBalancer IP from the previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Azure Database for PostgreSQL For testing purposes, you can deploy it on the AKS cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Azure Database for MySQL For testing purposes, you can deploy it on the AKS cluster using the following command: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql lbIp : \"\" #Add the LoadBalancer IP from previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml Configure Janssen # You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Microsoft Azure AKS"}, {"location": "janssen-server/install/helm-install/microsoft-azure/#install-janssen-on-aks", "text": "", "title": "Install Janssen on AKS"}, {"location": "janssen-server/install/helm-install/microsoft-azure/#system-requirements", "text": "The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0", "title": "System Requirements"}, {"location": "janssen-server/install/helm-install/microsoft-azure/#initial-setup", "text": "Install Azure CLI Create a Resource Group az group create --name janssen-resource-group --location eastus Create an AKS cluster such as the following example: az aks create -g janssen-resource-group -n janssen-cluster --enable-managed-identity --node-vm-size NODE_TYPE --node-count 2 --enable-addons monitoring --enable-msi-auth-for-monitoring --generate-ssh-keys You can adjust node-count and node-vm-size as per your desired cluster size Connect to the cluster az aks install-cli az aks get-credentials --resource-group janssen-resource-group --name janssen-cluster Install Helm3 Create jans namespace where our resources will reside kubectl create namespace jans", "title": "Initial Setup"}, {"location": "janssen-server/install/helm-install/microsoft-azure/#jans-installation-using-helm", "text": "Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer IP: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].ip}' Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the Loadbalance IP from the previous command isFqdnRegistered : false FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the LoadBalancer IP from the previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Azure Database for PostgreSQL For testing purposes, you can deploy it on the AKS cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Azure Database for MySQL For testing purposes, you can deploy it on the AKS cluster using the following command: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql lbIp : \"\" #Add the LoadBalancer IP from previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml", "title": "Jans Installation using Helm"}, {"location": "janssen-server/install/helm-install/microsoft-azure/#configure-janssen", "text": "You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Configure Janssen"}, {"location": "janssen-server/install/helm-install/rancher/", "tags": ["administration", "installation", "helm", "rancher"], "text": "Install Janssen Server Using Rancher Marketplace # For this quick start we will use a single node Kubernetes install in docker with a self-signed certificate . Note For a more generic setup, use Rancher UI to deploy the setup. For more options please follow this link . Installation Steps # Note If you are deploying an Ingress controller on a single node deployment, in which Ingress utilizes ports 80 and 443, then you have to adjust the host ports mapped for the rancher/rancher container. Here's an example on how to do that. Provision a Linux 4 CPU, 16 GB RAM, and 50GB SSD VM with ports 443 and 80 open. Save the VM IP address. For development environments, the VM can be set up using VMWare Workstation Player or VirtualBox with an Ubuntu 20.04 operating system running on a VM. Install Docker . Execute docker run -d --restart = unless-stopped -p 80 :80 -p 443 :443 --privileged rancher/rancher:latest The final line of the returned text is the container-id , which you'll need for the next step. Execute the following command to get the bootstrap password for login. docker logs <container-id> 2 > & 1 | grep \"Bootstrap Password:\" Head to https://<VM-IP-ADDRESS-FROM-FIRST-STEP> and log in with the username admin and the password from the previous step. If you are logging into Rancher for the first time, you'll need to enter just the password, and on the next step, Rancher will ask you to reset your current password. Next, you'll see the Rancher home page with a list of existing clusters. By default, the name of the newly created cluster would be local . Click on the cluster name to go to the dashboard. Add Janssen repository: From the top-left menu expand Apps > Repositories > Create > Add a repo name and the Index URL https://docs.jans.io/charts > Create From the top-left menu expand Apps and click Charts . Search for Janssen and begin your installation. During Step 1 of installation, be sure to select the Customize Helm options before install option. In Step 2, customize the settings for the Janssen installation. In Step 3, unselect the Wait option and start the installation.", "title": "Using Rancher Marketplace"}, {"location": "janssen-server/install/helm-install/rancher/#install-janssen-server-using-rancher-marketplace", "text": "For this quick start we will use a single node Kubernetes install in docker with a self-signed certificate . Note For a more generic setup, use Rancher UI to deploy the setup. For more options please follow this link .", "title": "Install Janssen Server Using Rancher Marketplace"}, {"location": "janssen-server/install/helm-install/rancher/#installation-steps", "text": "Note If you are deploying an Ingress controller on a single node deployment, in which Ingress utilizes ports 80 and 443, then you have to adjust the host ports mapped for the rancher/rancher container. Here's an example on how to do that. Provision a Linux 4 CPU, 16 GB RAM, and 50GB SSD VM with ports 443 and 80 open. Save the VM IP address. For development environments, the VM can be set up using VMWare Workstation Player or VirtualBox with an Ubuntu 20.04 operating system running on a VM. Install Docker . Execute docker run -d --restart = unless-stopped -p 80 :80 -p 443 :443 --privileged rancher/rancher:latest The final line of the returned text is the container-id , which you'll need for the next step. Execute the following command to get the bootstrap password for login. docker logs <container-id> 2 > & 1 | grep \"Bootstrap Password:\" Head to https://<VM-IP-ADDRESS-FROM-FIRST-STEP> and log in with the username admin and the password from the previous step. If you are logging into Rancher for the first time, you'll need to enter just the password, and on the next step, Rancher will ask you to reset your current password. Next, you'll see the Rancher home page with a list of existing clusters. By default, the name of the newly created cluster would be local . Click on the cluster name to go to the dashboard. Add Janssen repository: From the top-left menu expand Apps > Repositories > Create > Add a repo name and the Index URL https://docs.jans.io/charts > Create From the top-left menu expand Apps and click Charts . Search for Janssen and begin your installation. During Step 1 of installation, be sure to select the Customize Helm options before install option. In Step 2, customize the settings for the Janssen installation. In Step 3, unselect the Wait option and start the installation.", "title": "Installation Steps"}, {"location": "janssen-server/install/vm-install/dynamic-download/", "tags": ["administration", "installation", "vm", "dynamic"], "text": "Install Janssen Server using Dynamic Download # The dynamic download installs the latest development version of the Janssen Server. Note This method of installation is suitable only for testing, development, or feature exploration purposes. Not for production deployments. System Requirements # System should meet minimum VM system requirements Prerequisites # curl should be installed Install # Download the installer curl https://raw.githubusercontent.com/JanssenProject/jans/nightly/jans-linux-setup/jans_setup/install.py > install.py Execute Installer To execute installer, run the command below: python3 install.py The installer can be invoked using various options to tailor the installation process. Invoke the commands below to know about all the available options. python3 install.py --help One particularly useful option for development environments is the one below which installs the Janssen Server with test data loaded. python3 install.py --args=\"-t\" Installer can be run with all the arguments provided via command-line at the time of invocking the install script. This enables prompt-less installation. For example, see the command below: python3 install.py --args = \"-n -ip-address 10.229.38.28 -host-name jans-opensuse -city ah -state gj -country in -org-name gluu -email dhaval@gluu.org -jans-max-mem 26349 -admin-password admin --with-casa --install-jans-keycloak-link -t\" Uninstall # Use the command below to uninstall the Janssen Server Note For removal of the attached persistence store, please refer to this note . python3 install.py -uninstall", "title": "Dynamic Download"}, {"location": "janssen-server/install/vm-install/dynamic-download/#install-janssen-server-using-dynamic-download", "text": "The dynamic download installs the latest development version of the Janssen Server. Note This method of installation is suitable only for testing, development, or feature exploration purposes. Not for production deployments.", "title": "Install Janssen Server using Dynamic Download"}, {"location": "janssen-server/install/vm-install/dynamic-download/#system-requirements", "text": "System should meet minimum VM system requirements", "title": "System Requirements"}, {"location": "janssen-server/install/vm-install/dynamic-download/#prerequisites", "text": "curl should be installed", "title": "Prerequisites"}, {"location": "janssen-server/install/vm-install/dynamic-download/#install", "text": "Download the installer curl https://raw.githubusercontent.com/JanssenProject/jans/nightly/jans-linux-setup/jans_setup/install.py > install.py Execute Installer To execute installer, run the command below: python3 install.py The installer can be invoked using various options to tailor the installation process. Invoke the commands below to know about all the available options. python3 install.py --help One particularly useful option for development environments is the one below which installs the Janssen Server with test data loaded. python3 install.py --args=\"-t\" Installer can be run with all the arguments provided via command-line at the time of invocking the install script. This enables prompt-less installation. For example, see the command below: python3 install.py --args = \"-n -ip-address 10.229.38.28 -host-name jans-opensuse -city ah -state gj -country in -org-name gluu -email dhaval@gluu.org -jans-max-mem 26349 -admin-password admin --with-casa --install-jans-keycloak-link -t\"", "title": "Install"}, {"location": "janssen-server/install/vm-install/dynamic-download/#uninstall", "text": "Use the command below to uninstall the Janssen Server Note For removal of the attached persistence store, please refer to this note . python3 install.py -uninstall", "title": "Uninstall"}, {"location": "janssen-server/install/vm-install/rhel/", "tags": ["administration", "installation", "vm", "RHEL"], "text": "Red Hat EL Janssen Installation # Before you install, check the VM system requirements . Supported versions # Red Hat Enterprise Linux 8 (RHEL 8) Install the Package # Install EPEL and mod-auth-openidc as dependencies sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm sudo yum -y module enable mod_auth_openidc Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo rpm -import automation-jans-public-gpg.asc Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.el8.x86_64.rpm -P ~/ Verify integrity of the downloaded package using published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.el8.x86_64.rpm.sha256sum -P ~/ Check the hash if it is matching. sha256sum -c jans-0.0.0-nightly-el8.x86_64.rpm.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans-0.0.0-nightly-el8.x86_64.rpm: OK Install the package sudo yum install ~/jans-0.0.0-nightly-el8.x86_64.rpm Run the setup script # Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py The installer should confirm successful installation with a message similar to the one shown below: See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode. Verify the Installation # After the successful completion of setup process, verify the system health . Log in to Text User Interface (TUI) # Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa Enabling HTTPS # To enable communication with Janssen Server over TLS (https) in a production environment, Janssen Server needs details about CA certificate. Update the HTTPS cofiguration file https_jans.conf as shown below: Note Want to use Let's Encrypt to get a certificate? Follow this guide . Open https_jans.conf sudo vi /etc/httpd/conf.d/https_jans.conf Update SSLCertificateFile and SSLCertificateKeyFile parameters values SSLCertificateFile location_of_fullchain.pem SSLCertificateKeyFile location_of_privkey.pem Restart httpd service for changes to take effect sudo service httpd restart Uninstall # Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Delete files installed by Janssen Remove and purge the jans package Use the command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall Console output like below will confirm the successful uninstallation of the Janssen Server This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Stopping OpenDj Server Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/opendj Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf Remove the linux package Use the command below to remove and purge jans package yum remove jans.x86_64 Successful removal will remove the Janssen Server package along with the removal of all the unused dependencies.", "title": "RHEL"}, {"location": "janssen-server/install/vm-install/rhel/#red-hat-el-janssen-installation", "text": "Before you install, check the VM system requirements .", "title": "Red Hat EL Janssen Installation"}, {"location": "janssen-server/install/vm-install/rhel/#supported-versions", "text": "Red Hat Enterprise Linux 8 (RHEL 8)", "title": "Supported versions"}, {"location": "janssen-server/install/vm-install/rhel/#install-the-package", "text": "Install EPEL and mod-auth-openidc as dependencies sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm sudo yum -y module enable mod_auth_openidc Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo rpm -import automation-jans-public-gpg.asc Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.el8.x86_64.rpm -P ~/ Verify integrity of the downloaded package using published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.el8.x86_64.rpm.sha256sum -P ~/ Check the hash if it is matching. sha256sum -c jans-0.0.0-nightly-el8.x86_64.rpm.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans-0.0.0-nightly-el8.x86_64.rpm: OK Install the package sudo yum install ~/jans-0.0.0-nightly-el8.x86_64.rpm", "title": "Install the Package"}, {"location": "janssen-server/install/vm-install/rhel/#run-the-setup-script", "text": "Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py The installer should confirm successful installation with a message similar to the one shown below: See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode.", "title": "Run the setup script"}, {"location": "janssen-server/install/vm-install/rhel/#verify-the-installation", "text": "After the successful completion of setup process, verify the system health .", "title": "Verify the Installation"}, {"location": "janssen-server/install/vm-install/rhel/#log-in-to-text-user-interface-tui", "text": "Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa", "title": "Log in to Text User Interface (TUI)"}, {"location": "janssen-server/install/vm-install/rhel/#enabling-https", "text": "To enable communication with Janssen Server over TLS (https) in a production environment, Janssen Server needs details about CA certificate. Update the HTTPS cofiguration file https_jans.conf as shown below: Note Want to use Let's Encrypt to get a certificate? Follow this guide . Open https_jans.conf sudo vi /etc/httpd/conf.d/https_jans.conf Update SSLCertificateFile and SSLCertificateKeyFile parameters values SSLCertificateFile location_of_fullchain.pem SSLCertificateKeyFile location_of_privkey.pem Restart httpd service for changes to take effect sudo service httpd restart", "title": "Enabling HTTPS"}, {"location": "janssen-server/install/vm-install/rhel/#uninstall", "text": "Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Delete files installed by Janssen Remove and purge the jans package Use the command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall Console output like below will confirm the successful uninstallation of the Janssen Server This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Stopping OpenDj Server Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/opendj Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf Remove the linux package Use the command below to remove and purge jans package yum remove jans.x86_64 Successful removal will remove the Janssen Server package along with the removal of all the unused dependencies.", "title": "Uninstall"}, {"location": "janssen-server/install/vm-install/suse/", "tags": ["administration", "installation", "vm", "SUSE", "SLES", "Leap"], "text": "SUSE Janssen Installation # Before you install, check the VM system requirements . Supported versions # SUSE Linux Enterprise Server (SLES) 15 openSUSE Leap 15.5 Install the Package # If the server firewall is running, make sure you allow https , which is needed for OpenID and FIDO. sudo firewall-cmd --permanent --zone = public --add-service = https sudo firewall-cmd --reload for SLES, we need to enable PackageHub as per OSversion and architecture sudo SUSEConnect -p PackageHub/15.5/x86_64 Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo rpm -import automation-jans-public-gpg.asc Download the release package from the GitHub Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.suse15.x86_64.rpm Verify integrity of the downloaded package using published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.suse15.x86_64.rpm.sha256sum Check the hash if it is matching. You may need to change your working directory to where both the rpm and sha256sum file are located. sha256sum -c jans-0.0.0-nightly.suse15.x86_64.rpm.sha256sum Output similar to below should confirm the integrity of the downloaded package. <package-name>: OK Install the package sudo zypper install ~/jans-0.0.0-nightly.suse15.x86_64.rpm Run the setup script # Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode. Verify the Installation # After the successful completion of setup process, verify the system health . Log in to Text User Interface (TUI) # Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa Enabling HTTPS # To enable communication with Janssen Server over TLS (https) in a production environment, Janssen Server needs details about CA certificate. Update the HTTPS cofiguration file https_jans.conf as shown below: Note Want to use Let's Encrypt to get a certificate? Follow this guide . Open https_jans.conf sudo vi /etc/apache2/vhosts.d/_https_jans.conf Update SSLCertificateFile and SSLCertificateKeyFile parameters values SSLCertificateFile location_of_fullchain.pem SSLCertificateKeyFile location_of_privkey.pem Restart httpd service for changes to take effect sudo /usr/sbin/rcapache2 restart Uninstall # Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Uninstall Janssen Server Remove and purge the jans package If you have not run the Jans setup script, you can skip step 1 and just remove the package. First, run command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall You'll see the following confirmation: This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Stopping OpenDj Server Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/opendj Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf Second uninstall the package: rpm -qa | grep jans And then use zypper remove <package>", "title": "Suse"}, {"location": "janssen-server/install/vm-install/suse/#suse-janssen-installation", "text": "Before you install, check the VM system requirements .", "title": "SUSE Janssen Installation"}, {"location": "janssen-server/install/vm-install/suse/#supported-versions", "text": "SUSE Linux Enterprise Server (SLES) 15 openSUSE Leap 15.5", "title": "Supported versions"}, {"location": "janssen-server/install/vm-install/suse/#install-the-package", "text": "If the server firewall is running, make sure you allow https , which is needed for OpenID and FIDO. sudo firewall-cmd --permanent --zone = public --add-service = https sudo firewall-cmd --reload for SLES, we need to enable PackageHub as per OSversion and architecture sudo SUSEConnect -p PackageHub/15.5/x86_64 Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo rpm -import automation-jans-public-gpg.asc Download the release package from the GitHub Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.suse15.x86_64.rpm Verify integrity of the downloaded package using published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-0.0.0-nightly-stable.suse15.x86_64.rpm.sha256sum Check the hash if it is matching. You may need to change your working directory to where both the rpm and sha256sum file are located. sha256sum -c jans-0.0.0-nightly.suse15.x86_64.rpm.sha256sum Output similar to below should confirm the integrity of the downloaded package. <package-name>: OK Install the package sudo zypper install ~/jans-0.0.0-nightly.suse15.x86_64.rpm", "title": "Install the Package"}, {"location": "janssen-server/install/vm-install/suse/#run-the-setup-script", "text": "Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode.", "title": "Run the setup script"}, {"location": "janssen-server/install/vm-install/suse/#verify-the-installation", "text": "After the successful completion of setup process, verify the system health .", "title": "Verify the Installation"}, {"location": "janssen-server/install/vm-install/suse/#log-in-to-text-user-interface-tui", "text": "Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa", "title": "Log in to Text User Interface (TUI)"}, {"location": "janssen-server/install/vm-install/suse/#enabling-https", "text": "To enable communication with Janssen Server over TLS (https) in a production environment, Janssen Server needs details about CA certificate. Update the HTTPS cofiguration file https_jans.conf as shown below: Note Want to use Let's Encrypt to get a certificate? Follow this guide . Open https_jans.conf sudo vi /etc/apache2/vhosts.d/_https_jans.conf Update SSLCertificateFile and SSLCertificateKeyFile parameters values SSLCertificateFile location_of_fullchain.pem SSLCertificateKeyFile location_of_privkey.pem Restart httpd service for changes to take effect sudo /usr/sbin/rcapache2 restart", "title": "Enabling HTTPS"}, {"location": "janssen-server/install/vm-install/suse/#uninstall", "text": "Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Uninstall Janssen Server Remove and purge the jans package If you have not run the Jans setup script, you can skip step 1 and just remove the package. First, run command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall You'll see the following confirmation: This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Stopping OpenDj Server Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/opendj Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf Second uninstall the package: rpm -qa | grep jans And then use zypper remove <package>", "title": "Uninstall"}, {"location": "janssen-server/install/vm-install/ubuntu/", "tags": ["administration", "installation", "vm", "ubuntu"], "text": "Ubuntu Janssen Installation # Supported Versions # Ubuntu 22.04 Ubuntu 20.04 Before you install, check the VM system requirements . Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo gpg --import automation-jans-public-gpg.asc ; Install the Package # Ubuntu 22.04 # Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu22.04_amd64.deb -P /tmp Verify integrity of the downloaded package by verifying published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu22.04_amd64.deb.sha256sum -P /tmp Check the hash if it is matching. cd /tmp sha256sum -c jans_0.0.0-nightly.ubuntu22.04_amd64.deb.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans_0.0.0-nightly.ubuntu22.04_amd64.deb.sha256sum: OK Install the package sudo apt install ./jans_0.0.0-nightly.ubuntu22.04_amd64.deb Ubuntu 20.04 # Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu20.04_amd64.deb -P /tmp Verify integrity of the downloaded package by verifying published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu20.04_amd64.deb.sha256sum -P /tmp Check the hash if it is matching. cd /tmp sha256sum -c jans_0.0.0-nightly.ubuntu20.04_amd64.deb.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans_0.0.0-nightly.ubuntu20.04_amd64.deb.sha256sum: OK Install the package sudo apt install ./jans_0.0.0-nightly.ubuntu20.04_amd64.deb Run the setup script # Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode. Verify the Installation # After the successful completion of setup process, verify the system health . Log in to Text User Interface (TUI) # Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa Let's Encrypt # To enable communication with Janssen Server over tls (https) in production environment, Janssen Server needs details about CA certificate. To generate Let\u2019s Encrypt CA certificate follow this let's encrypt . Uninstall # Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Delete files installed by Janssen Remove and purge the jans package Use the command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall You'll see the following confirmation: This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf The command below removes and purges the jans package apt-get --purge remove jans Which should result in the following: Reading package lists... Done Building dependency tree... Done Reading state information... Done The following packages were automatically installed and are no longer required: apache2 apache2-bin apache2-data apache2-utils libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.3-0 postgresql postgresql-contrib python3-pymysql python3-ruamel.yaml python3-ruamel.yaml.clib Use 'apt autoremove' to remove them. The following packages will be REMOVED: jans* 0 upgraded, 0 newly installed, 1 to remove and 2 not upgraded. After this operation, 1631 MB disk space will be freed. Do you want to continue? [Y/n] y (Reading database ... 166839 files and directories currently installed.) Removing jans (0.0.0-nightly~ubuntu20.04) ... Checking to make sure service is down...", "title": "Ubuntu"}, {"location": "janssen-server/install/vm-install/ubuntu/#ubuntu-janssen-installation", "text": "", "title": "Ubuntu Janssen Installation"}, {"location": "janssen-server/install/vm-install/ubuntu/#supported-versions", "text": "Ubuntu 22.04 Ubuntu 20.04 Before you install, check the VM system requirements . Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo gpg --import automation-jans-public-gpg.asc ;", "title": "Supported Versions"}, {"location": "janssen-server/install/vm-install/ubuntu/#install-the-package", "text": "", "title": "Install the Package"}, {"location": "janssen-server/install/vm-install/ubuntu/#ubuntu-2204", "text": "Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu22.04_amd64.deb -P /tmp Verify integrity of the downloaded package by verifying published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu22.04_amd64.deb.sha256sum -P /tmp Check the hash if it is matching. cd /tmp sha256sum -c jans_0.0.0-nightly.ubuntu22.04_amd64.deb.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans_0.0.0-nightly.ubuntu22.04_amd64.deb.sha256sum: OK Install the package sudo apt install ./jans_0.0.0-nightly.ubuntu22.04_amd64.deb", "title": "Ubuntu 22.04"}, {"location": "janssen-server/install/vm-install/ubuntu/#ubuntu-2004", "text": "Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu20.04_amd64.deb -P /tmp Verify integrity of the downloaded package by verifying published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/nightly/jans_0.0.0-nightly-stable.ubuntu20.04_amd64.deb.sha256sum -P /tmp Check the hash if it is matching. cd /tmp sha256sum -c jans_0.0.0-nightly.ubuntu20.04_amd64.deb.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans_0.0.0-nightly.ubuntu20.04_amd64.deb.sha256sum: OK Install the package sudo apt install ./jans_0.0.0-nightly.ubuntu20.04_amd64.deb", "title": "Ubuntu 20.04"}, {"location": "janssen-server/install/vm-install/ubuntu/#run-the-setup-script", "text": "Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode.", "title": "Run the setup script"}, {"location": "janssen-server/install/vm-install/ubuntu/#verify-the-installation", "text": "After the successful completion of setup process, verify the system health .", "title": "Verify the Installation"}, {"location": "janssen-server/install/vm-install/ubuntu/#log-in-to-text-user-interface-tui", "text": "Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa", "title": "Log in to Text User Interface (TUI)"}, {"location": "janssen-server/install/vm-install/ubuntu/#lets-encrypt", "text": "To enable communication with Janssen Server over tls (https) in production environment, Janssen Server needs details about CA certificate. To generate Let\u2019s Encrypt CA certificate follow this let's encrypt .", "title": "Let's Encrypt"}, {"location": "janssen-server/install/vm-install/ubuntu/#uninstall", "text": "Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Delete files installed by Janssen Remove and purge the jans package Use the command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall You'll see the following confirmation: This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf The command below removes and purges the jans package apt-get --purge remove jans Which should result in the following: Reading package lists... Done Building dependency tree... Done Reading state information... Done The following packages were automatically installed and are no longer required: apache2 apache2-bin apache2-data apache2-utils libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.3-0 postgresql postgresql-contrib python3-pymysql python3-ruamel.yaml python3-ruamel.yaml.clib Use 'apt autoremove' to remove them. The following packages will be REMOVED: jans* 0 upgraded, 0 newly installed, 1 to remove and 2 not upgraded. After this operation, 1631 MB disk space will be freed. Do you want to continue? [Y/n] y (Reading database ... 166839 files and directories currently installed.) Removing jans (0.0.0-nightly~ubuntu20.04) ... Checking to make sure service is down...", "title": "Uninstall"}, {"location": "janssen-server/install/vm-install/vm-requirements/", "tags": ["requirements", "installation", "vm", "hardware"], "text": "VM System Requirements # The Janssen Project currently provides packages for these Linux distros: Ubuntu (versions: 20.04) SUSE (SLES or LEAP) (version: 15) RedHat Enterprise Linux (version: 8) Hardware Requirements # A single-VM deployment is where all services are running on one server. Although, the requirements can vary based on the size of the data and the required concurrency, the following guidelines can help you plan: Development and Test Environments # 8 GB RAM 4 CPU 20 GB Disk Production Environment Recommendation: # 8 GB RAM 4 CPU 4 GB swap space 50 GB Disk Port Configuration # Janssen Server requires the following ports to be open for incoming connections. Port Protocol Notes 443 TCP TLS/HTTP You may want to use a redirect on port 80 to 443, although it is not required. Of course you will also need some way to login to your server, but that is out of scope of these docs. Check your server firewall documentation to configure your firewall to allow https . Hostname / IP Address Configuration # It is recommended that you use a static ip address for your Janssen Server. Your server should also return the hostname for the hostname command, it's recommended that you add the hostname to the /etc/hosts file. File Descriptor Configuration (FD) # Like most database and Internet servers, you must have at least 65k file descriptors. If you don't, your server will hang. First, check the current file descriptor limit using command below. If the existing FD limit exceeds 65535, then you're good. # cat /proc/sys/fs/file-max If FD limit is less than 65535 (e.g. 1024), then follow the steps below to increase the value. 1) Set soft and hard limits by adding the following lines in the /etc/security/limits.conf file * soft nofile 65535 * hard nofile 262144 2) Add the following lines to /etc/pam.d/login if not already present session required pam_limits.so 3) Increase the FD limit in /proc/sys/fs/file-max echo 65535 > /proc/sys/fs/file-max** 4) Use the ulimit command to set the FD limit to the hard limit specified in /etc/security/limits.conf . If setting to hard limit doesn't work, then try to set it to the soft limit. ulimit -n 262144 5) Restart the system", "title": "VM Requirements"}, {"location": "janssen-server/install/vm-install/vm-requirements/#vm-system-requirements", "text": "The Janssen Project currently provides packages for these Linux distros: Ubuntu (versions: 20.04) SUSE (SLES or LEAP) (version: 15) RedHat Enterprise Linux (version: 8)", "title": "VM System Requirements"}, {"location": "janssen-server/install/vm-install/vm-requirements/#hardware-requirements", "text": "A single-VM deployment is where all services are running on one server. Although, the requirements can vary based on the size of the data and the required concurrency, the following guidelines can help you plan:", "title": "Hardware Requirements"}, {"location": "janssen-server/install/vm-install/vm-requirements/#development-and-test-environments", "text": "8 GB RAM 4 CPU 20 GB Disk", "title": "Development and Test Environments"}, {"location": "janssen-server/install/vm-install/vm-requirements/#production-environment-recommendation", "text": "8 GB RAM 4 CPU 4 GB swap space 50 GB Disk", "title": "Production Environment Recommendation:"}, {"location": "janssen-server/install/vm-install/vm-requirements/#port-configuration", "text": "Janssen Server requires the following ports to be open for incoming connections. Port Protocol Notes 443 TCP TLS/HTTP You may want to use a redirect on port 80 to 443, although it is not required. Of course you will also need some way to login to your server, but that is out of scope of these docs. Check your server firewall documentation to configure your firewall to allow https .", "title": "Port Configuration"}, {"location": "janssen-server/install/vm-install/vm-requirements/#hostname-ip-address-configuration", "text": "It is recommended that you use a static ip address for your Janssen Server. Your server should also return the hostname for the hostname command, it's recommended that you add the hostname to the /etc/hosts file.", "title": "Hostname / IP Address Configuration"}, {"location": "janssen-server/install/vm-install/vm-requirements/#file-descriptor-configuration-fd", "text": "Like most database and Internet servers, you must have at least 65k file descriptors. If you don't, your server will hang. First, check the current file descriptor limit using command below. If the existing FD limit exceeds 65535, then you're good. # cat /proc/sys/fs/file-max If FD limit is less than 65535 (e.g. 1024), then follow the steps below to increase the value. 1) Set soft and hard limits by adding the following lines in the /etc/security/limits.conf file * soft nofile 65535 * hard nofile 262144 2) Add the following lines to /etc/pam.d/login if not already present session required pam_limits.so 3) Increase the FD limit in /proc/sys/fs/file-max echo 65535 > /proc/sys/fs/file-max** 4) Use the ulimit command to set the FD limit to the hard limit specified in /etc/security/limits.conf . If setting to hard limit doesn't work, then try to set it to the soft limit. ulimit -n 262144 5) Restart the system", "title": "File Descriptor Configuration (FD)"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/", "tags": ["administration", "keycloak", "SAML", "inbound"], "text": "Overview # Janssen supports authentication against external SAML identity provider (IDP) namely inbound SAML/inbound identity. This document provides instructions for configuring Janssen server Enable inbound SAML # Make sure you have Janssen server with SAML plugin installed and enabled. SAML plugin can be enabled using TUI (Jans Saml -> Contribution) Inbound SAML Authentication Flow # The following is a high-level diagram depicting a typical inbound identity user authentication and provisioning workflow. Configure SAML IDP # Use Janssen Text-based UI(TUI) or Janssen command-line interface to create new IDP Keycloak Server. 1. Navigate to Jans SAML > Identity Providers Go to Add Identity Provider and press Enter Enter a name (unique identifier) for this provider (letters, digits, and underscore characters allowed). Enter a display name for the Add Identity Provider Upload IDP Metadata by selecting file for Metadata Source Type and press Enter after you navigated on Browse of Metadata File Or you can, optionally provide individual metadata elements by selecting manual for Metadata Source Type . See adding a sample idp in the following figure Save details SAML IDP is created in Keycloak server under realm jans . IDP details are also persisted in Jans DB. To edit IDP details later, you can navigate to the idp in the list and press Enter , you will get a popup screen as shown in the figure below: Configure IDP for inbound SAML # SAML IDP should have been configured as stated in above Use Agama Lab is an online visual editor to build authentication flows. Learn more about Agama Lab Fork existing agama-inbound-saml project from Agama Lab Projects In Agama orchestrator create a new flow by adding a RFAC (Redirect and fetch a callback) node for SAML IDP. Deploying .gama package on Janssen Server Testing the authentication flow using Jans Tarp. Install Tarp, check details here . Open Tarp extension. Enter URL of Keycloak OpenID configuration. Example http:///realms/keycloak-external-broker/.well-known/openid-configuration. Click Register. Registered Client details are displayed, enter Additional Params to hint Keycloak about IDP to be trigger. Example {\"kc_idp_hint\":\"gluu-saml-idp-1\"} Click \"Trigger Auth Code Flow. This should redirect to IDP login page. Enter user details and login.", "title": "Inbound SAML"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/#overview", "text": "Janssen supports authentication against external SAML identity provider (IDP) namely inbound SAML/inbound identity. This document provides instructions for configuring Janssen server", "title": "Overview"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/#enable-inbound-saml", "text": "Make sure you have Janssen server with SAML plugin installed and enabled. SAML plugin can be enabled using TUI (Jans Saml -> Contribution)", "title": "Enable inbound SAML"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/#inbound-saml-authentication-flow", "text": "The following is a high-level diagram depicting a typical inbound identity user authentication and provisioning workflow.", "title": "Inbound SAML Authentication Flow"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/#configure-saml-idp", "text": "Use Janssen Text-based UI(TUI) or Janssen command-line interface to create new IDP Keycloak Server. 1. Navigate to Jans SAML > Identity Providers Go to Add Identity Provider and press Enter Enter a name (unique identifier) for this provider (letters, digits, and underscore characters allowed). Enter a display name for the Add Identity Provider Upload IDP Metadata by selecting file for Metadata Source Type and press Enter after you navigated on Browse of Metadata File Or you can, optionally provide individual metadata elements by selecting manual for Metadata Source Type . See adding a sample idp in the following figure Save details SAML IDP is created in Keycloak server under realm jans . IDP details are also persisted in Jans DB. To edit IDP details later, you can navigate to the idp in the list and press Enter , you will get a popup screen as shown in the figure below:", "title": "Configure SAML IDP"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/#configure-idp-for-inbound-saml", "text": "SAML IDP should have been configured as stated in above Use Agama Lab is an online visual editor to build authentication flows. Learn more about Agama Lab Fork existing agama-inbound-saml project from Agama Lab Projects In Agama orchestrator create a new flow by adding a RFAC (Redirect and fetch a callback) node for SAML IDP. Deploying .gama package on Janssen Server Testing the authentication flow using Jans Tarp. Install Tarp, check details here . Open Tarp extension. Enter URL of Keycloak OpenID configuration. Example http:///realms/keycloak-external-broker/.well-known/openid-configuration. Click Register. Registered Client details are displayed, enter Additional Params to hint Keycloak about IDP to be trigger. Example {\"kc_idp_hint\":\"gluu-saml-idp-1\"} Click \"Trigger Auth Code Flow. This should redirect to IDP login page. Enter user details and login.", "title": "Configure IDP for inbound SAML"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/", "tags": ["administration", "keycloak", "SAML", "SSO"], "text": "Overview # The Janssen Server acts as a SAML Identity Provider to support outbound SAML single sign-on (SSO). It does this by leveraging the SAML features available in Keycloak , while leveraging the Janssen Server's authentication module to handle the user authentication part of SSO. Once authentication is successful, the user is redirected to the SP with personal attributes and an active SSO session. Installation # During installation of the Janssen Server, simply select the option Install Jans KC to install and setup SAML SSO for Keycloak. Instructions on how to setup SAML SSO with Keycloak post-install will eventually be provided. Managing SAML Service Providers Through the Jans-Cli # To act as an IDP to various SAML SPs (Service Providers), the latter need to be added to the Janssen Server. This can be done via the Jans TUI which is what we will cover in this section. Adding a SAML SP # Open Jans-TUI Select the menu item Jans SAML > Service Providers Then navigate and select <Add Service Provider> Input the following: Display Name : An identifiable name for the Service Provider Enable TR : Whether or not the Service Provider should be enabled Metadata Location : The location of the metadata. The supported options so far are file and manual . Released Attributes : The user attributes to be released via the SAML response if authentication is successful The configurable options are kept to the bare functional minimum but will be expanded gradually. The manual metadata option for Metadata Location , allows the possibility to specify SP metadata information manually. IDP Metadata Location # For SAML authentication to work, there is a need for the SPs to trust the IDP, which usually is done by using an IDP metadata file that will be used on the SP side. The metadata can be found at https://<server-hostname>/kc/realms/jans/protocol/saml/descriptor where <server-hostname> is the hostname of the Janssen server specified during installation. IDP Initiated Flows # This content is a work in progress IDP Key Management # This content is a work in progress Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "SAML SSO"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#overview", "text": "The Janssen Server acts as a SAML Identity Provider to support outbound SAML single sign-on (SSO). It does this by leveraging the SAML features available in Keycloak , while leveraging the Janssen Server's authentication module to handle the user authentication part of SSO. Once authentication is successful, the user is redirected to the SP with personal attributes and an active SSO session.", "title": "Overview"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#installation", "text": "During installation of the Janssen Server, simply select the option Install Jans KC to install and setup SAML SSO for Keycloak. Instructions on how to setup SAML SSO with Keycloak post-install will eventually be provided.", "title": "Installation"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#managing-saml-service-providers-through-the-jans-cli", "text": "To act as an IDP to various SAML SPs (Service Providers), the latter need to be added to the Janssen Server. This can be done via the Jans TUI which is what we will cover in this section.", "title": "Managing SAML Service Providers Through the Jans-Cli"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#adding-a-saml-sp", "text": "Open Jans-TUI Select the menu item Jans SAML > Service Providers Then navigate and select <Add Service Provider> Input the following: Display Name : An identifiable name for the Service Provider Enable TR : Whether or not the Service Provider should be enabled Metadata Location : The location of the metadata. The supported options so far are file and manual . Released Attributes : The user attributes to be released via the SAML response if authentication is successful The configurable options are kept to the bare functional minimum but will be expanded gradually. The manual metadata option for Metadata Location , allows the possibility to specify SP metadata information manually.", "title": "Adding a SAML SP"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#idp-metadata-location", "text": "For SAML authentication to work, there is a need for the SPs to trust the IDP, which usually is done by using an IDP metadata file that will be used on the SP side. The metadata can be found at https://<server-hostname>/kc/realms/jans/protocol/saml/descriptor where <server-hostname> is the hostname of the Janssen server specified during installation.", "title": "IDP Metadata Location"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#idp-initiated-flows", "text": "This content is a work in progress", "title": "IDP Initiated Flows"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#idp-key-management", "text": "This content is a work in progress", "title": "IDP Key Management"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/kubernetes-ops/backup-restore/", "tags": ["administration", "kubernetes", "operations", "backup", "restore"], "text": "The Jans Server should be backed up frequently, we recommend once daily . There are multiple methods for backing up jans server. One way is manually using imperative commands. The other is automatically using open source tools. Manual Backup and Restore # Manual Backup # Configmap backup: kubectl get configmap cn -n <namespace> -o yaml > configmap-backup.yaml Secret backup: kubectl get secret cn -n <namespace> -o yaml > secret-backup.yaml Get the user supplied values: Save the values.yaml that was used in the initial jans installation using helm. In the event that the user supplied or override values yaml was lost, you can obtain it by executing the following command: helm get values <release name> -n <namespace> Keep note of installed chart version: helm list -n <namespace> Keep note of the chart version. For example: 0.0.0-nightly Manual Restore # Create namespace kubectl create namespace <namespace> Configmap restore: kubectl create -f configmap-backup.yaml Secret restore: kubectl create -f secret-backup.yaml Insall jans using the override or user supplied values with the same chart version: helm install <release-name> janssen/janssen -f values.yaml --version = <0.0.0-nightly> -n <namespace> Automatic Backup and Restore # There are several tools that helps in automatic backups and restore, like Kasten K10 . You can follow online guides to deploy it and use it to configure automatic backups.", "title": "Backup and Restore"}, {"location": "janssen-server/kubernetes-ops/backup-restore/#manual-backup-and-restore", "text": "", "title": "Manual Backup and Restore"}, {"location": "janssen-server/kubernetes-ops/backup-restore/#manual-backup", "text": "Configmap backup: kubectl get configmap cn -n <namespace> -o yaml > configmap-backup.yaml Secret backup: kubectl get secret cn -n <namespace> -o yaml > secret-backup.yaml Get the user supplied values: Save the values.yaml that was used in the initial jans installation using helm. In the event that the user supplied or override values yaml was lost, you can obtain it by executing the following command: helm get values <release name> -n <namespace> Keep note of installed chart version: helm list -n <namespace> Keep note of the chart version. For example: 0.0.0-nightly", "title": "Manual Backup"}, {"location": "janssen-server/kubernetes-ops/backup-restore/#manual-restore", "text": "Create namespace kubectl create namespace <namespace> Configmap restore: kubectl create -f configmap-backup.yaml Secret restore: kubectl create -f secret-backup.yaml Insall jans using the override or user supplied values with the same chart version: helm install <release-name> janssen/janssen -f values.yaml --version = <0.0.0-nightly> -n <namespace>", "title": "Manual Restore"}, {"location": "janssen-server/kubernetes-ops/backup-restore/#automatic-backup-and-restore", "text": "There are several tools that helps in automatic backups and restore, like Kasten K10 . You can follow online guides to deploy it and use it to configure automatic backups.", "title": "Automatic Backup and Restore"}, {"location": "janssen-server/kubernetes-ops/cert-management/", "tags": ["administration", "kubernetes", "operations", "certificate management", "certification and key rotation"], "text": "Overview # Rotating Certificates and Keys in Kubernetes setup Note janssen-config-cm in all examples refer to jans installation configuration parameters where janssen is the helm-release-name . Web (Ingress) # Associated certificates and keys /etc/certs/web_https.crt /etc/certs/web_https.key Note During fresh installation, the config-job checks if SSL certificates and keys are mounted as files. If no mounted files are found, it attempts to download SSL certificates from the FQDN supplied. If the download is successful, an empty key file is generated. If no mounted or downloaded files are found, it generates self-signed SSL certificates, CA certificates, and keys. Rotate # Create a file named web-key-rotation.yaml with the following contents : apiVersion : batch/v1 kind : Job metadata : name : web-key-rotation spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : restartPolicy : Never containers : - name : web-key-rotation image : ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly-1 envFrom : - configMapRef : name : janssen-config-cm # This may be differnet in Helm args : [ \"patch\" , \"web\" , \"--opts\" , \"valid-to:365\" ] Apply job kubectl apply -f web-key-rotation.yaml -n <jans-namespace> Load from existing source # Note This will load web_https.crt and web_https.key from /etc/certs . Create a secret with web_https.crt and web_https.key . Note that this may already exist in your deployment. kubectl create secret generic web-cert-key --from-file = web_https.crt --from-file = web_https.key -n <jans-namespace> ` Create a file named load-web-key-rotation.yaml with the following contents : apiVersion : batch/v1 kind : Job metadata : name : load-web-key-rotation spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : restartPolicy : Never volumes : - name : web-cert secret : secretName : web-cert-key items : - key : web_https.crt path : web_https.crt - name : web-key secret : secretName : web-cert-key items : - key : web_https.key path : web_https.key containers : - name : load-web-key-rotation image : ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly-1 envFrom : - configMapRef : name : janssen-config-cm #This may be differnet in Helm volumeMounts : - name : web-cert mountPath : /etc/certs/web_https.crt subPath : web_https.crt - name : web-key mountPath : /etc/certs/web_https.key subPath : web_https.key args : [ \"patch\" , \"web\" , \"--opts\" , \"source:from-files\" ] Apply job kubectl apply -f load-web-key-rotation.yaml -n <jans-namespace> Auth-server # Warning key rotation CronJob is usually installed with jans. Please make sure before deploying using kubectl get cronjobs -n <jans-namespace> Associated certificates and keys /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Create a file named auth-key-rotation.yaml with the following contents : kind : CronJob apiVersion : batch/v1 metadata : name : auth-key-rotation spec : # runs the job every 48 hours schedule : \"@every 48h\" concurrencyPolicy : Forbid jobTemplate : spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : containers : - name : auth-key-rotation image : ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly-1 resources : requests : memory : \"300Mi\" cpu : \"300m\" limits : memory : \"300Mi\" cpu : \"300m\" envFrom : - configMapRef : name : janssen-config-cm args : [ \"patch\" , \"auth\" , \"--opts\" , \"interval:48\" , \"--opts\" , \"key-strategy:OLDER\" , \"--opts\" , \"privkey-push-delay:300\" , \"--opts\" , \"privkey-push-strategy:NEWER\" ] restartPolicy : Never Apply cron job kubectl apply -f auth-key-rotation.yaml -n <jans-namespace>", "title": "Certificate Management"}, {"location": "janssen-server/kubernetes-ops/cert-management/#overview", "text": "Rotating Certificates and Keys in Kubernetes setup Note janssen-config-cm in all examples refer to jans installation configuration parameters where janssen is the helm-release-name .", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/cert-management/#web-ingress", "text": "Associated certificates and keys /etc/certs/web_https.crt /etc/certs/web_https.key Note During fresh installation, the config-job checks if SSL certificates and keys are mounted as files. If no mounted files are found, it attempts to download SSL certificates from the FQDN supplied. If the download is successful, an empty key file is generated. If no mounted or downloaded files are found, it generates self-signed SSL certificates, CA certificates, and keys.", "title": "Web (Ingress)"}, {"location": "janssen-server/kubernetes-ops/cert-management/#rotate", "text": "Create a file named web-key-rotation.yaml with the following contents : apiVersion : batch/v1 kind : Job metadata : name : web-key-rotation spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : restartPolicy : Never containers : - name : web-key-rotation image : ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly-1 envFrom : - configMapRef : name : janssen-config-cm # This may be differnet in Helm args : [ \"patch\" , \"web\" , \"--opts\" , \"valid-to:365\" ] Apply job kubectl apply -f web-key-rotation.yaml -n <jans-namespace>", "title": "Rotate"}, {"location": "janssen-server/kubernetes-ops/cert-management/#load-from-existing-source", "text": "Note This will load web_https.crt and web_https.key from /etc/certs . Create a secret with web_https.crt and web_https.key . Note that this may already exist in your deployment. kubectl create secret generic web-cert-key --from-file = web_https.crt --from-file = web_https.key -n <jans-namespace> ` Create a file named load-web-key-rotation.yaml with the following contents : apiVersion : batch/v1 kind : Job metadata : name : load-web-key-rotation spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : restartPolicy : Never volumes : - name : web-cert secret : secretName : web-cert-key items : - key : web_https.crt path : web_https.crt - name : web-key secret : secretName : web-cert-key items : - key : web_https.key path : web_https.key containers : - name : load-web-key-rotation image : ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly-1 envFrom : - configMapRef : name : janssen-config-cm #This may be differnet in Helm volumeMounts : - name : web-cert mountPath : /etc/certs/web_https.crt subPath : web_https.crt - name : web-key mountPath : /etc/certs/web_https.key subPath : web_https.key args : [ \"patch\" , \"web\" , \"--opts\" , \"source:from-files\" ] Apply job kubectl apply -f load-web-key-rotation.yaml -n <jans-namespace>", "title": "Load from existing source"}, {"location": "janssen-server/kubernetes-ops/cert-management/#auth-server", "text": "Warning key rotation CronJob is usually installed with jans. Please make sure before deploying using kubectl get cronjobs -n <jans-namespace> Associated certificates and keys /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Create a file named auth-key-rotation.yaml with the following contents : kind : CronJob apiVersion : batch/v1 metadata : name : auth-key-rotation spec : # runs the job every 48 hours schedule : \"@every 48h\" concurrencyPolicy : Forbid jobTemplate : spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : containers : - name : auth-key-rotation image : ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly-1 resources : requests : memory : \"300Mi\" cpu : \"300m\" limits : memory : \"300Mi\" cpu : \"300m\" envFrom : - configMapRef : name : janssen-config-cm args : [ \"patch\" , \"auth\" , \"--opts\" , \"interval:48\" , \"--opts\" , \"key-strategy:OLDER\" , \"--opts\" , \"privkey-push-delay:300\" , \"--opts\" , \"privkey-push-strategy:NEWER\" ] restartPolicy : Never Apply cron job kubectl apply -f auth-key-rotation.yaml -n <jans-namespace>", "title": "Auth-server"}, {"location": "janssen-server/kubernetes-ops/custom-attributes/", "tags": ["administration", "kubernetes", "operations", "custom attributes", "schema", "claim"], "text": "Overview # Making changes in the schema to add custom columns/attributes Download the custom_schema.json file: wget https://raw.githubusercontent.com/JanssenProject/jans/main/jans-linux-setup/jans_setup/schema/custom_schema.json Make your edits in custom_schema.json : For example we will add 4 attributes and define them as int, json, bool, and text Firstly, add the attribute names to the object class: \"objectClasses\": [ { \"kind\": \"AUXILIARY\", \"may\": [ \"intAttribute\", \"jsonAttribute\", \"boolAttribute\", \"textAttribute\" Describe the attributes inside attributeTypes . You can refer to RFC 4517 : \"attributeTypes\": [ { \"desc\": \"int desc\", \"equality\": \"integerMatch\", \"names\": [ \"intAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.27\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"json desc\", \"equality\": \"caseIgnoreSubstringsMatch\", \"names\": [ \"jsonAttribute\" ], \"multivalued\": true, \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.15\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"bool desc\", \"equality\": \"booleanMatch\", \"names\": [ \"boolAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.7\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"text desc\", \"equality\": \"caseIgnoreMatch\", \"names\": [ \"textAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.15\", \"x_origin\": \"Jans created attribute\" } ], Create a configmap with the schema file: kubectl create cm custom-schema-cm --from-file=custom_schema.json -n <namespace> Mount the configmap in your override.yaml under persistence.volumes and persistence.volumeMounts : persistence: volumeMounts: - name: schema mountPath: /app/schema/custom_schema.json subPath: custom_schema.json volumes: - name: schema configMap: name: custom-schema-cm Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f override.yaml --version = 1 .0.x", "title": "Custom Attributes"}, {"location": "janssen-server/kubernetes-ops/custom-attributes/#overview", "text": "Making changes in the schema to add custom columns/attributes Download the custom_schema.json file: wget https://raw.githubusercontent.com/JanssenProject/jans/main/jans-linux-setup/jans_setup/schema/custom_schema.json Make your edits in custom_schema.json : For example we will add 4 attributes and define them as int, json, bool, and text Firstly, add the attribute names to the object class: \"objectClasses\": [ { \"kind\": \"AUXILIARY\", \"may\": [ \"intAttribute\", \"jsonAttribute\", \"boolAttribute\", \"textAttribute\" Describe the attributes inside attributeTypes . You can refer to RFC 4517 : \"attributeTypes\": [ { \"desc\": \"int desc\", \"equality\": \"integerMatch\", \"names\": [ \"intAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.27\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"json desc\", \"equality\": \"caseIgnoreSubstringsMatch\", \"names\": [ \"jsonAttribute\" ], \"multivalued\": true, \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.15\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"bool desc\", \"equality\": \"booleanMatch\", \"names\": [ \"boolAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.7\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"text desc\", \"equality\": \"caseIgnoreMatch\", \"names\": [ \"textAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.15\", \"x_origin\": \"Jans created attribute\" } ], Create a configmap with the schema file: kubectl create cm custom-schema-cm --from-file=custom_schema.json -n <namespace> Mount the configmap in your override.yaml under persistence.volumes and persistence.volumeMounts : persistence: volumeMounts: - name: schema mountPath: /app/schema/custom_schema.json subPath: custom_schema.json volumes: - name: schema configMap: name: custom-schema-cm Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f override.yaml --version = 1 .0.x", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/customization/", "tags": ["administration", "developer", "operations", "kubernetes", "customization"], "text": "Most organizations will want to edit and customize the look and feel of public-facing jans server pages to match their own corporate branding. The following documentation provides the file locations of public facing pages, as well as instructions for adding custom HTML, CSS, and Javascript files to your jans server. Overview # All web pages are xhtml files. Default pages bundled in the jans-auth.war are: # Login page: login.xhtml Authorization page: authorize.xhtml Logout page: logout.xhtml Error page: error.xhtml To override default pages listed above: # Put a modified login.xhtml or authorize.xhtml or error.xhtml or logout.xhtml under /opt/jans/jetty/jans-auth/custom/pages/ Directory structure for customization # /opt/jans/jetty/jans-auth/ |-- custom | |-- i18n (resource bundles) | |-- libs (library files used by custom script) | |-- pages (web pages) | |-- static (images and css files) Adding a new web page for Person Authentication scripts # If enterOTP.xhtml is your webpage for step 2 of authentication, place it under /opt/jans/jetty/jans-auth/custom/pages/auth/enterOTP.xhtml Reference it in the custom script as follows: def getPageForStep(self, configurationAttributes, step): # Used to specify the page you want to return for a given step if (step == 1): return \"/auth/login.xhtml\" if (step == 2) return \"/auth/enterOTP.xhtml\" Reference login pages # Here you will find several login pages for different authentication methods. Customized resource bundles # Resource bundles that are present in the jans-auth.war are present in this folder To override the defaults, custom .properties files should be placed in the following file under this path : /opt/jans/jetty/jans-auth/custom/i18n/jans-auth.properties Resource bundle names to support other languages should be placed under the same folder /opt/jans/jetty/jans-auth/custom/i18n/ . Some examples of file names are : jans-auth_en.properties jans-auth_bg.properties jans-auth_de.properties jans-auth_es.properties jans-auth_fr.properties jans-auth_it.properties jans-auth_ru.properties jans-auth_tr.properties To add translation for a language that is not yet supported, create new properties file in resource folder and name it jans-auth_[language_code].properties, then add language code as supported-locale to the faces-config.xml present in the same folder. Custom CSS files # Place the file in /opt/jans/jetty/jans-auth/custom/static/stylesheet/theme.css Reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/stylesheet/theme.css or /jans-auth/ext/resources/stylesheet/theme.css Custom image files # All images should be placed under /opt/jans/jetty/jans-auth/custom/static/img Reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/img/fileName.png or /jans-auth/ext/resources/img/fileName.jpg Page layout, header, footer (xhtml Template) customization # Templates refers to the common interface layout and style. For example, a banner, logo in common header and copyright information in footer. All templates should be placed under /opt/jans/jetty/jans-auth/custom/pages/WEB-INF/incl/layout/ Place a modified template.xhtml in the above location which will override the default template file from the war Custom Jar file for scripts # for JARs less than 1MB # Create a configmap with the custom jar file: kubectl -n <namespace> create cm my-custom-jar --from-file=mycustom.jar Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts auth-server: volumeMounts: - name: my-custom-jar-volume mountPath: /opt/jans/jetty/jans-auth/custom/libs/mycustom.jar subPath: mycustom.jar volumes: - name: my-custom-jar-volume configMap: name: my-custom-jar Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x For JARs greater than 1MB # Create a configmap or secret for a shell script that contains instructions to pull the custom jar file: #!/bin/sh # This script will pull the custom jar file from a remote location # and place it in the correct location for the Jans Auth server to use it wget -O /opt/jans/jetty/jans-auth/custom/libs/mycustom.jar https://mydomain.com/mycustom.jar kubectl -n <namespace> create cm my-custom-jar --from-file=mycustomjar.sh Mount the configmap or secret in your values.yaml under auth-server.volumes and auth-server.volumeMounts auth-server: volumeMounts: - name: my-custom-jar-volume mountPath: /tmp/mycustomjar.sh subPath: mycustomjar.sh volumes: - name: my-custom-jar-volume configMap: name: my-custom-jar defaultMode: 0755 customScripts: - /tmp/mycustomjar.sh Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Customized pages examples # Custom Login page # This guide will demonstrate how to customize the html and css of the default login page. Here's a screenshot of the default login page. As an example, we will add text to the top of the form and change the color of the button using the following steps: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the login.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/login.xhtml login.xhtml Modify the file locally: < h:form id = \"loginForm\" class = \"bg-highlight position-relative d-flex flex-column align-items-center justify-content-center\" style = \"height: 100vh; gap: 2rem\" > <!-- customization --> < div class = \"row\" >< p id = \"creds-title\" > Enter Credentials </ p ></ div > <!-- end of customization --> Get the login-template.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/WEB-INF/incl/layout/login-template.xhtml login-template.xhtml Modify the file locally: < h:head > < link type = \"text/css\" rel = \"stylesheet\" href = \"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" /> <!-- customization --> < link rel = \"stylesheet\" href = \"/jans-auth/ext/resources/stylesheet/custom.css\" /> <!-- end of customization --> </ h:head > Copy the following text and save it as custom.css : # creds-title { font-style : italic ; font-weight : bolder ; color : white ; font-size : 2 em ; } Create configmaps to store the content of login.xhtml , login-template.xhtml and custom.css . kubectl -n <namespace> create cm auth-server-custom-html --from-file = login.xhtml kubectl -n <namespace> create cm auth-server-custom-layout-html --from-file = login-template.xhtml kubectl -n <namespace> create cm auth-server-custom-css --from-file = custom.css Mount the configmaps in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : auth-server-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # login.xthml will be mounted under this directory - name : auth-server-layout-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages/WEB-INF/incl/layout # login-template.xthml will be mounted under this directory - name : auth-server-static-volume mountPath : /tmp/static #custom.css will be mounted in the temporary location lifecycle : postStart : exec : command : [ \"sh\" , \"-c\" , \"mkdir /opt/jans/jetty/jans-auth/custom/static/stylesheet/ && cp /tmp/static/custom.css /opt/jans/jetty/jans-auth/custom/static/stylesheet/\" ] # custom.css will be copied from the temporary to the desired location volumes : - name : auth-server-pages-volume configMap : name : auth-server-custom-html - name : auth-server-layout-volume configMap : name : auth-server-custom-layout-html - name : auth-server-static-volume configMap : name : auth-server-custom-css Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized login page. Custom Device-code page # This guide will demonstrate how to customize the html and css of the device-code page. Here's a screenshot of the device-code page. As an example, we will change the color of the button to blue using the following steps: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the device_authorization.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/device_authorization.xhtml device_authorization.xhtml Modify the file locally: < div class = \"device-authz-button\" > < div style = \"width: 100%\" > <!-- customization --> < div style = \"text-align: center;\" > < h:commandButton id = \"continueButton\" style = \"background-color: red; color: white;\" value = \"#{msgs['device.authorization.confirm.button']}\" iconAwesome = \"fa-sign-in\" > < f:ajax execute = \"@form\" render = \"@form messages\" listener = \"#{deviceAuthorizationAction.processUserCodeVerification}\" /> </ h:commandButton > </ div > <!-- end of customization --> Create a configmap to store the content of device_authorization.xhtml . kubectl -n <namespace> create cm device-code-custom-html --from-file = device_authorization.xhtml Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : device-code-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # device_authorization.xthml will be mounted under this directory volumes : - name : device-code-pages-volume configMap : name : device-code-custom-html Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized device-code page. Custom Error page # This guide will demonstrate how to customize the html and css of the error page. Here's a screenshot of the default Error page. As an example, we will change the color of the text at the top of the error page: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the error.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/error.xhtml error.xhtml Modify the file locally: < div class = \"section\" > <!-- customization --> < h1 style = \"color: red; font-size: 3em; font-weight: bold; font-family: Arial\" > OOPS </ h1 > <!-- end of customization --> </ div > Create a configmap to store the content of error.xhtml . kubectl -n <namespace> create cm error-custom-html --from-file = error.xhtml Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : error-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # error.xthml will be mounted under this directory volumes : - name : error-pages-volume configMap : name : error-custom-html Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized error page.", "title": "Customization"}, {"location": "janssen-server/kubernetes-ops/customization/#overview", "text": "All web pages are xhtml files.", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/customization/#default-pages-bundled-in-the-jans-authwar-are", "text": "Login page: login.xhtml Authorization page: authorize.xhtml Logout page: logout.xhtml Error page: error.xhtml", "title": "Default pages bundled in the jans-auth.war are:"}, {"location": "janssen-server/kubernetes-ops/customization/#to-override-default-pages-listed-above", "text": "Put a modified login.xhtml or authorize.xhtml or error.xhtml or logout.xhtml under /opt/jans/jetty/jans-auth/custom/pages/", "title": "To override default pages listed above:"}, {"location": "janssen-server/kubernetes-ops/customization/#directory-structure-for-customization", "text": "/opt/jans/jetty/jans-auth/ |-- custom | |-- i18n (resource bundles) | |-- libs (library files used by custom script) | |-- pages (web pages) | |-- static (images and css files)", "title": "Directory structure for customization"}, {"location": "janssen-server/kubernetes-ops/customization/#adding-a-new-web-page-for-person-authentication-scripts", "text": "If enterOTP.xhtml is your webpage for step 2 of authentication, place it under /opt/jans/jetty/jans-auth/custom/pages/auth/enterOTP.xhtml Reference it in the custom script as follows: def getPageForStep(self, configurationAttributes, step): # Used to specify the page you want to return for a given step if (step == 1): return \"/auth/login.xhtml\" if (step == 2) return \"/auth/enterOTP.xhtml\"", "title": "Adding a new web page for Person Authentication scripts"}, {"location": "janssen-server/kubernetes-ops/customization/#reference-login-pages", "text": "Here you will find several login pages for different authentication methods.", "title": "Reference login pages"}, {"location": "janssen-server/kubernetes-ops/customization/#customized-resource-bundles", "text": "Resource bundles that are present in the jans-auth.war are present in this folder To override the defaults, custom .properties files should be placed in the following file under this path : /opt/jans/jetty/jans-auth/custom/i18n/jans-auth.properties Resource bundle names to support other languages should be placed under the same folder /opt/jans/jetty/jans-auth/custom/i18n/ . Some examples of file names are : jans-auth_en.properties jans-auth_bg.properties jans-auth_de.properties jans-auth_es.properties jans-auth_fr.properties jans-auth_it.properties jans-auth_ru.properties jans-auth_tr.properties To add translation for a language that is not yet supported, create new properties file in resource folder and name it jans-auth_[language_code].properties, then add language code as supported-locale to the faces-config.xml present in the same folder.", "title": "Customized resource bundles"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-css-files", "text": "Place the file in /opt/jans/jetty/jans-auth/custom/static/stylesheet/theme.css Reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/stylesheet/theme.css or /jans-auth/ext/resources/stylesheet/theme.css", "title": "Custom CSS files"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-image-files", "text": "All images should be placed under /opt/jans/jetty/jans-auth/custom/static/img Reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/img/fileName.png or /jans-auth/ext/resources/img/fileName.jpg", "title": "Custom image files"}, {"location": "janssen-server/kubernetes-ops/customization/#page-layout-header-footer-xhtml-template-customization", "text": "Templates refers to the common interface layout and style. For example, a banner, logo in common header and copyright information in footer. All templates should be placed under /opt/jans/jetty/jans-auth/custom/pages/WEB-INF/incl/layout/ Place a modified template.xhtml in the above location which will override the default template file from the war", "title": "Page layout, header, footer (xhtml Template) customization"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-jar-file-for-scripts", "text": "", "title": "Custom Jar file for scripts"}, {"location": "janssen-server/kubernetes-ops/customization/#for-jars-less-than-1mb", "text": "Create a configmap with the custom jar file: kubectl -n <namespace> create cm my-custom-jar --from-file=mycustom.jar Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts auth-server: volumeMounts: - name: my-custom-jar-volume mountPath: /opt/jans/jetty/jans-auth/custom/libs/mycustom.jar subPath: mycustom.jar volumes: - name: my-custom-jar-volume configMap: name: my-custom-jar Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x", "title": "for JARs less than 1MB"}, {"location": "janssen-server/kubernetes-ops/customization/#for-jars-greater-than-1mb", "text": "Create a configmap or secret for a shell script that contains instructions to pull the custom jar file: #!/bin/sh # This script will pull the custom jar file from a remote location # and place it in the correct location for the Jans Auth server to use it wget -O /opt/jans/jetty/jans-auth/custom/libs/mycustom.jar https://mydomain.com/mycustom.jar kubectl -n <namespace> create cm my-custom-jar --from-file=mycustomjar.sh Mount the configmap or secret in your values.yaml under auth-server.volumes and auth-server.volumeMounts auth-server: volumeMounts: - name: my-custom-jar-volume mountPath: /tmp/mycustomjar.sh subPath: mycustomjar.sh volumes: - name: my-custom-jar-volume configMap: name: my-custom-jar defaultMode: 0755 customScripts: - /tmp/mycustomjar.sh Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x", "title": "For JARs greater than 1MB"}, {"location": "janssen-server/kubernetes-ops/customization/#customized-pages-examples", "text": "", "title": "Customized pages examples"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-login-page", "text": "This guide will demonstrate how to customize the html and css of the default login page. Here's a screenshot of the default login page. As an example, we will add text to the top of the form and change the color of the button using the following steps: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the login.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/login.xhtml login.xhtml Modify the file locally: < h:form id = \"loginForm\" class = \"bg-highlight position-relative d-flex flex-column align-items-center justify-content-center\" style = \"height: 100vh; gap: 2rem\" > <!-- customization --> < div class = \"row\" >< p id = \"creds-title\" > Enter Credentials </ p ></ div > <!-- end of customization --> Get the login-template.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/WEB-INF/incl/layout/login-template.xhtml login-template.xhtml Modify the file locally: < h:head > < link type = \"text/css\" rel = \"stylesheet\" href = \"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" /> <!-- customization --> < link rel = \"stylesheet\" href = \"/jans-auth/ext/resources/stylesheet/custom.css\" /> <!-- end of customization --> </ h:head > Copy the following text and save it as custom.css : # creds-title { font-style : italic ; font-weight : bolder ; color : white ; font-size : 2 em ; } Create configmaps to store the content of login.xhtml , login-template.xhtml and custom.css . kubectl -n <namespace> create cm auth-server-custom-html --from-file = login.xhtml kubectl -n <namespace> create cm auth-server-custom-layout-html --from-file = login-template.xhtml kubectl -n <namespace> create cm auth-server-custom-css --from-file = custom.css Mount the configmaps in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : auth-server-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # login.xthml will be mounted under this directory - name : auth-server-layout-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages/WEB-INF/incl/layout # login-template.xthml will be mounted under this directory - name : auth-server-static-volume mountPath : /tmp/static #custom.css will be mounted in the temporary location lifecycle : postStart : exec : command : [ \"sh\" , \"-c\" , \"mkdir /opt/jans/jetty/jans-auth/custom/static/stylesheet/ && cp /tmp/static/custom.css /opt/jans/jetty/jans-auth/custom/static/stylesheet/\" ] # custom.css will be copied from the temporary to the desired location volumes : - name : auth-server-pages-volume configMap : name : auth-server-custom-html - name : auth-server-layout-volume configMap : name : auth-server-custom-layout-html - name : auth-server-static-volume configMap : name : auth-server-custom-css Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized login page.", "title": "Custom Login page"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-device-code-page", "text": "This guide will demonstrate how to customize the html and css of the device-code page. Here's a screenshot of the device-code page. As an example, we will change the color of the button to blue using the following steps: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the device_authorization.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/device_authorization.xhtml device_authorization.xhtml Modify the file locally: < div class = \"device-authz-button\" > < div style = \"width: 100%\" > <!-- customization --> < div style = \"text-align: center;\" > < h:commandButton id = \"continueButton\" style = \"background-color: red; color: white;\" value = \"#{msgs['device.authorization.confirm.button']}\" iconAwesome = \"fa-sign-in\" > < f:ajax execute = \"@form\" render = \"@form messages\" listener = \"#{deviceAuthorizationAction.processUserCodeVerification}\" /> </ h:commandButton > </ div > <!-- end of customization --> Create a configmap to store the content of device_authorization.xhtml . kubectl -n <namespace> create cm device-code-custom-html --from-file = device_authorization.xhtml Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : device-code-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # device_authorization.xthml will be mounted under this directory volumes : - name : device-code-pages-volume configMap : name : device-code-custom-html Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized device-code page.", "title": "Custom Device-code page"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-error-page", "text": "This guide will demonstrate how to customize the html and css of the error page. Here's a screenshot of the default Error page. As an example, we will change the color of the text at the top of the error page: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the error.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/error.xhtml error.xhtml Modify the file locally: < div class = \"section\" > <!-- customization --> < h1 style = \"color: red; font-size: 3em; font-weight: bold; font-family: Arial\" > OOPS </ h1 > <!-- end of customization --> </ div > Create a configmap to store the content of error.xhtml . kubectl -n <namespace> create cm error-custom-html --from-file = error.xhtml Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : error-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # error.xthml will be mounted under this directory volumes : - name : error-pages-volume configMap : name : error-custom-html Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized error page.", "title": "Custom Error page"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/", "text": "Overview # This guide shows how to store and retrieve jans configmaps and secrets externally in AWS Secrets Manager , GCP Secret Manager and Vault . Note Configmaps and Secrets are stored as a collection of key-value pairs. A secret in AWS/GCP Secret Manager has a max size of 65536 bytes. So the collection of key-value pairs is splitted between secrets, and thus note that during secrets retrieval it's possible that a single key-value pair is to be splitted between 2 AWS/GCP secrets. Create Secrets # AWS # There are 2 types of Secrets in AWS: String Secret where the secret can be created and retrieved from the console. Binary Secret where the secret is binary-encoded and can be created and retrieved only using the CLI/SDK. Configmaps are stored in a single String Secret . It follows the naming convention of janssen_configs Secrets are splitted and stored in multiple Binary Secrets due to the max size limitation. Secrets follows the naming convention of janssen_secrets , janssen_secrets_1 , janssen_secrets_2 ..etc Every single secret doesn't have to be a valid json, but instead the collection of all secrets should have a valid json. For example: janssen_secrets : {\"key1\":\"value1\", janssen_secrets_1 : \"key2\":\"value2\", janssen_secrets_2 : \"key3\":\"value3\"} Fresh Installation # You will need the ACCESS_KEY_ID and SECRET_ACCESS_KEY of an IAM user with a SecretsManagerReadWrite policy attached. Add the following configuration to your override.yaml : global : configAdapterName : aws configSecretAdapter : aws config : configmap : cnAwsAccessKeyId : L30E10OME18S1220S221 cnAwsSecretAccessKey : Z1A1M9A1L1EKALIeHHN~o cnAwsDefaultRegion : us-east-1 #Choose based on the desired region cnAwsSecretsEndpointUrl : https://secretsmanager.us-east-1.amazonaws.com #Choose based on the desired region cnAwsSecretsNamePrefix : janssen cnAwsProfile : janssen #Choose based on your aws named profile cnAwsSecretsReplicaRegions : [] #Optional if you want secrets to be replicated. [{\"Region\": \"us-west-1\"}, {\"Region\": \"us-west-2\"}] Run helm install or helm upgrade if Janssen is already installed: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> Export/Migration # Configmaps # Get the json of the configmap kubectl get configmap -n <namespace> cn -o json Configmaps in AWS are stored as StringSecret , they can be created and retrieved from the console: Click Create Secret > Choose Other type of Secret > Click on Plaintext tab > Paste the json of the key-value pairs. Secrets # Get the json of the secret kubectl get secret -n <namespace> cn -o json Secrets in AWS are splitted across multiple BinarySecrets which is created and retrieved using the CLI/SDK Assuming the json is stored in a file named binary-secrets.json : aws secretsmanager create-secret --name <secret-name> --secret-binary fileb://binary-secrets.json --region <secret-region> GCP # Fresh Installation # Make sure you enabled Secret Manager API . You will need a Service account with the roles/secretmanager.admin role. This service account json should then be base64 encoded. Add the following configuration to your override.yaml : global : configAdapterName : google configSecretAdapter : google config : configmap : cnGoogleSecretManagerServiceAccount : SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo= #base64 encoded service account json cnGoogleProjectId : google-project-to-save-config-and-secrets-to cnSecretGoogleSecretVersionId : \"latest\" # Secret version to be used for secret configuration. Defaults to latest and should normally always stay that way. cnSecretGoogleSecretNamePrefix : janssen cnGoogleSecretManagerPassPhrase : Test1234# #Passphrase for Janssen secret in Google Secret Manager. Used for encrypting and decrypting data from Google's Secret Manager. cnConfigGoogleSecretVersionId : \"latest\" #Secret version to be used for configuration. Defaults to latest and should normally always stay that way. cnConfigGoogleSecretNamePrefix : janssen Run helm install or helm upgrade if Janssen is already installed: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> Export/Migration # Get the json of the secret/configmap kubectl get configmap -n <namespace> cn -o json From the console, Go to Secret Manager > Click on Create Secret > Add a name > Upload a json file or add the json to the Secret value field > Create Managing Versions # While there's no limitation on how many versions a secret can have, the recommendation is to keep the number as low as possible, e.g. 5 active versions. If there are too many secret versions, it's best to destroy older versions manually, for example: gcloud secrets versions list jans-secret --filter = \"state = enabled\" --filter = \"createTime < '2024-03-02'\" | grep \"NAME:\" | tr -d \"NAME: \" > versions_to_destroy.txt while read -r line ; do gcloud secrets versions destroy \" $line \" --secret = jans-secret done < \"versions_to_destroy.txt\" Vault # Note The deployment of Vault is hosted on-premises, not within the HashiCorp Cloud Platform service Enable the KV secrets engine version 1 in Vault. For example: vault secrets enable -path=secret -version=1 kv Note that the path i.e. secret will be mapped to cnVaultKvPath later. Create a policy , which will be attached later to the appRole . Create first a file named policy.hcl with the required capabilities. path \"secret/<name>/*\" { capabilities = [\"create\", \"list\", \"read\", \"delete\", \"update\"] } Note that <name> will be mapped to cnVaultPrefix later. Create the policy: vault policy write <name> /path/to/policy.hcl Enable and configure appRole . You have also to reference the previously created policy. For example: vault auth enable -path=approle approle vault write auth/approle/role/<role-name> token_policies=\"<policy-name>\" The default appRole path is approle which will be mapped to cnVaultAppRolePath later. Add the following configuration to your override.yaml : global : configSecretAdapter : vault config : configmap : # -- Vault AppRole RoleID. cnVaultRoleId : \"\" # -- Vault AppRole SecretID. cnVaultSecretId : \"\" # -- Base URL of Vault. cnVaultAddr : http://localhost:8200 # -- Verify connection to Vault. cnVaultVerify : false # -- Path to file contains Vault AppRole role ID. cnVaultRoleIdFile : /etc/certs/vault_role_id # -- Path to file contains Vault AppRole secret ID. cnVaultSecretIdFile : /etc/certs/vault_secret_id # -- Vault namespace used to access the secrets. cnVaultNamespace : \"\" # -- Path to Vault KV secrets engine. cnVaultKvPath : secret # -- Base prefix name used to access secrets. cnVaultPrefix : jans # -- Path to Vault AppRole. cnVaultAppRolePath : approle 5. Run helm install or helm upgrade Retrieve Secrets # AWS # String Secret : To retrieve the secret value from the Console, click on the secret name and then click on Retrieve Secret Value Binary Secret : To retrieve the secret value using the cli aws secretsmanager get-secret-value --secret-id <secret-name> --query 'SecretBinary' --output text --region <secret-region> Note that the secret is binary encoded, so in order to have a decoded value, you can run the following aws secretsmanager get-secret-value --secret-id <secret-name> --query 'SecretBinary' --output text --region <secret-region> | base64 --decode Repeat these commands across all the secrets, to get the full key-value pairs. GCP # Review this to check multiple ways to retrieve secrets stored in GCP Secret Manager.", "title": "External Secrets and Configmaps"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#overview", "text": "This guide shows how to store and retrieve jans configmaps and secrets externally in AWS Secrets Manager , GCP Secret Manager and Vault . Note Configmaps and Secrets are stored as a collection of key-value pairs. A secret in AWS/GCP Secret Manager has a max size of 65536 bytes. So the collection of key-value pairs is splitted between secrets, and thus note that during secrets retrieval it's possible that a single key-value pair is to be splitted between 2 AWS/GCP secrets.", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#create-secrets", "text": "", "title": "Create Secrets"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#aws", "text": "There are 2 types of Secrets in AWS: String Secret where the secret can be created and retrieved from the console. Binary Secret where the secret is binary-encoded and can be created and retrieved only using the CLI/SDK. Configmaps are stored in a single String Secret . It follows the naming convention of janssen_configs Secrets are splitted and stored in multiple Binary Secrets due to the max size limitation. Secrets follows the naming convention of janssen_secrets , janssen_secrets_1 , janssen_secrets_2 ..etc Every single secret doesn't have to be a valid json, but instead the collection of all secrets should have a valid json. For example: janssen_secrets : {\"key1\":\"value1\", janssen_secrets_1 : \"key2\":\"value2\", janssen_secrets_2 : \"key3\":\"value3\"}", "title": "AWS"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#fresh-installation", "text": "You will need the ACCESS_KEY_ID and SECRET_ACCESS_KEY of an IAM user with a SecretsManagerReadWrite policy attached. Add the following configuration to your override.yaml : global : configAdapterName : aws configSecretAdapter : aws config : configmap : cnAwsAccessKeyId : L30E10OME18S1220S221 cnAwsSecretAccessKey : Z1A1M9A1L1EKALIeHHN~o cnAwsDefaultRegion : us-east-1 #Choose based on the desired region cnAwsSecretsEndpointUrl : https://secretsmanager.us-east-1.amazonaws.com #Choose based on the desired region cnAwsSecretsNamePrefix : janssen cnAwsProfile : janssen #Choose based on your aws named profile cnAwsSecretsReplicaRegions : [] #Optional if you want secrets to be replicated. [{\"Region\": \"us-west-1\"}, {\"Region\": \"us-west-2\"}] Run helm install or helm upgrade if Janssen is already installed: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace>", "title": "Fresh Installation"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#exportmigration", "text": "", "title": "Export/Migration"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#configmaps", "text": "Get the json of the configmap kubectl get configmap -n <namespace> cn -o json Configmaps in AWS are stored as StringSecret , they can be created and retrieved from the console: Click Create Secret > Choose Other type of Secret > Click on Plaintext tab > Paste the json of the key-value pairs.", "title": "Configmaps"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#secrets", "text": "Get the json of the secret kubectl get secret -n <namespace> cn -o json Secrets in AWS are splitted across multiple BinarySecrets which is created and retrieved using the CLI/SDK Assuming the json is stored in a file named binary-secrets.json : aws secretsmanager create-secret --name <secret-name> --secret-binary fileb://binary-secrets.json --region <secret-region>", "title": "Secrets"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#gcp", "text": "", "title": "GCP"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#fresh-installation_1", "text": "Make sure you enabled Secret Manager API . You will need a Service account with the roles/secretmanager.admin role. This service account json should then be base64 encoded. Add the following configuration to your override.yaml : global : configAdapterName : google configSecretAdapter : google config : configmap : cnGoogleSecretManagerServiceAccount : SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo= #base64 encoded service account json cnGoogleProjectId : google-project-to-save-config-and-secrets-to cnSecretGoogleSecretVersionId : \"latest\" # Secret version to be used for secret configuration. Defaults to latest and should normally always stay that way. cnSecretGoogleSecretNamePrefix : janssen cnGoogleSecretManagerPassPhrase : Test1234# #Passphrase for Janssen secret in Google Secret Manager. Used for encrypting and decrypting data from Google's Secret Manager. cnConfigGoogleSecretVersionId : \"latest\" #Secret version to be used for configuration. Defaults to latest and should normally always stay that way. cnConfigGoogleSecretNamePrefix : janssen Run helm install or helm upgrade if Janssen is already installed: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace>", "title": "Fresh Installation"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#exportmigration_1", "text": "Get the json of the secret/configmap kubectl get configmap -n <namespace> cn -o json From the console, Go to Secret Manager > Click on Create Secret > Add a name > Upload a json file or add the json to the Secret value field > Create", "title": "Export/Migration"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#managing-versions", "text": "While there's no limitation on how many versions a secret can have, the recommendation is to keep the number as low as possible, e.g. 5 active versions. If there are too many secret versions, it's best to destroy older versions manually, for example: gcloud secrets versions list jans-secret --filter = \"state = enabled\" --filter = \"createTime < '2024-03-02'\" | grep \"NAME:\" | tr -d \"NAME: \" > versions_to_destroy.txt while read -r line ; do gcloud secrets versions destroy \" $line \" --secret = jans-secret done < \"versions_to_destroy.txt\"", "title": "Managing Versions"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#vault", "text": "Note The deployment of Vault is hosted on-premises, not within the HashiCorp Cloud Platform service Enable the KV secrets engine version 1 in Vault. For example: vault secrets enable -path=secret -version=1 kv Note that the path i.e. secret will be mapped to cnVaultKvPath later. Create a policy , which will be attached later to the appRole . Create first a file named policy.hcl with the required capabilities. path \"secret/<name>/*\" { capabilities = [\"create\", \"list\", \"read\", \"delete\", \"update\"] } Note that <name> will be mapped to cnVaultPrefix later. Create the policy: vault policy write <name> /path/to/policy.hcl Enable and configure appRole . You have also to reference the previously created policy. For example: vault auth enable -path=approle approle vault write auth/approle/role/<role-name> token_policies=\"<policy-name>\" The default appRole path is approle which will be mapped to cnVaultAppRolePath later. Add the following configuration to your override.yaml : global : configSecretAdapter : vault config : configmap : # -- Vault AppRole RoleID. cnVaultRoleId : \"\" # -- Vault AppRole SecretID. cnVaultSecretId : \"\" # -- Base URL of Vault. cnVaultAddr : http://localhost:8200 # -- Verify connection to Vault. cnVaultVerify : false # -- Path to file contains Vault AppRole role ID. cnVaultRoleIdFile : /etc/certs/vault_role_id # -- Path to file contains Vault AppRole secret ID. cnVaultSecretIdFile : /etc/certs/vault_secret_id # -- Vault namespace used to access the secrets. cnVaultNamespace : \"\" # -- Path to Vault KV secrets engine. cnVaultKvPath : secret # -- Base prefix name used to access secrets. cnVaultPrefix : jans # -- Path to Vault AppRole. cnVaultAppRolePath : approle 5. Run helm install or helm upgrade", "title": "Vault"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#retrieve-secrets", "text": "", "title": "Retrieve Secrets"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#aws_1", "text": "String Secret : To retrieve the secret value from the Console, click on the secret name and then click on Retrieve Secret Value Binary Secret : To retrieve the secret value using the cli aws secretsmanager get-secret-value --secret-id <secret-name> --query 'SecretBinary' --output text --region <secret-region> Note that the secret is binary encoded, so in order to have a decoded value, you can run the following aws secretsmanager get-secret-value --secret-id <secret-name> --query 'SecretBinary' --output text --region <secret-region> | base64 --decode Repeat these commands across all the secrets, to get the full key-value pairs.", "title": "AWS"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#gcp_1", "text": "Review this to check multiple ways to retrieve secrets stored in GCP Secret Manager.", "title": "GCP"}, {"location": "janssen-server/kubernetes-ops/health-check/", "tags": ["administration", "kubernetes", "operations", "health-checks"], "text": "Overview # Health checks are used to determine if a container is working as it should or not. This is done in Kubernetes using probes. Jans deployed components uses two types of probes: Readiness probes : used to know when a container is ready to start accepting traffic Liveness probes : used to know when to restart a container Jans Liveness and Readiness probes # Here is a list of the liveness and readiness probes of the deployed jans components auth-server # Auth-sever executes the python3 healthcheck.py in liveness and readiness probes. This python scripts parses the healthcheck endpoint to make sure the status is up. livenessProbe : # Executes the python3 healthcheck. exec : command : - python3 - /app/scripts/healthcheck.py # Configure the liveness healthcheck for the auth-server if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : # Executes the python3 healthcheck. exec : command : - python3 - /app/scripts/healthcheck.py # Configure the readiness healthcheck for the auth-server if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5 config-api # The health check of liveness and readiness probes is a HTTP GET request against a config-api endpoint livenessProbe : # http liveness probe endpoint httpGet : path : /jans-config-api/api/v1/health/live port : 8074 # Configure the liveness healthcheck for the config-api if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : # http readiness probe endpoint httpGet : path : jans-config-api/api/v1/health/ready port : 8074 # Configure the readiness healthcheck for the config-api if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5 fido2 # The health check of liveness and readiness probes is a HTTP GET request against a fido2 endpoint livenessProbe : # http liveness probe endpoint httpGet : path : /jans-fido2/sys/health-check port : http-fido2 # Configure the liveness healthcheck for the fido2 if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5 readinessProbe : # http readiness probe endpoint httpGet : path : /jans-fido2/sys/health-check port : http-fido2 # Configure the readiness healthcheck for the fido2 if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 scim # The health check of liveness and readiness probes is a HTTP GET request against a scim endpoint livenessProbe : httpGet : # http liveness probe endpoint path : /jans-scim/sys/health-check port : 8080 # Configure the liveness healthcheck for the SCIM if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : httpGet : # http readiness probe endpoint path : /jans-scim/sys/health-check port : 8080 # Configure the readiness healthcheck for the SCIM if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5", "title": "Health Check"}, {"location": "janssen-server/kubernetes-ops/health-check/#overview", "text": "Health checks are used to determine if a container is working as it should or not. This is done in Kubernetes using probes. Jans deployed components uses two types of probes: Readiness probes : used to know when a container is ready to start accepting traffic Liveness probes : used to know when to restart a container", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/health-check/#jans-liveness-and-readiness-probes", "text": "Here is a list of the liveness and readiness probes of the deployed jans components", "title": "Jans Liveness and Readiness probes"}, {"location": "janssen-server/kubernetes-ops/health-check/#auth-server", "text": "Auth-sever executes the python3 healthcheck.py in liveness and readiness probes. This python scripts parses the healthcheck endpoint to make sure the status is up. livenessProbe : # Executes the python3 healthcheck. exec : command : - python3 - /app/scripts/healthcheck.py # Configure the liveness healthcheck for the auth-server if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : # Executes the python3 healthcheck. exec : command : - python3 - /app/scripts/healthcheck.py # Configure the readiness healthcheck for the auth-server if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5", "title": "auth-server"}, {"location": "janssen-server/kubernetes-ops/health-check/#config-api", "text": "The health check of liveness and readiness probes is a HTTP GET request against a config-api endpoint livenessProbe : # http liveness probe endpoint httpGet : path : /jans-config-api/api/v1/health/live port : 8074 # Configure the liveness healthcheck for the config-api if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : # http readiness probe endpoint httpGet : path : jans-config-api/api/v1/health/ready port : 8074 # Configure the readiness healthcheck for the config-api if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5", "title": "config-api"}, {"location": "janssen-server/kubernetes-ops/health-check/#fido2", "text": "The health check of liveness and readiness probes is a HTTP GET request against a fido2 endpoint livenessProbe : # http liveness probe endpoint httpGet : path : /jans-fido2/sys/health-check port : http-fido2 # Configure the liveness healthcheck for the fido2 if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5 readinessProbe : # http readiness probe endpoint httpGet : path : /jans-fido2/sys/health-check port : http-fido2 # Configure the readiness healthcheck for the fido2 if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5", "title": "fido2"}, {"location": "janssen-server/kubernetes-ops/health-check/#scim", "text": "The health check of liveness and readiness probes is a HTTP GET request against a scim endpoint livenessProbe : httpGet : # http liveness probe endpoint path : /jans-scim/sys/health-check port : 8080 # Configure the liveness healthcheck for the SCIM if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : httpGet : # http readiness probe endpoint path : /jans-scim/sys/health-check port : 8080 # Configure the readiness healthcheck for the SCIM if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5", "title": "scim"}, {"location": "janssen-server/kubernetes-ops/jans-saml/", "tags": ["administration", "kubernetes", "operations", "jans-saml", "keycloak"], "text": "Overview # Jans-SAML/Keycloak has the flexibility to be deployed using either MySQL or PostgreSQL as its backend. MySQL # Make the following changes in your values.yaml : global : saml : enabled : true ingress : samlEnabled : true config : configmap : kcDbVendor : mysql kcDbUsername : keycloak kcDbPassword : Test1234# kcDbSchema : keycloak kcDbUrlHost : mysql.kc.svc.cluster.local kcDbUrlPort : 3306 kcDbUrlDatabase : keycloak If you provide a non-root MySQL user to Keycloak, you will encounter the following error and warnings: SQLException: XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency WARNING - jans-saml - 2024-02-05 16:54:04,256 - Unable to grant XA_RECOVER_ADMIN privilege to 'keycloak' user; reason=Access denied; you need (at least one of) the GRANT OPTION privilege(s) for this operation WARNING - jans-saml - 2024-02-05 16:54:04,256 - Got insufficient permission, please try using user with XA_RECOVER_ADMIN privilege and running the following query manually via MySQL client: \"GRANT XA_RECOVER_ADMIN ON *.* TO 'keycloak'@'%'; FLUSH PRIVILEGES;\" To resolve this issue, it's necessary to adhere to the guidance provided in the logs. PostgreSQL # Make the following changes in your values.yaml : global : saml : enabled : true ingress : samlEnabled : true config : configmap : kcDbVendor : postgres kcDbUsername : keycloak kcDbPassword : Test1234# kcDbSchema : public kcDbUrlHost : postgres.kc.svc.cluster.local kcDbUrlPort : 5432 kcDbUrlDatabase : keycloak kcDbUrlProperties : \"\"", "title": "Jans SAML/Keycloak"}, {"location": "janssen-server/kubernetes-ops/jans-saml/#overview", "text": "Jans-SAML/Keycloak has the flexibility to be deployed using either MySQL or PostgreSQL as its backend.", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/jans-saml/#mysql", "text": "Make the following changes in your values.yaml : global : saml : enabled : true ingress : samlEnabled : true config : configmap : kcDbVendor : mysql kcDbUsername : keycloak kcDbPassword : Test1234# kcDbSchema : keycloak kcDbUrlHost : mysql.kc.svc.cluster.local kcDbUrlPort : 3306 kcDbUrlDatabase : keycloak If you provide a non-root MySQL user to Keycloak, you will encounter the following error and warnings: SQLException: XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency WARNING - jans-saml - 2024-02-05 16:54:04,256 - Unable to grant XA_RECOVER_ADMIN privilege to 'keycloak' user; reason=Access denied; you need (at least one of) the GRANT OPTION privilege(s) for this operation WARNING - jans-saml - 2024-02-05 16:54:04,256 - Got insufficient permission, please try using user with XA_RECOVER_ADMIN privilege and running the following query manually via MySQL client: \"GRANT XA_RECOVER_ADMIN ON *.* TO 'keycloak'@'%'; FLUSH PRIVILEGES;\" To resolve this issue, it's necessary to adhere to the guidance provided in the logs.", "title": "MySQL"}, {"location": "janssen-server/kubernetes-ops/jans-saml/#postgresql", "text": "Make the following changes in your values.yaml : global : saml : enabled : true ingress : samlEnabled : true config : configmap : kcDbVendor : postgres kcDbUsername : keycloak kcDbPassword : Test1234# kcDbSchema : public kcDbUrlHost : postgres.kc.svc.cluster.local kcDbUrlPort : 5432 kcDbUrlDatabase : keycloak kcDbUrlProperties : \"\"", "title": "PostgreSQL"}, {"location": "janssen-server/kubernetes-ops/logs/", "tags": ["administration", "kubernetes", "operations", "logs"], "text": "Overview # The Janssen logs can be viewed using the following command: kubectl logs <pod-name> -n <namespace> Log Levels # The following log levels can be configured through the configuration CLI: Log Level Messages Logged Trace All messages Debug Debug level and above Info Informational level and above Warn Warning level and above Error Error level and above Fatal Only fatal errors Off Logging is disabled Configuring Log Levels # To get the current log level of any component, run the following command: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_<service-name>_APP_LOGGERS auth-server # To get the current log level of auth-server: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_AUTH_APP_LOGGERS Example output: CN_AUTH_APP_LOGGERS : '{ \"audit_log_level\":\"INFO\", \"audit_log_target\":\"FILE\", \"auth_log_level\":\"INFO\", \"auth_log_target\":\"STDOUT\", \"http_log_level\":\"INFO\", \"http_log_target\":\"FILE\", \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in auth-server, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : auth-server : appLoggers : authLogLevel : \"TRACE\" httpLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" auditStatsLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of auth-server: kubectl logs -f deployment/<helm-release-name>-auth-server -n <namespace> config-api # To get the current log level of config-api: kubectl get configmap -n <namspace> <helm-release-name>-config-cm -o yaml | grep CN_CONFIG_API_APP_LOGGERS Example output: CN_CONFIG_API_APP_LOGGERS : '{ \"config_api_log_level\":\"INFO\", \"config_api_log_target\":\"STDOUT\", \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in config-api, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : config-api : appLoggers : configApiLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of config-api: kubectl logs -f deployment/<helm-release-name>-config-api -n <namespace> fido2 # To get the current log level of fido2: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_FIDO2_APP_LOGGERS Example output: CN_FIDO2_APP_LOGGERS : '{ \"fido2_log_level\":\"INFO\", \"fido2_log_target\":\"STDOUT\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\" }' To override the current logging level in fido2, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : fido2 : appLoggers : fido2LogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of fido2: kubectl logs -f deployment/<helm-release-name>-fido2 -n <namespace> scim # To get the current log level of scim: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_SCIM_APP_LOGGERS Example output: CN_SCIM_APP_LOGGERS : '{ \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"scim_log_level\":\"INFO\", \"scim_log_target\":\"STDOUT\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in scim, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : scim : appLoggers : scimLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of scim: kubectl logs -f deployment/<helm-release-name>-scim -n <namespace> Hack it # Warning This can cause deployments to break, but if you wish you may edit it directly and restart the wanted deployment Edit using the following command: kubectl edit configmap <helm-release-name>-config-cm -n <namespace> Restart the wanted deployment: kubectl rollout restart deployment <deployment-name> -n <namespace>", "title": "Logs"}, {"location": "janssen-server/kubernetes-ops/logs/#overview", "text": "The Janssen logs can be viewed using the following command: kubectl logs <pod-name> -n <namespace>", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/logs/#log-levels", "text": "The following log levels can be configured through the configuration CLI: Log Level Messages Logged Trace All messages Debug Debug level and above Info Informational level and above Warn Warning level and above Error Error level and above Fatal Only fatal errors Off Logging is disabled", "title": "Log Levels"}, {"location": "janssen-server/kubernetes-ops/logs/#configuring-log-levels", "text": "To get the current log level of any component, run the following command: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_<service-name>_APP_LOGGERS", "title": "Configuring Log Levels"}, {"location": "janssen-server/kubernetes-ops/logs/#auth-server", "text": "To get the current log level of auth-server: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_AUTH_APP_LOGGERS Example output: CN_AUTH_APP_LOGGERS : '{ \"audit_log_level\":\"INFO\", \"audit_log_target\":\"FILE\", \"auth_log_level\":\"INFO\", \"auth_log_target\":\"STDOUT\", \"http_log_level\":\"INFO\", \"http_log_target\":\"FILE\", \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in auth-server, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : auth-server : appLoggers : authLogLevel : \"TRACE\" httpLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" auditStatsLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of auth-server: kubectl logs -f deployment/<helm-release-name>-auth-server -n <namespace>", "title": "auth-server"}, {"location": "janssen-server/kubernetes-ops/logs/#config-api", "text": "To get the current log level of config-api: kubectl get configmap -n <namspace> <helm-release-name>-config-cm -o yaml | grep CN_CONFIG_API_APP_LOGGERS Example output: CN_CONFIG_API_APP_LOGGERS : '{ \"config_api_log_level\":\"INFO\", \"config_api_log_target\":\"STDOUT\", \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in config-api, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : config-api : appLoggers : configApiLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of config-api: kubectl logs -f deployment/<helm-release-name>-config-api -n <namespace>", "title": "config-api"}, {"location": "janssen-server/kubernetes-ops/logs/#fido2", "text": "To get the current log level of fido2: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_FIDO2_APP_LOGGERS Example output: CN_FIDO2_APP_LOGGERS : '{ \"fido2_log_level\":\"INFO\", \"fido2_log_target\":\"STDOUT\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\" }' To override the current logging level in fido2, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : fido2 : appLoggers : fido2LogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of fido2: kubectl logs -f deployment/<helm-release-name>-fido2 -n <namespace>", "title": "fido2"}, {"location": "janssen-server/kubernetes-ops/logs/#scim", "text": "To get the current log level of scim: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_SCIM_APP_LOGGERS Example output: CN_SCIM_APP_LOGGERS : '{ \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"scim_log_level\":\"INFO\", \"scim_log_target\":\"STDOUT\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in scim, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : scim : appLoggers : scimLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of scim: kubectl logs -f deployment/<helm-release-name>-scim -n <namespace>", "title": "scim"}, {"location": "janssen-server/kubernetes-ops/logs/#hack-it", "text": "Warning This can cause deployments to break, but if you wish you may edit it directly and restart the wanted deployment Edit using the following command: kubectl edit configmap <helm-release-name>-config-cm -n <namespace> Restart the wanted deployment: kubectl rollout restart deployment <deployment-name> -n <namespace>", "title": "Hack it"}, {"location": "janssen-server/kubernetes-ops/memory-dump/", "tags": ["administration", "kubernetes", "operations", "memory", "dump", "heap"], "text": "Overview # This document will demonstrate how to generate a memory dump so that you can analyze your memory usage. Services supported # This operation can be made in the following Java-based services: Service JAVA_OPTIONS environment variable auth-server CN_AUTH_JAVA_OPTIONS casa CN_CASA_JAVA_OPTIONS config-api CN_CONFIG_API_JAVA_OPTIONS fido2 CN_FIDO2_JAVA_OPTIONS link CN_LINK_JAVA_OPTIONS saml CN_SAML_JAVA_OPTIONS scim CN_SCIM_JAVA_OPTIONS Steps # Let's go through the steps needed to generate a dump in config-api : Increase the pod's memory request and limit to something larger than the default. Edit the config-api deployment and modify the JAVA_OPTIONS: env: - name: CN_CONFIG_API_JAVA_OPTIONS value: -XX:MaxDirectMemorySize=400m -Xmx150m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -XX:MaxRAMPercentage=0 Modify the command key in the deployment to add the following: command: - /bin/sh - -c - | /app/scripts/entrypoint.sh & sleep 900000000 You can view the heap usage using the following command: kubectl exec -n <namespace> pod-name -- jcmd 7 GC.heap_info Now once the process meets its limit, the process should shut down without the pod getting an OOM, allowing you to get the dump from within the pod. Copy the generated dump from the pod: kubectl cp -n <namespace> pod-name:tmp/java_pid7.hprof java_pid7.hprof", "title": "Memory Dump"}, {"location": "janssen-server/kubernetes-ops/memory-dump/#overview", "text": "This document will demonstrate how to generate a memory dump so that you can analyze your memory usage.", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/memory-dump/#services-supported", "text": "This operation can be made in the following Java-based services: Service JAVA_OPTIONS environment variable auth-server CN_AUTH_JAVA_OPTIONS casa CN_CASA_JAVA_OPTIONS config-api CN_CONFIG_API_JAVA_OPTIONS fido2 CN_FIDO2_JAVA_OPTIONS link CN_LINK_JAVA_OPTIONS saml CN_SAML_JAVA_OPTIONS scim CN_SCIM_JAVA_OPTIONS", "title": "Services supported"}, {"location": "janssen-server/kubernetes-ops/memory-dump/#steps", "text": "Let's go through the steps needed to generate a dump in config-api : Increase the pod's memory request and limit to something larger than the default. Edit the config-api deployment and modify the JAVA_OPTIONS: env: - name: CN_CONFIG_API_JAVA_OPTIONS value: -XX:MaxDirectMemorySize=400m -Xmx150m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -XX:MaxRAMPercentage=0 Modify the command key in the deployment to add the following: command: - /bin/sh - -c - | /app/scripts/entrypoint.sh & sleep 900000000 You can view the heap usage using the following command: kubectl exec -n <namespace> pod-name -- jcmd 7 GC.heap_info Now once the process meets its limit, the process should shut down without the pod getting an OOM, allowing you to get the dump from within the pod. Copy the generated dump from the pod: kubectl cp -n <namespace> pod-name:tmp/java_pid7.hprof java_pid7.hprof", "title": "Steps"}, {"location": "janssen-server/kubernetes-ops/scaling/", "tags": ["administration", "kubernetes", "operations", "scaling"], "text": "Overview # Scaling is the ability to handle the increase in usage by expanding the existing resources(nodes/pods). Scaling types # Scaling in Kubernetes can be done automatically and manually . Automatic Scaling # Kubernetes has the capability to provision resources automatically in order to match the needed demand. Horizontal Pod Autoscaler (HPA) # HPA automatically resizes the number of pods to match demand. In order for hpa to work, you have to: Install metrics server kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml Define requests for the metric used It is configured and enabled by default in the deployed jans components. The default configuration scales in and out based on the CPU utilization of the pods. <component-name> : hpa : enabled : true minReplicas : 1 maxReplicas : 10 targetCPUUtilizationPercentage : 50 # -- metrics if targetCPUUtilizationPercentage is not set metrics : [] # -- Scaling Policies behavior : {} Cluster Autoscaler # Cluster Autoscaler automatically resizes the number of nodes in a given node pool, based on the demands of your workloads. Cluster Autoscaler is available in AWS , GCP , and Azure . Manual Scaling # Kubernetes also offers the option to manually scale your resources. For example, you can increase manually the pod replicas of auth-server deployment using the following command: kubectl scale --replicas = 3 deployment/auth-server -n <namespace>", "title": "Scaling"}, {"location": "janssen-server/kubernetes-ops/scaling/#overview", "text": "Scaling is the ability to handle the increase in usage by expanding the existing resources(nodes/pods).", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/scaling/#scaling-types", "text": "Scaling in Kubernetes can be done automatically and manually .", "title": "Scaling types"}, {"location": "janssen-server/kubernetes-ops/scaling/#automatic-scaling", "text": "Kubernetes has the capability to provision resources automatically in order to match the needed demand.", "title": "Automatic Scaling"}, {"location": "janssen-server/kubernetes-ops/scaling/#horizontal-pod-autoscaler-hpa", "text": "HPA automatically resizes the number of pods to match demand. In order for hpa to work, you have to: Install metrics server kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml Define requests for the metric used It is configured and enabled by default in the deployed jans components. The default configuration scales in and out based on the CPU utilization of the pods. <component-name> : hpa : enabled : true minReplicas : 1 maxReplicas : 10 targetCPUUtilizationPercentage : 50 # -- metrics if targetCPUUtilizationPercentage is not set metrics : [] # -- Scaling Policies behavior : {}", "title": "Horizontal Pod Autoscaler (HPA)"}, {"location": "janssen-server/kubernetes-ops/scaling/#cluster-autoscaler", "text": "Cluster Autoscaler automatically resizes the number of nodes in a given node pool, based on the demands of your workloads. Cluster Autoscaler is available in AWS , GCP , and Azure .", "title": "Cluster Autoscaler"}, {"location": "janssen-server/kubernetes-ops/scaling/#manual-scaling", "text": "Kubernetes also offers the option to manually scale your resources. For example, you can increase manually the pod replicas of auth-server deployment using the following command: kubectl scale --replicas = 3 deployment/auth-server -n <namespace>", "title": "Manual Scaling"}, {"location": "janssen-server/kubernetes-ops/start-order/", "tags": ["administration", "kubernetes", "operations", "start-order"], "text": "Service Start Order # Network traffic between Jans services # Database Access: all Jans services require access to the database. Pod-2-Pod Communication: Jans services communicate with each other as depicted. External/Internet Communication : Auth-server: should be publically accessible. Rest of the pods: We recommend to only keep the .well-known endpoints public and protect the rest.", "title": "Start Order"}, {"location": "janssen-server/kubernetes-ops/start-order/#service-start-order", "text": "", "title": "Service Start Order"}, {"location": "janssen-server/kubernetes-ops/start-order/#network-traffic-between-jans-services", "text": "Database Access: all Jans services require access to the database. Pod-2-Pod Communication: Jans services communicate with each other as depicted. External/Internet Communication : Auth-server: should be publically accessible. Rest of the pods: We recommend to only keep the .well-known endpoints public and protect the rest.", "title": "Network traffic between Jans services"}, {"location": "janssen-server/kubernetes-ops/tui-k8s/", "tags": ["administration", "kubernetes", "operations", "tui"], "text": "Overview # Using the TUI with a Janssen Kubernetes Setup - Watch Video Installing TUI and connecting to a Kubernetes installation. Download jans-cli-tui from the release assets depending on your OS. For example: wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-cli-tui-linux-ubuntu-X86-64.pyz Now we have jans-cli-tui-linux-ubuntu-X86-64.pyz downloaded. Now we can grab the FQDN, client-id, client-secret, and connect using the following commands: FQDN= #Add your FQDN here TUI_CLIENT_ID=$(kubectl get cm cn -n <namespace> --template={{.data.tui_client_id}}) TUI_CLIENT_SECRET=$(kubectl get secret cn -n <namespace> --template={{.data.tui_client_pw}} | base64 -d) #add -noverify if your FQDN is not registered python3 jans-cli-tui-linux-ubuntu-X86-64.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET", "title": "TUI K8s"}, {"location": "janssen-server/kubernetes-ops/tui-k8s/#overview", "text": "Using the TUI with a Janssen Kubernetes Setup - Watch Video Installing TUI and connecting to a Kubernetes installation. Download jans-cli-tui from the release assets depending on your OS. For example: wget https://github.com/JanssenProject/jans/releases/download/nightly/jans-cli-tui-linux-ubuntu-X86-64.pyz Now we have jans-cli-tui-linux-ubuntu-X86-64.pyz downloaded. Now we can grab the FQDN, client-id, client-secret, and connect using the following commands: FQDN= #Add your FQDN here TUI_CLIENT_ID=$(kubectl get cm cn -n <namespace> --template={{.data.tui_client_id}}) TUI_CLIENT_SECRET=$(kubectl get secret cn -n <namespace> --template={{.data.tui_client_pw}} | base64 -d) #add -noverify if your FQDN is not registered python3 jans-cli-tui-linux-ubuntu-X86-64.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/upgrade/", "tags": ["administration", "kubernetes", "operations", "helm", "upgrade"], "text": "This guide shows how to upgrade a Janssen helm deployment. helm ls -n <namepsace> Keep note of the helm release version Add your changes to override.yaml Apply your upgrade: helm upgrade <janssen-release-name> janssen/janssen -n <namespace> -f override.yaml --version=0.0.0-nightly", "title": "Upgrade"}, {"location": "janssen-server/link/jans-keycloak-link/", "tags": ["administration", "link", "keycloak"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Jans Keycloak Link"}, {"location": "janssen-server/link/jans-keycloak-link/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/link/jans-keycloak-link/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/link/jans-keycloak-link/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/link/jans-link/", "tags": ["administration", "link", "jans-ldap-link"], "text": "Jans LDAP Link # The Jans LDAPLink synchronization service updates the Janssen User Store when authoritative data is managed in an external LDAP store. Installation # The API is available as the Jans Link component of Jans Server. Upon installation you can select if you want to install this Service along with other Janssen Server components. Post installation, to add Jans-Link component, use the following: python3 /opt/jans/jans-setup/setup.py --install-jans-link ` Jans LDAP link gets installed as a service that can be managed using below commands. To Satrt Jans-Link systemctl start jans-link To check status systemctl status jans-link To Stop Jans-Link systemctl stop jans-link Jans LDAP Link Configuration # Using Jans CLI # Janssen Server CLI provides number of operations and metadata information about Jans LDAP link. To see Jans-Link info using Jans CLI /opt/jans/jans-cli/config-cli.py --info JansLinkConfiguration To see Jans Link properties using below command. /opt/jans/jans-cli/config-cli.py --operation-id get-jans-link-properties To see basic schema of Jans-Link use below command /opt/jans/jans-cli/config-cli.py --schema \"Jans Link Plugin:AppConfiguration\" Output of above command will be similar to this: { \"inumConfig\" : { \"configId\" : \"local_inum\" , \"bindDN\" : \"cn=directory manager\" , \"bindPassword\" : \"+iChsQofo6Y=\" , \"servers\" : [ \"localhost:1636\" ], \"maxConnections\" : 10 , \"useSSL\" : true , \"baseDNs\" : [ \"ou=link,o=site\" ], \"useAnonymousBind\" : false , \"enabled\" : true , \"version\" : 0 , \"level\" : 0 }, \"targetConfig\" : { \"maxConnections\" : 2 , \"useSSL\" : false , \"useAnonymousBind\" : false , \"enabled\" : false , \"version\" : 0 , \"level\" : 0 }, \"ldapSearchSizeLimit\" : 1000 , \"keyAttributes\" : [ \"uid\" ], \"keyObjectClasses\" : [ \"gluuPerson\" ], \"sourceAttributes\" : [ \"mail\" , \"cn\" , \"sn\" ], \"updateMethod\" : \"copy\" , \"defaultInumServer\" : true , \"keepExternalPerson\" : true , \"useSearchLimit\" : false , \"attributeMapping\" : [ { \"source\" : \"uid\" , \"destination\" : \"uid\" }, { \"source\" : \"cn\" , \"destination\" : \"cn\" }, { \"source\" : \"sn\" , \"destination\" : \"sn\" } ], \"snapshotFolder\" : \"/var/jans/link-snapshots\" , \"snapshotMaxCount\" : 10 , \"baseDN\" : \"o=jans\" , \"personObjectClassTypes\" : [ \"jansCustomPerson\" , \"jansPerson\" , \"eduPerson\" ], \"personCustomObjectClass\" : \"jansCustomPerson\" , \"allowPersonModification\" : false , \"supportedUserStatus\" : [ \"active\" , \"inactive\" ], \"metricReporterInterval\" : 0 , \"metricReporterKeepDataDays\" : 0 , \"disableJdkLogger\" : true , \"cleanServiceInterval\" : 0 , \"linkEnabled\" : false , \"serverIpAddress\" : \"255.255.255.255\" , \"lastUpdate\" : \"2023-07-05T18:27:28\" , \"lastUpdateCount\" : \"0\" , \"problemCount\" : \"3\" , \"useLocalCache\" : false } Using Jans TUI # Janssen Server TUI provides ability configure Jans LDAP link component with a menu option as shown below: Section below covers Jans LDAP link configuration in more details. Configuration Using TUI # In order to configre Jans LDAP Link, the administrator needs to know various values of the backend LDAP(or Active Directory). For example, host & port , bindDN , user information, password , Objectclasses , attributes which will be pulled, etc. In addition, the administrator needs to know generic information about the Jans Server's LDAP. By default, the deployer can use localhost:1636 , cn=directory manager , password chosen during installation, ou=people,o=site as server information, bindDN , bindDN password and baseDN respectively. Let's move forward with the Jans-Link setup. Enabled : Enable your Jans-link configuration. Refresh Method : There have two refresh mode copy and VDS . If the organization has any kind of Active Directory/LDAP server, they are strongly recommended to use the Copy Method from the drop-down menu. Any organization with a database like mysql can use the VDS method. This option can be enabled via the drop-down menu in Refresh Method option. Mapping : In the source attribute to destination attribute mapping field, you can enter the source attribute value on the left, and the destination attribute on the right. In other words, you can specify what the attribute is on the backend in the left field, and what it should be rendered as when it comes through the Jans Server in the right field. Server IP address : Proviede your server IP address. Polling Interval (minutes) : This is the interval value for running the link mechanism in the Jans Server. It is recommended to be kept higher than 15 minutes. Keep External Persons : Enable it during Jans-Link setup. This will allow your default user 'admin' to log into Jans Server after initial linking iteration. If you do not enable 'Keep External Person', your 'admin' user including all other test users will be gone after first linking iteration. Snapshot Directory : Every cycle of Jans Server link cycle saves an overall snapshot and problem-list record on a specified location. This is where the Jans Server Administrator can specify the location. You can easily decide whether link synchronizes all users or not. Generally the rejected users are enclosed in the problem-list file. Snapshot Count : This defines the total number of snapshots that are allowed to be saved in the hard drive of the VM. It is recommended to be kept to 10 snapshots. Load Source Data withLimited Search Customer Backend Key Attribute Key Attributes : This is the unique key attribute of backend Active Directory/LDAP Server such as MikeAccountname for any Active Directory. Key Object Classes : This contains the Object Classes of the backend Active Directory/LDAP which has permission to talk to Jans Server link such as person, organizationalPerson, user etc. Source Attributes : This contains the list of attributes which will be pulled and read by the Jans Server. Custom LDAP Filter : If there is any custom search required, this filtering mechanism can be used such as \"sn=*\" whereas the value of this field ensures that every user must contain an attribute named SN . Source Backend LDAP Server This section allows the Jans Server to connect to the backend Active Directory/LDAP server of the organization. Add new Source LDAP Config Name : Input source as the value Bind DN : This contains the username to connect to the backend server. You need to use full DN here. As for example, cn=jans , dc=company , dc=org . Bind Password : This is your server password. Max Connections : This value defines the maximum number of connections that are allowed to read the backend Active Directory/LDAP server. It is recommended to keep the value of 2 or 3. Server:Port : provide your server name and port number. Base DNs : This contains the location of the Active Directory/LDAP tree from where the Jans Server shall read the user information. Use SSL : Use this feature if the backend server allows SSL connectivity. Enable : This check-box is used to save and push the changes. Do not use this unless the server administrator has entered all the required values. Inum DB Server This section of the application allows the server administrator to connect to the internal LDAP of the Jans Server. As Jans Server administrator, you do not need to insert anything here in this section as new Gluu Server versions automatically populates this for you (unlessyou try to manually configure it anyway). Things To Remember # The Jans Server supports two LDAP modes: Authentication Identity mapping To synchronize user accounts from an external LDAP directory server, you can use the built-in Jans CLI or Jans TUI features for Service Link, which supports mapping identities from one or more source directory servers. After configuring Jans Link, you should give it some time to run and populate the LDAP server. Here are some tips before you get started: Make sure you are using LDAP authentication Check the snapshots folder to see if files are being created. Use the Jans TUI to browse users. Use the command ldapsearch to check to see if results are starting to come in. The following command will search for the total number of users in the Jans LDAP: /opt/opendj/bin/ldapsearch -h localhost -p 1636 -Z -X -D \"cn=directory manager\" -w <pass> -b \"ou=people,o=DA....,o=jans\" dn | grep \"dn\\:\" | wc -l Try to log in with one of these users. We assume that you have also set up your Jans Server to use the correct LDAP server for authentication. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Jans LDAP Link"}, {"location": "janssen-server/link/jans-link/#jans-ldap-link", "text": "The Jans LDAPLink synchronization service updates the Janssen User Store when authoritative data is managed in an external LDAP store.", "title": "Jans LDAP Link"}, {"location": "janssen-server/link/jans-link/#installation", "text": "The API is available as the Jans Link component of Jans Server. Upon installation you can select if you want to install this Service along with other Janssen Server components. Post installation, to add Jans-Link component, use the following: python3 /opt/jans/jans-setup/setup.py --install-jans-link ` Jans LDAP link gets installed as a service that can be managed using below commands. To Satrt Jans-Link systemctl start jans-link To check status systemctl status jans-link To Stop Jans-Link systemctl stop jans-link", "title": "Installation"}, {"location": "janssen-server/link/jans-link/#jans-ldap-link-configuration", "text": "", "title": "Jans LDAP Link Configuration"}, {"location": "janssen-server/link/jans-link/#using-jans-cli", "text": "Janssen Server CLI provides number of operations and metadata information about Jans LDAP link. To see Jans-Link info using Jans CLI /opt/jans/jans-cli/config-cli.py --info JansLinkConfiguration To see Jans Link properties using below command. /opt/jans/jans-cli/config-cli.py --operation-id get-jans-link-properties To see basic schema of Jans-Link use below command /opt/jans/jans-cli/config-cli.py --schema \"Jans Link Plugin:AppConfiguration\" Output of above command will be similar to this: { \"inumConfig\" : { \"configId\" : \"local_inum\" , \"bindDN\" : \"cn=directory manager\" , \"bindPassword\" : \"+iChsQofo6Y=\" , \"servers\" : [ \"localhost:1636\" ], \"maxConnections\" : 10 , \"useSSL\" : true , \"baseDNs\" : [ \"ou=link,o=site\" ], \"useAnonymousBind\" : false , \"enabled\" : true , \"version\" : 0 , \"level\" : 0 }, \"targetConfig\" : { \"maxConnections\" : 2 , \"useSSL\" : false , \"useAnonymousBind\" : false , \"enabled\" : false , \"version\" : 0 , \"level\" : 0 }, \"ldapSearchSizeLimit\" : 1000 , \"keyAttributes\" : [ \"uid\" ], \"keyObjectClasses\" : [ \"gluuPerson\" ], \"sourceAttributes\" : [ \"mail\" , \"cn\" , \"sn\" ], \"updateMethod\" : \"copy\" , \"defaultInumServer\" : true , \"keepExternalPerson\" : true , \"useSearchLimit\" : false , \"attributeMapping\" : [ { \"source\" : \"uid\" , \"destination\" : \"uid\" }, { \"source\" : \"cn\" , \"destination\" : \"cn\" }, { \"source\" : \"sn\" , \"destination\" : \"sn\" } ], \"snapshotFolder\" : \"/var/jans/link-snapshots\" , \"snapshotMaxCount\" : 10 , \"baseDN\" : \"o=jans\" , \"personObjectClassTypes\" : [ \"jansCustomPerson\" , \"jansPerson\" , \"eduPerson\" ], \"personCustomObjectClass\" : \"jansCustomPerson\" , \"allowPersonModification\" : false , \"supportedUserStatus\" : [ \"active\" , \"inactive\" ], \"metricReporterInterval\" : 0 , \"metricReporterKeepDataDays\" : 0 , \"disableJdkLogger\" : true , \"cleanServiceInterval\" : 0 , \"linkEnabled\" : false , \"serverIpAddress\" : \"255.255.255.255\" , \"lastUpdate\" : \"2023-07-05T18:27:28\" , \"lastUpdateCount\" : \"0\" , \"problemCount\" : \"3\" , \"useLocalCache\" : false }", "title": "Using Jans CLI"}, {"location": "janssen-server/link/jans-link/#using-jans-tui", "text": "Janssen Server TUI provides ability configure Jans LDAP link component with a menu option as shown below: Section below covers Jans LDAP link configuration in more details.", "title": "Using Jans TUI"}, {"location": "janssen-server/link/jans-link/#configuration-using-tui", "text": "In order to configre Jans LDAP Link, the administrator needs to know various values of the backend LDAP(or Active Directory). For example, host & port , bindDN , user information, password , Objectclasses , attributes which will be pulled, etc. In addition, the administrator needs to know generic information about the Jans Server's LDAP. By default, the deployer can use localhost:1636 , cn=directory manager , password chosen during installation, ou=people,o=site as server information, bindDN , bindDN password and baseDN respectively. Let's move forward with the Jans-Link setup. Enabled : Enable your Jans-link configuration. Refresh Method : There have two refresh mode copy and VDS . If the organization has any kind of Active Directory/LDAP server, they are strongly recommended to use the Copy Method from the drop-down menu. Any organization with a database like mysql can use the VDS method. This option can be enabled via the drop-down menu in Refresh Method option. Mapping : In the source attribute to destination attribute mapping field, you can enter the source attribute value on the left, and the destination attribute on the right. In other words, you can specify what the attribute is on the backend in the left field, and what it should be rendered as when it comes through the Jans Server in the right field. Server IP address : Proviede your server IP address. Polling Interval (minutes) : This is the interval value for running the link mechanism in the Jans Server. It is recommended to be kept higher than 15 minutes. Keep External Persons : Enable it during Jans-Link setup. This will allow your default user 'admin' to log into Jans Server after initial linking iteration. If you do not enable 'Keep External Person', your 'admin' user including all other test users will be gone after first linking iteration. Snapshot Directory : Every cycle of Jans Server link cycle saves an overall snapshot and problem-list record on a specified location. This is where the Jans Server Administrator can specify the location. You can easily decide whether link synchronizes all users or not. Generally the rejected users are enclosed in the problem-list file. Snapshot Count : This defines the total number of snapshots that are allowed to be saved in the hard drive of the VM. It is recommended to be kept to 10 snapshots. Load Source Data withLimited Search Customer Backend Key Attribute Key Attributes : This is the unique key attribute of backend Active Directory/LDAP Server such as MikeAccountname for any Active Directory. Key Object Classes : This contains the Object Classes of the backend Active Directory/LDAP which has permission to talk to Jans Server link such as person, organizationalPerson, user etc. Source Attributes : This contains the list of attributes which will be pulled and read by the Jans Server. Custom LDAP Filter : If there is any custom search required, this filtering mechanism can be used such as \"sn=*\" whereas the value of this field ensures that every user must contain an attribute named SN . Source Backend LDAP Server This section allows the Jans Server to connect to the backend Active Directory/LDAP server of the organization. Add new Source LDAP Config Name : Input source as the value Bind DN : This contains the username to connect to the backend server. You need to use full DN here. As for example, cn=jans , dc=company , dc=org . Bind Password : This is your server password. Max Connections : This value defines the maximum number of connections that are allowed to read the backend Active Directory/LDAP server. It is recommended to keep the value of 2 or 3. Server:Port : provide your server name and port number. Base DNs : This contains the location of the Active Directory/LDAP tree from where the Jans Server shall read the user information. Use SSL : Use this feature if the backend server allows SSL connectivity. Enable : This check-box is used to save and push the changes. Do not use this unless the server administrator has entered all the required values. Inum DB Server This section of the application allows the server administrator to connect to the internal LDAP of the Jans Server. As Jans Server administrator, you do not need to insert anything here in this section as new Gluu Server versions automatically populates this for you (unlessyou try to manually configure it anyway).", "title": "Configuration Using TUI"}, {"location": "janssen-server/link/jans-link/#things-to-remember", "text": "The Jans Server supports two LDAP modes: Authentication Identity mapping To synchronize user accounts from an external LDAP directory server, you can use the built-in Jans CLI or Jans TUI features for Service Link, which supports mapping identities from one or more source directory servers. After configuring Jans Link, you should give it some time to run and populate the LDAP server. Here are some tips before you get started: Make sure you are using LDAP authentication Check the snapshots folder to see if files are being created. Use the Jans TUI to browse users. Use the command ldapsearch to check to see if results are starting to come in. The following command will search for the total number of users in the Jans LDAP: /opt/opendj/bin/ldapsearch -h localhost -p 1636 -Z -X -D \"cn=directory manager\" -w <pass> -b \"ou=people,o=DA....,o=jans\" dn | grep \"dn\\:\" | wc -l Try to log in with one of these users. We assume that you have also set up your Jans Server to use the correct LDAP server for authentication.", "title": "Things To Remember"}, {"location": "janssen-server/link/jans-link/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/lock/lock-server/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling"], "text": "Jans Lock Overview # Lock Server is a Java Weld application that connects ephemeral Cedarlings to the enterprise by providing a number of endpoints Installation # Admins can deploy Lock Server as part of Jans Auth Server or as a stanalone web server. Configuration # A list of server-level configuration properties. Logs # Lock Server creates the following logs: lock_server_config.log lock_server_audit.log -- RDBMS option lock_server_jwt_status.log CLI / TUI # Admins can manage Lock Server runtime configuration and see activity using the Jans CLI or TUI. Create/Read/Update/Delete Policy Stores Total Number of Authz requests per day View/Search current Cedarling clients by searching for username View authz activity for this Cedarling client OAuth Security # Cedarling should present an SSA during client registration. This will enable Cedarlings to obtain access tokens with scopes for OAuth protected Lock Server endpoints.", "title": "Lock Server"}, {"location": "janssen-server/lock/lock-server/#jans-lock-overview", "text": "Lock Server is a Java Weld application that connects ephemeral Cedarlings to the enterprise by providing a number of endpoints", "title": "Jans Lock Overview"}, {"location": "janssen-server/lock/lock-server/#installation", "text": "Admins can deploy Lock Server as part of Jans Auth Server or as a stanalone web server.", "title": "Installation"}, {"location": "janssen-server/lock/lock-server/#configuration", "text": "A list of server-level configuration properties.", "title": "Configuration"}, {"location": "janssen-server/lock/lock-server/#logs", "text": "Lock Server creates the following logs: lock_server_config.log lock_server_audit.log -- RDBMS option lock_server_jwt_status.log", "title": "Logs"}, {"location": "janssen-server/lock/lock-server/#cli-tui", "text": "Admins can manage Lock Server runtime configuration and see activity using the Jans CLI or TUI. Create/Read/Update/Delete Policy Stores Total Number of Authz requests per day View/Search current Cedarling clients by searching for username View authz activity for this Cedarling client", "title": "CLI / TUI"}, {"location": "janssen-server/lock/lock-server/#oauth-security", "text": "Cedarling should present an SSA during client registration. This will enable Cedarlings to obtain access tokens with scopes for OAuth protected Lock Server endpoints.", "title": "OAuth Security"}, {"location": "janssen-server/planning/application-portal/", "tags": ["administration", "planning", "portal"], "text": "An application portal (\"portal\") is a website that displays all the protected applications available for an end user to access. The Janssen Project does not provide a portal. But you can build your own. Each application that you want in your portal should be configured as an OpenID Connect RP. Build a simple website (any CMS will do) that is also an RP. The OP can provide the roles of the user, or another claim, which will enable your portal to determine which websites to display. Iterate and display the websites (or icons) with the respective URLs.", "title": "Application Portal"}, {"location": "janssen-server/planning/benchmarking/", "tags": ["administration", "planning", "benchmarking"], "text": "Want confidence that your Janssen platform will perform with the latency and concurrency you need in production? If so, then you MUST benchmark properly. It's critical that your test data and transactions mock what you need to prove in production. For cloud-native deployments, benchmarking is also essential to test auto-scaling and failover. Ideally, you'll test the same hardware and network. Remember that OAuth has different flows, which have a different number of steps, and different requirements for compute and persistence. For example, the OAuth Client Credential Grant is very short: there is one token request and one token response. The OpenID Code Flow has many more steps: it has a request/response to the authorization, token, Userinfo and logout endpoints. It's really important to test the exact flow you intend to use in production. Benchmarking also has the benefit of testing the index configuration in your database. Every database trades disk space for performance by using indexes. If you miss an index, performance sometimes comes to a grinding halt. Your service may even crash. Having confidence that all potential index scenarios get executed in your benchmarking is essential. Auth Server publishes JUnit tests and some tools for generating test data. Because each page rendered by Auth Server has a state, you cannot use a static load generation page tool. Don't forget to gather data on compute, storage, and memory. Also, watch the resources consumed by each web service and system service (e.g. database). You can't find the bottleneck without this data. System libraries and hardware choices may also impact your results. Benchmarking is an iterative process. Inevitably, things never go exactly how you guessed they would. And you make changes to your environment and run the benchmarking tests again-- ad nauseam . Leave enough time for benchmarking. However much time you think it will take, triple your estimate. Make sure you look at both short tests and long running tests. A slow memory leak may only present after many hours of high load. Also, run some crazy tests, just so you know what happens. Some organizations benchmark for ten times the normal volume. But when an incident happens, they see 1,000 times the normal volume. Think outside-the-box. It's tricky load testing some newer two-factor authentication services, especially if they rely on new features of the browser. Hopefully the tools to benchmark these will evolve. Janssen Auth Server supports a number of deployment models--both VM and cloud-native. While cloud-native architecture enables true horizontal scalability, it comes at a cost. Benchmarking can help you understand if that cost is justified. Load test # In cloud-native architecture, the load testing is executed via k8s pods. Authorization Code Flow jmeter load test # For load testing with Authorization Code Flow jmeter test, the following script is used. See Authorization code flow recipe for details. Resource Owner Password Grant (ROPC) Flow jmeter load test # For load testing with Resource Owner Password Grant (ROPC) Flow jmeter test, the following script is used. See ROPC flow recipe for details.", "title": "Benchmarking"}, {"location": "janssen-server/planning/benchmarking/#load-test", "text": "In cloud-native architecture, the load testing is executed via k8s pods.", "title": "Load test"}, {"location": "janssen-server/planning/benchmarking/#authorization-code-flow-jmeter-load-test", "text": "For load testing with Authorization Code Flow jmeter test, the following script is used. See Authorization code flow recipe for details.", "title": "Authorization Code Flow jmeter load test"}, {"location": "janssen-server/planning/benchmarking/#resource-owner-password-grant-ropc-flow-jmeter-load-test", "text": "For load testing with Resource Owner Password Grant (ROPC) Flow jmeter test, the following script is used. See ROPC flow recipe for details.", "title": "Resource Owner Password Grant (ROPC) Flow jmeter load test"}, {"location": "janssen-server/planning/caching/", "tags": ["administration", "planning", "caching", "Redis", "Memcached"], "text": "There are two reasons to use caching. First, to improve performance by reducing the number of writes to the disk. Second, to share session data in a clustered deployment. Janssen supports a few different options for caching, as controlled by the cacheProviderType . Also keep in mind that unless the sessionIdPersistInCache is set to True , Auth Server will store sessions in the database. In-Memory If you only have one server, you can use RAM as the cache. Watch the memory usage of Auth Server--if it gets too high you may want to switch to another cache mechanism. Database A \"database cache\" is an oxymoron. But in cases where you don't want another component or service, but you need the session replication for a cluster, it may be convenient to persist the \"cache\" data in the database. Redis The best choice if you need a cache service for RDBMS, or Spanner. Great performance and low cache miss rate. Commercial Redis supports TLS, which is a good option if you need secure communication. Memcached Still a good choice, especially if that's what you already run for other applications. We have observed a slightly higher cache miss rate under high load, which is fairly atypical for most login applications. Cloud Cache Amazon ElastiCache or Google Memorystore offers both Redis and Memcached managed services. They work fine.", "title": "Caching"}, {"location": "janssen-server/planning/central-auth-service/", "tags": ["administration", "planning", "integration"], "text": "Older monolithic web access management platforms from the 2000s had features to allow central policy management--what users can access what resources. But modern federated digital identity platforms generally do not. That's true for two reasons. First implementing all the OAuth and OpenID features is already a wide swath of requirements. Second, policy management, or authorization, has itself become a nice market. Note the policy management platforms list in the RBAC planning guide page. With that said, if the number of policies is low, there are some ways to use Jans Auth Server as a central policy decision point. You could use the presence of OAuth scopes to signal to the policy enforcement point the extent of access. In this case, policies could be implemented as code in the Update Token interception script. A similar strategy is to use UMA access tokens (\"RPT tokens\"), in which case you would use either the RPT interception script or the claims gathering interception script to implement your policies (or a combination of both). But this approach should be used with caution. Most of the policy management tools today use a declarative language for policies. Maintaining policies in code does not scale as well.", "title": "Central Authorization Service Integration"}, {"location": "janssen-server/planning/certificates-keys/", "tags": ["administration", "planning", "certificates", "keys", "cryptography", "JCE", "HSM", "FIPS"], "text": "JSON Signing and Encryption # Janssen uses keys for signing and encryption, primarily concerning JSON documents. There are six IETF RFCs that provide considerable detail: RFC 7515 JSON Web Signing (JWS) RFC 7516 JSON Web Encryption (JWE) RFC 7517 JSON Web Key (JWK) RFC 7518 JSON Web Algorithms (JWA) RFC 7519 JSON Web Signing (JWT) RFC 7520 Examples of Protecting Content Using JSON Object Signing and Encryption (JOSE) Auth Server Supported Signing # JWT Type Algorithms DPOP RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Authorization HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, ES512, PS256, PS384, PS512 Request Object HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Userinfo HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Token Endpoint Auth HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 ID Token HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Auth Server Supported Encryption # Encryption Methods Algorithms Authorization A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM id_token A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Request object A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Userinfo A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Encryption Algorithms Algorithms Userinfo RSA1_5, RSA-OAEP, A128KW, A256KW id_token RSA1_5, RSA-OAEP, A128KW, A256KW authorization RSA1_5, RSA-OAEP, A128KW, A256KW request object RSA1_5, RSA-OAEP, A128KW, A256KW Java Cryptographic Engine (JCE) # Janssen projects ships and tests with the Bouncy Castle Crypto API's JCE. However, you may substitute your own JCE as long as it has implementations for the algorithms used by Auth Server. Key Rotation # OpenID Connect clients must support the rotation of both signing and encryption keys. The best practice is to rotate often--the default configuration in a VM installation of Auth Server is every two days . The reason for such a frequent rotation is to make sure developer account for rotation at the time they create applications--lest they forget and their software breaks a year later when rotation happens. In a single VM deployment, key rotation is controlled by Auth Server. But in a clustered deployment, key rotation has to happen centrally. Janssen includes a key rotation service for cloud deployments. Certificates # X.509 is used extensively for web server TLS. But it is also used for Mutual Transport Layer Security (MTLS), either initiated by a software client, or presented by a person (i.e. a personal certificate). MTLS is generally implemented in the web tier. FIPS # To support FIPS 140-2 conformance, you must use a FIPS approved JCE, and preferably, use an operating system that has FIPS Enforcement, like RHEL 8 .", "title": "Certificates/Keys"}, {"location": "janssen-server/planning/certificates-keys/#json-signing-and-encryption", "text": "Janssen uses keys for signing and encryption, primarily concerning JSON documents. There are six IETF RFCs that provide considerable detail: RFC 7515 JSON Web Signing (JWS) RFC 7516 JSON Web Encryption (JWE) RFC 7517 JSON Web Key (JWK) RFC 7518 JSON Web Algorithms (JWA) RFC 7519 JSON Web Signing (JWT) RFC 7520 Examples of Protecting Content Using JSON Object Signing and Encryption (JOSE)", "title": "JSON Signing and Encryption"}, {"location": "janssen-server/planning/certificates-keys/#auth-server-supported-signing", "text": "JWT Type Algorithms DPOP RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Authorization HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, ES512, PS256, PS384, PS512 Request Object HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Userinfo HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Token Endpoint Auth HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 ID Token HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512", "title": "Auth Server Supported Signing"}, {"location": "janssen-server/planning/certificates-keys/#auth-server-supported-encryption", "text": "Encryption Methods Algorithms Authorization A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM id_token A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Request object A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Userinfo A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Encryption Algorithms Algorithms Userinfo RSA1_5, RSA-OAEP, A128KW, A256KW id_token RSA1_5, RSA-OAEP, A128KW, A256KW authorization RSA1_5, RSA-OAEP, A128KW, A256KW request object RSA1_5, RSA-OAEP, A128KW, A256KW", "title": "Auth Server Supported Encryption"}, {"location": "janssen-server/planning/certificates-keys/#java-cryptographic-engine-jce", "text": "Janssen projects ships and tests with the Bouncy Castle Crypto API's JCE. However, you may substitute your own JCE as long as it has implementations for the algorithms used by Auth Server.", "title": "Java Cryptographic Engine (JCE)"}, {"location": "janssen-server/planning/certificates-keys/#key-rotation", "text": "OpenID Connect clients must support the rotation of both signing and encryption keys. The best practice is to rotate often--the default configuration in a VM installation of Auth Server is every two days . The reason for such a frequent rotation is to make sure developer account for rotation at the time they create applications--lest they forget and their software breaks a year later when rotation happens. In a single VM deployment, key rotation is controlled by Auth Server. But in a clustered deployment, key rotation has to happen centrally. Janssen includes a key rotation service for cloud deployments.", "title": "Key Rotation"}, {"location": "janssen-server/planning/certificates-keys/#certificates", "text": "X.509 is used extensively for web server TLS. But it is also used for Mutual Transport Layer Security (MTLS), either initiated by a software client, or presented by a person (i.e. a personal certificate). MTLS is generally implemented in the web tier.", "title": "Certificates"}, {"location": "janssen-server/planning/certificates-keys/#fips", "text": "To support FIPS 140-2 conformance, you must use a FIPS approved JCE, and preferably, use an operating system that has FIPS Enforcement, like RHEL 8 .", "title": "FIPS"}, {"location": "janssen-server/planning/components/", "tags": ["administration", "planning", "components", "architecture"], "text": "This page has a brief description of the major components of a Janssen deployment. Auth Server : This component is the OAuth Authorization Server, the OpenID Connect Provider, and the UMA Authorization Server--this is the main Internet-facing component of Janssen. It's the service that returns tokens, JWTs, and identity assertions. This service must be Internet-facing. Database : Like most IAM platforms, Janssen requires some kind of persistence service to store configuration and other entity data (client, person, scope, attribute, FIDO device, etc.) As different databases are good for different deployments, Janssen supports MySQL and Postgres. Cache : Getting data from a disk is still the slowest part of any web platform. If you want higher transaction speeds, one strategy is to use a memory cache instead of the disk (i.e. database). Janssen was designed to store short-lived objects in the cache, like the code in the OpenID code flow (which is only used one time) or access tokens, which only live for a few minutes. Currently, Janssen has three options for cache: in-memory , which is suitable only for one node VM deployments; redis which is probably your best option; and memcached which you should use if a Redis cache service is not available (and tends to have more cache misses under high volume). Key Management Janssen does a lot of cryptographic signing and encryption. Where you store the private keys has an impact on the security of your Janssen platform. For cloud deployments, many providers are providing key storage as a service. You could also use the file system or an HSM. FIDO2 : This component provides the server side endpoints to enroll and validate devices that use FIDO. It provides both FIDO U2F (register, authenticate) and FIDO 2 (attestation, assertion) endpoints. This service must be internet facing. Config API : The API to configure the auth-server and other components is consolidated in this component. This service should not be Internet-facing. SCIM : SCIM is JSON/REST API to manage user data. Use it to add, edit and update user information. This service should not be Internet facing. CLI : While you can use curl to call the Config API, CLI is a command line tool that provides a simple single line options for configuration. In the background, it is just calling the Config API. To authenticate, you'll use the OAuth Device flow. The CLI need not be on the same server as any of the components (you can run it from your desktop). But you will need network connectivity to the Config API and the Auth Server. TUI : A menu-driven interactive tool for configuration, the \"TUI\" or \"text user interface\" might resemble a 90's BIOS configuration, but it gets the job done without the need for a web browser. Like the CLI, you can run it from anywhere, but need connectivity to the Config API and Auth Server. The TUI writes a \"CLI log\"--the one-liner you could have executed to do whatever you just did in the interface. This will help you if you want to script stuff later on. Jans Core : This library has code that is shared across several Janssen projects. You will most likely need this project when you build other Janssen components. Jans ORM : This is the library for persistence and caching implementations in Janssen. Currently,only RDBMS is supported. Agama : The Agama module offers an alternative way to build authentication flows in Janssen Server. With Agama, flows are coded in a DSL (domain specific language) designed for the sole purpose of writing web flows. Setup : Configuring a Janssen Auth Server platform is complicated. How do you generate the keys and certificates? How do you generate the minimal data set to start your system? The setup component helps you bootstrap a minimal system.", "title": "Components"}, {"location": "janssen-server/planning/customization/", "tags": ["administration", "planning", "localization", "international", "language"], "text": "Customization and Localization # You can customize just about everything in the Janssen Platform. That's pretty much the point of running your own identity platform. This includes the look and feel of the web pages, the language of the user-facing content, the behavior of endpoints, error messages, and more. Behavior of endpoints # Almost every endpoint has an interception script, which enables you to implement custom business logic. For a more general discussion of the extensibility of the Janssen platform, see the Developer Guide . Web content # There are several front channel flows in Auth Server (front channel = web browser): OpenID User Authentication OpenID Consent Post-Authentication UMA Claims Gathering Each of these scripts contains a method which is similar to getPageForStep which fetches the respective Facelets xhtml file for that step. Facelets is very friendly to designers, as it's possible to mix content such as regular HTML with JSF components. Thus Facelets pages can have both static and dynamic content and leverage all your \"normal\" web design tools like CSS and JavaScript. Facelets also support templates. Each .xhtml page has access to the authentication context, and you can insert data from the respective interception script. Also, each .xhtml page is unique and has a built-in state identifier, preventing Auth Server from responding to any page which it did not render. For more information, see the Developer Guide . Note, in the getPageForStep method, you can have a conditional statement to return different pages based either on the detected or requested language of the subject. Error messages # You can change the descriptions for the various front-channel Auth Server error messages, for example, what would Auth Server return for a bad request to the Authorization Endpoint. Of course, you can also customize the web server error messages, like 404, by configuring your web server. Auth Server should never return a stackTrace. Localization for OpenID Connect client metadata # Because client information may be displayed via the OpenID protocol, language support is needed at the client level. For example, the client name, description, terms of service URI, or logo may differ based on the end user's language. Section 2.1 of OpenID Connect Client Registration, Metadata Languages and Scripts states: Human-readable Client Metadata values and Client Metadata values that reference human-readable values MAY be represented in multiple languages and scripts. For example, values such as client_name, tos_uri, policy_uri, logo_uri, and client_uri might have multiple locale-specific values in some Client registrations. To specify the languages and scripts, BCP47 language tags are added to Client Metadata member names, delimited by a # character. For example, the value for tos_uri#ja-Hani-JP would direct the subject to the terms of service agreement in Japanese. Janssen does not yet support languages syntax for OpenID user claims, as described in OpenID Core Section 5.2, Claims Languages and Scripts .", "title": "Customization/Localization"}, {"location": "janssen-server/planning/customization/#customization-and-localization", "text": "You can customize just about everything in the Janssen Platform. That's pretty much the point of running your own identity platform. This includes the look and feel of the web pages, the language of the user-facing content, the behavior of endpoints, error messages, and more.", "title": "Customization and Localization"}, {"location": "janssen-server/planning/customization/#behavior-of-endpoints", "text": "Almost every endpoint has an interception script, which enables you to implement custom business logic. For a more general discussion of the extensibility of the Janssen platform, see the Developer Guide .", "title": "Behavior of endpoints"}, {"location": "janssen-server/planning/customization/#web-content", "text": "There are several front channel flows in Auth Server (front channel = web browser): OpenID User Authentication OpenID Consent Post-Authentication UMA Claims Gathering Each of these scripts contains a method which is similar to getPageForStep which fetches the respective Facelets xhtml file for that step. Facelets is very friendly to designers, as it's possible to mix content such as regular HTML with JSF components. Thus Facelets pages can have both static and dynamic content and leverage all your \"normal\" web design tools like CSS and JavaScript. Facelets also support templates. Each .xhtml page has access to the authentication context, and you can insert data from the respective interception script. Also, each .xhtml page is unique and has a built-in state identifier, preventing Auth Server from responding to any page which it did not render. For more information, see the Developer Guide . Note, in the getPageForStep method, you can have a conditional statement to return different pages based either on the detected or requested language of the subject.", "title": "Web content"}, {"location": "janssen-server/planning/customization/#error-messages", "text": "You can change the descriptions for the various front-channel Auth Server error messages, for example, what would Auth Server return for a bad request to the Authorization Endpoint. Of course, you can also customize the web server error messages, like 404, by configuring your web server. Auth Server should never return a stackTrace.", "title": "Error messages"}, {"location": "janssen-server/planning/customization/#localization-for-openid-connect-client-metadata", "text": "Because client information may be displayed via the OpenID protocol, language support is needed at the client level. For example, the client name, description, terms of service URI, or logo may differ based on the end user's language. Section 2.1 of OpenID Connect Client Registration, Metadata Languages and Scripts states: Human-readable Client Metadata values and Client Metadata values that reference human-readable values MAY be represented in multiple languages and scripts. For example, values such as client_name, tos_uri, policy_uri, logo_uri, and client_uri might have multiple locale-specific values in some Client registrations. To specify the languages and scripts, BCP47 language tags are added to Client Metadata member names, delimited by a # character. For example, the value for tos_uri#ja-Hani-JP would direct the subject to the terms of service agreement in Japanese. Janssen does not yet support languages syntax for OpenID user claims, as described in OpenID Core Section 5.2, Claims Languages and Scripts .", "title": "Localization for OpenID Connect client metadata"}, {"location": "janssen-server/planning/delegated-user-admin/", "tags": ["administration", "planning"], "text": "Delegated user administration is normally implemented via a website where a privileged user can search / add / edit / delete people in their organization. You will not be surprised to hear that this is an identity management use case that Janssen Auth Server does not provide out of the box. But if you wanted to build a website that performed this function, you could use the SCIM protocol to do so. In your application, you could read the user claims to find out the organization, role, or other information about the person managing data. Then your web application could use this information to make filters when making SCIM calls. Or another handy trick is to put the person's role information in an OAuth access token (using the Update Token script), and then use the SCIM interception script to add the respective filters.", "title": "Delegated User Administration"}, {"location": "janssen-server/planning/discovery/", "tags": ["administration", "planning", "discovery"], "text": "In a federated identity topology, you can authenticate a person by redirecting their browser to the correct IDP. But what happens when there is more then one IDP? Before the person authenticates, how do you know to which IDP to send them? This challenge is called \"discovery\", \"where are you from\", or \"WAYF\". There are a few ways to handle discovery. Here are a few: Display a list of logos and enable the end user to pick the IDP. If you ever clicked on a social login button, you've experienced this approach. Use a different URL for each IDP, like https://customer1.saas.com or https://saas.com/customer2 . Based on which URL the person hits, you know where to send them. Prompt the person to enter something identifying, like their email address. You can use this to look up their home IDP. Use contextual information, like network address, geolocation, or browser data. Once you've figured out the person behind the browser, it may make sense to write a cookie so next time, you don't have to bother them. While it's possible to implement a discovery workflow using an Agama script or an Auth Server person authentication interception script, you also write a simple web application, and then redirect to the authorization endpoint with a hint as an extra parameter and a specific acr_values .", "title": "Discovery"}, {"location": "janssen-server/planning/dns/", "tags": ["administration", "planning", "DNS", "hostname", "TLS", "X.509"], "text": "Trust in the Internet is largely derived from TLS. Like it or not, we are highly reliant on making a secure connection from a web browser using X.509 security to ensure that we are connecting to a trusted web server. The cn of that web server certificate is the hostname of the server. There is no guarantee that a two distinct trusted root CA's have not issued duplicate certificates for the same hostname. Thus, if your DNS server is hacked, bad things may ensue. This is not a hypothetical risk. Actual attacks have been implemented by adding entries to a DNS server that look real, but point to the attacker's website. DNS attacks are very difficult for the end-user to detect. For example, https://account.acme.com v. https://accounts.acme.com --both would look ok to a typical end user. So rule number one: PROTECT DNS--the whole integrity of your identity platform is otherwise vulnerable. From a deployment perspective, remember that in most cases the hostname of your IDP points to the HTTP load balancer (unless you have a single VM deployment). In most cases, you will also terminate TLS in the load balancer. The DNS hostname is baked into the protocols. For example, the authorization endpoint may look like this: \"authorization_endpoint\" : \"https://account.acme.com/jans-auth/restv1/authorize\" Note that the hostname is built into the protocol, not just the Web TLS layer. If you were to change the hostname of your web server, your deployment would break, because you would have to update all the configuration data in the IDP that contains the hostname too. And you'd have to regenerate any X.509 certificates. For this reason, you should think carefully about the hostname before you run setup and create the base installation of your Janssen Platform. To change the hostname, we recommend you re-install. If you want to promote your configuration from development to production, you may also need to consider keeping the hostname the same--although be careful you don't hit production by mistake in your testing.", "title": "DNS"}, {"location": "janssen-server/planning/identity-access-governance/", "tags": ["administration", "planning", "IAG", "Identity Governance"], "text": "Janssen is not a governance platform, so it does not do any of the following: Role Management # Role Based Access Control (RBAC) is a strategy used by many organizations to authorize access to resources. However, RBAC has a dark side: if roles are used to reference each unique access requirement the number of roles can grow exponentially. In fact, some organizations have more roles than people! This is known as \"role explosion.\" Role Management is an enterprise workforce governance practice which correlates roles across all applications to reduce their number to the lowest common denominator of \"enterprise roles\". Access Certification # The role request and approval processes tend to result in a person accumulating many roles over time. However, because removal of roles no-longer-needed is often overlooked, it's important for organizations to regularly perform access certification campaigns (i.e. \"recertification\" or \"attestation\"). For example, once per year, managers may need to decide if the roles assigned to subordinate employees are still needed. Removal of a non-sensitive role is not an urgent matter. However, certain situations might require faster action, for example if an employee is moved to a different organizational unit with a different manager. The new manager assumes responsibility for the employee's roles, and should execute an ad-hoc recertification process for that specific user. Segregation of Duties # Sometimes an organization should prevent a person from having two roles simultaneously. For example, there could be an account rule that a person can't both sign and approve checks. Or a person can't perform both financial advisory and equity trading. The governance platform may enable organizations to define these Segregation of Duties to prevent such conflicts of interest.", "title": "Identity Access Governance"}, {"location": "janssen-server/planning/identity-access-governance/#role-management", "text": "Role Based Access Control (RBAC) is a strategy used by many organizations to authorize access to resources. However, RBAC has a dark side: if roles are used to reference each unique access requirement the number of roles can grow exponentially. In fact, some organizations have more roles than people! This is known as \"role explosion.\" Role Management is an enterprise workforce governance practice which correlates roles across all applications to reduce their number to the lowest common denominator of \"enterprise roles\".", "title": "Role Management"}, {"location": "janssen-server/planning/identity-access-governance/#access-certification", "text": "The role request and approval processes tend to result in a person accumulating many roles over time. However, because removal of roles no-longer-needed is often overlooked, it's important for organizations to regularly perform access certification campaigns (i.e. \"recertification\" or \"attestation\"). For example, once per year, managers may need to decide if the roles assigned to subordinate employees are still needed. Removal of a non-sensitive role is not an urgent matter. However, certain situations might require faster action, for example if an employee is moved to a different organizational unit with a different manager. The new manager assumes responsibility for the employee's roles, and should execute an ad-hoc recertification process for that specific user.", "title": "Access Certification"}, {"location": "janssen-server/planning/identity-access-governance/#segregation-of-duties", "text": "Sometimes an organization should prevent a person from having two roles simultaneously. For example, there could be an account rule that a person can't both sign and approve checks. Or a person can't perform both financial advisory and equity trading. The governance platform may enable organizations to define these Segregation of Duties to prevent such conflicts of interest.", "title": "Segregation of Duties"}, {"location": "janssen-server/planning/identity-management/", "tags": ["administration", "planning", "IDM", "Identity Management", "SCIM"], "text": "Identity Management # In Janssen docs, the term Identity Management or \"IDM\" is the process of adding, editing and deleting data in various domain systems. Ideally, identity data would exist in only one place. But this ideal is currently undesirable. For performance, data joins, auditing, and many other reasons (for the foreseeable future) identity data is sprinkled across many systems. So when we update identity data, how do we keep all our infrastructure up-to-date? This task has been the realm of IDM platforms, which enable organizations to define workflows to update identity information, and through the use of \"connectors\", to push this data to all disparate databases. IDM platforms range in size and complexity. An admin could write a Python script to automate adding new users to a domain. Large enterprises may implement a commercial IDM platform, like Sailpoint or an open-source IDM platform like Evolveum Midpoint . Or you might have a human IDM--\"Hey Bob, we hired a new person. Can you add her?\" The Janssen platform does not include an IDM component. Fundamentally, Janssen is a consumer of identity data. One of the most common ways for identity data to make its way to the Janssen database is via the SCIM interface. This is an API that has a /users endpoint, to which an IDM system can send updates. For example, the IDM system may POST to the /users endpoint to add a new user to the Janssen database, or DELETE to the /users endpoint to remove a user. With that said, sometimes organizations might encode IDM business logic in the Janssen platform. This is particularly true for consumer-facing applications. In general, it only works for relatively simple requirements, particularly when the Janssen platform is the authoritative source of identity data. Using the various interception scripts, it's possible to send identity data from the Janssen platform to external systems. For example, let's say an organization has only two silos of identity data: Jans Auth Server and a MongoDB database record. In a case like this, when a person registers through a Person Authn Interception Script or Agama flow, you could call an API which updates the MongoDB database. It's also possible to implement approval workflows using UMA. For example, an API might require an UMA access token (i.e. an RPT token), and obtaining this token may require the consent of two different individuals. But it is worth remembering that the Janssen Platform was not purpose-built for IDM, and therefore any implementation for such use cases should be tactical. You may have to build many features yourself. Especially for enterprise workforce applications, you should seriously consider using off-the-shelf software before writing too much code in Janssen.", "title": "Identity Management"}, {"location": "janssen-server/planning/identity-management/#identity-management", "text": "In Janssen docs, the term Identity Management or \"IDM\" is the process of adding, editing and deleting data in various domain systems. Ideally, identity data would exist in only one place. But this ideal is currently undesirable. For performance, data joins, auditing, and many other reasons (for the foreseeable future) identity data is sprinkled across many systems. So when we update identity data, how do we keep all our infrastructure up-to-date? This task has been the realm of IDM platforms, which enable organizations to define workflows to update identity information, and through the use of \"connectors\", to push this data to all disparate databases. IDM platforms range in size and complexity. An admin could write a Python script to automate adding new users to a domain. Large enterprises may implement a commercial IDM platform, like Sailpoint or an open-source IDM platform like Evolveum Midpoint . Or you might have a human IDM--\"Hey Bob, we hired a new person. Can you add her?\" The Janssen platform does not include an IDM component. Fundamentally, Janssen is a consumer of identity data. One of the most common ways for identity data to make its way to the Janssen database is via the SCIM interface. This is an API that has a /users endpoint, to which an IDM system can send updates. For example, the IDM system may POST to the /users endpoint to add a new user to the Janssen database, or DELETE to the /users endpoint to remove a user. With that said, sometimes organizations might encode IDM business logic in the Janssen platform. This is particularly true for consumer-facing applications. In general, it only works for relatively simple requirements, particularly when the Janssen platform is the authoritative source of identity data. Using the various interception scripts, it's possible to send identity data from the Janssen platform to external systems. For example, let's say an organization has only two silos of identity data: Jans Auth Server and a MongoDB database record. In a case like this, when a person registers through a Person Authn Interception Script or Agama flow, you could call an API which updates the MongoDB database. It's also possible to implement approval workflows using UMA. For example, an API might require an UMA access token (i.e. an RPT token), and obtaining this token may require the consent of two different individuals. But it is worth remembering that the Janssen Platform was not purpose-built for IDM, and therefore any implementation for such use cases should be tactical. You may have to build many features yourself. Especially for enterprise workforce applications, you should seriously consider using off-the-shelf software before writing too much code in Janssen.", "title": "Identity Management"}, {"location": "janssen-server/planning/kubernetes/", "tags": ["administration", "planning", "kubernetes"], "text": "Overview # This planning guide helps you learn about when to use Jans with Kubernetes, why to use it, an overview of best practices around it, platforms supported and important tools that can help ease the operations. The When and Why? # Whether to use Kubernetes , VM or a cluster of VMs depends on answering several key questions some of which are: What's the size of my organization/customer serving base? # Answering this question gives the load of authentications per second expected which determines if you are in the threshold of operating a VM for Jans. Anything past 50 auths per second points to a cluster setup which is curerntly Kuberentes. We do plan to support more cloud-native setups soon. Can my organization handle min-hrs of downtime? # This ties to question 1 but even with the best operational automation VM setups restoring/patching a VM will result in downtime. Does my organization function in different regions? # If your organization works in several regions a VM setup is almost immediately ruled out. Does my organization expect to double in growth each year? or possibly faster? # If your organization or your customer base is growing fast rule out a VM setup. Is this an on-premise vs hybrid vs cloud deployment? # This question weighs on the current infrastructure of your organization. Operating on-premise Kubernetes setups needs generally more technical resources than operating a cloud setup. Comparing that to a VM setup, operating a VM setup is much easier in on-premise setups. The more the momentum of your org pulls to cloud vs onpremise the more it pulls to Kuberetnes vs a VM setup respectively. What's my organizations technical expertise level on Kubernetes vs VMs? # This determines the amount of investment needed to overcome the learning curve to operate a Kubernetes cluster. If your Kubernetes technical resources are low and the above questions point to a VM setup you should think about going with a vm setup. If you got conflicting answers above, for example if the customer size dedicated that you should operate a Kubernetes cluster you need to invest in your technical staff. If you are on the borderline invest in your Kubernetes technical staff while operating a vm setup and prepare to move in the near future. Does the deployment need to be highly available(HA)? # We recommend using Kubernetes-based CN deployments for situations where high availability is a critical factor. Though VM cluster can provide high availability, we do not recommend the HA setup with VMs. Primarily because effort required to upgrade multiple servers and configuring them is much more as compared to a cloud native deployment and it is error-prone. We recommend you follow the CN setup for HA as you will get automatic upgrades, patches with a single helm upgrade command. In general the Kubernetes deployment offers an easy deployment strategy with a helm chart and an easy upgrade path but taking the above into account is very important. The Supported Clouds # We support several clouds managed Kubernetes solutions but that doesn't mean our setup will not work with other managed Kubernetes solutions. In fact, our Kubernetes setup is expected to work across almost all managed solutions however those not listed below were not tested. AWS GCP Azure DOKS Local/Hybrid # Rancher # Rancher UI can be deployed to several clouds / multi-clouds and also be used to manage local setups. Important tools and tech to consider # Helm Terraform Prometheus and Grafana Pipeline tech such as Jenkins, Ansible, Cloud Build ..etc", "title": "Kubernetes"}, {"location": "janssen-server/planning/kubernetes/#overview", "text": "This planning guide helps you learn about when to use Jans with Kubernetes, why to use it, an overview of best practices around it, platforms supported and important tools that can help ease the operations.", "title": "Overview"}, {"location": "janssen-server/planning/kubernetes/#the-when-and-why", "text": "Whether to use Kubernetes , VM or a cluster of VMs depends on answering several key questions some of which are:", "title": "The When and Why?"}, {"location": "janssen-server/planning/kubernetes/#whats-the-size-of-my-organizationcustomer-serving-base", "text": "Answering this question gives the load of authentications per second expected which determines if you are in the threshold of operating a VM for Jans. Anything past 50 auths per second points to a cluster setup which is curerntly Kuberentes. We do plan to support more cloud-native setups soon.", "title": "What's the size of my organization/customer serving base?"}, {"location": "janssen-server/planning/kubernetes/#can-my-organization-handle-min-hrs-of-downtime", "text": "This ties to question 1 but even with the best operational automation VM setups restoring/patching a VM will result in downtime.", "title": "Can my organization handle min-hrs of downtime?"}, {"location": "janssen-server/planning/kubernetes/#does-my-organization-function-in-different-regions", "text": "If your organization works in several regions a VM setup is almost immediately ruled out.", "title": "Does my organization function in different regions?"}, {"location": "janssen-server/planning/kubernetes/#does-my-organization-expect-to-double-in-growth-each-year-or-possibly-faster", "text": "If your organization or your customer base is growing fast rule out a VM setup.", "title": "Does my organization expect to double in growth each year? or possibly faster?"}, {"location": "janssen-server/planning/kubernetes/#is-this-an-on-premise-vs-hybrid-vs-cloud-deployment", "text": "This question weighs on the current infrastructure of your organization. Operating on-premise Kubernetes setups needs generally more technical resources than operating a cloud setup. Comparing that to a VM setup, operating a VM setup is much easier in on-premise setups. The more the momentum of your org pulls to cloud vs onpremise the more it pulls to Kuberetnes vs a VM setup respectively.", "title": "Is this an on-premise vs hybrid vs cloud deployment?"}, {"location": "janssen-server/planning/kubernetes/#whats-my-organizations-technical-expertise-level-on-kubernetes-vs-vms", "text": "This determines the amount of investment needed to overcome the learning curve to operate a Kubernetes cluster. If your Kubernetes technical resources are low and the above questions point to a VM setup you should think about going with a vm setup. If you got conflicting answers above, for example if the customer size dedicated that you should operate a Kubernetes cluster you need to invest in your technical staff. If you are on the borderline invest in your Kubernetes technical staff while operating a vm setup and prepare to move in the near future.", "title": "What's my organizations technical expertise level on Kubernetes vs VMs?"}, {"location": "janssen-server/planning/kubernetes/#does-the-deployment-need-to-be-highly-availableha", "text": "We recommend using Kubernetes-based CN deployments for situations where high availability is a critical factor. Though VM cluster can provide high availability, we do not recommend the HA setup with VMs. Primarily because effort required to upgrade multiple servers and configuring them is much more as compared to a cloud native deployment and it is error-prone. We recommend you follow the CN setup for HA as you will get automatic upgrades, patches with a single helm upgrade command. In general the Kubernetes deployment offers an easy deployment strategy with a helm chart and an easy upgrade path but taking the above into account is very important.", "title": "Does the deployment need to be highly available(HA)?"}, {"location": "janssen-server/planning/kubernetes/#the-supported-clouds", "text": "We support several clouds managed Kubernetes solutions but that doesn't mean our setup will not work with other managed Kubernetes solutions. In fact, our Kubernetes setup is expected to work across almost all managed solutions however those not listed below were not tested. AWS GCP Azure DOKS", "title": "The Supported Clouds"}, {"location": "janssen-server/planning/kubernetes/#localhybrid", "text": "", "title": "Local/Hybrid"}, {"location": "janssen-server/planning/kubernetes/#rancher", "text": "Rancher UI can be deployed to several clouds / multi-clouds and also be used to manage local setups.", "title": "Rancher"}, {"location": "janssen-server/planning/kubernetes/#important-tools-and-tech-to-consider", "text": "Helm Terraform Prometheus and Grafana Pipeline tech such as Jenkins, Ansible, Cloud Build ..etc", "title": "Important tools and tech to consider"}, {"location": "janssen-server/planning/load-balancers/", "tags": ["administration", "planning", "load balancer", "nginx", "apache HTTPD", "istio"], "text": "Janssen Auth Server is stateless, so you can spool up as many instances as your load requires. But as there is only one hostname, you need a way to distribute the requests. Typically, this is where a load balancer comes in. The load balancer also terminates the SSL connection, which offloads the cryptographic compute from the application. In cloud-native jargon, load balancing is called HTTP Ingress. In your load balancer configuration, you can use any routing algorithm. There is no need for \"sticky sessions\", or whatever the load balancer you are using calls that. For example, it's ok to use even round robin. Although modern HTTP ingress controllers enable some very flexible routing options to do A/B testing and zero downtime updates. As Janssen Auth Server doesn't really care what load balancer you use, some options you might want to consider are: Apache HTTPD nginx istio f5 Amazon Elastic Load Balancing Google Cloud Load Balancing", "title": "Load Balancers"}, {"location": "janssen-server/planning/machine-to-machine/", "tags": ["administration", "planning"], "text": "OAuth gives us a perfect infrastructure for one machine (i.e. software) to authenticate itself while calling an API of another machine: the Client Credential Grant . The software receiving the token can validate the access token signature, or if it's a reference token, can use OAuth Introspection . For extra security, the software in question can also use mutual TLS to authenticate. The OAuth Authorization Server can also send extra security context, like scopes (which typically communicate the extent of access), or other information about the software vendor or characteristics. Of course this requires the devices in this machine-to-machine scenario to have a tcp stack (some constrained IOT devices only have a UDP stack).", "title": "Machine-to-Machine Authentication"}, {"location": "janssen-server/planning/multi-tenancy/", "tags": ["administration", "planning", "multitenancy"], "text": "Multitenancy is a software architecture where several distinct customers can utilize a single software instance. For a federated identity platform, this presents a number of challenges: Privacy: Customers must only see their own user information and data Trust: Customers trust a distinct set of RPs Authorization: Customers have specific policy requirements UX: Customers brand all user-facing web pages and messages Logs: Customers see only their own log Custom Business Logic: Customers have special rules, for example, to authenticate users, register clients, or issue access tokens. Cryptographic Keys: Customers have their own keys URLs: Customers host the IDP using their own domain name Quality of Service: Customers control response time and concurrency Access: Customers can access systems and data directly One key decision to make with regard to multitenancy is which systems to share. You could share nothing, which lowers deployment complexity but increases operational complexity. Or you could share everything, which is easier to operate, saves money on hardware, but requires a lot more code. Or you could land somewhere between--share some systems, but not others. If you want to address all the challenges of multitenancy, then a \"shared nothing\" approach makes the most sense. And with advances in cloud-native deployment, gitops, and configuration as code, you can approach the cost savings of \"shared everything\" multitenancy today, especially if you leverage serverless, just in time auto-scaling. However, you will need some cloud-native devops gurus to pull this off. If having one top-level domain is acceptable, it is possible to add a tenant_id property to each entity (for example, client and person entities). Auth Server and SCIM interception scripts enable you to filter results by adding this tenant_id to queries behind the scenes. For example, you could also render different login pages by using default_acr_values for clients. It's possible in the future Jansen Project will implement some kind of support to bundle a multitenancy approach that captures some of the properties described above at the code level, but for the time being, it is not a priority.", "title": "Multi-tenancy"}, {"location": "janssen-server/planning/passwordless-auth/", "tags": ["administration", "planning", "passwordless"], "text": "Auth Server is not proscriptive about how an organization authenticates a person. If you want to avoid passwords, that's great. Everyone knows passwords are terrible. Modern authentication flows use a series of web pages to mitigate sufficient risk, enabling them to issue an assertion about the subject's identity. In order to perform authentication, identification is a given. This implies that all authentication flows normally start with the subject asserting some kind of identifier: username, email address, phone number, or any other identifier that uniquely identifies a person. Auth Server is not opinionated about how you do this. You could prompt the user to enter their identifier. Or for example, you could ask the user to scan a QR code, and identify a phone identified with a person. With identification done, Auth Server can present any number of additional web pages to establish that identity. These pages can ask for any \"factors\". For example, if you want to perform two factor authentication in one step, you could use a FIDO 2 credential, which combines possession with either knowledge or biometric. But in practice, you could ask for any one or more combinations of credentials--none of which must include a password. Net-net, \"passwordless\" is really just marketing jargon. Normally it implies some kind of risk assessment to optimize user experience. If you can imagine any such authentication flow, you can implement it in Auth Server.", "title": "Passwordless Authentication"}, {"location": "janssen-server/planning/persistence/", "tags": ["administration", "planning", "persistence", "MySQL", "Aurora", "Postgres", "database"], "text": "The performance of the web tier is derived from the performance of the persistence tier. While memory-caching short lived entities to reduce persistence is an option, there are still long lived objects that need to be written to the disk. Picking the right database has a huge impact on the operational burden of a digital identity infrastructure. All database administration requires some black art--every platform has some secret knobs and levers that are critical to tuning, availability and rapid diagnosis. So beyond the performance requirements that determine the right choice for a database, you also need to consider operational concerns. Janssen's strategy is to provide optionality for persistence. There is no one size fits all solution for databases. The following section will detail some of the pros and cons of the various databases we currently support. MySQL You know it... you love it. That's the biggest advantage. Performance is great out of the box. But if you have high concurrency, you'll have to figure out a plan for replication, and horizontal scaling. MySQL is our default persistence for Production deployments using Kubernetes . Postgres Same as MySQL above, but there are some great commercial distributions of Postgres like EnterpriseDB . Postgres is our default persistence for VM based non-production deployments . Aurora So you want MySQL, but you want Amazon to handle some of the care and feeding? Aurora enables you to consume database as a cloud service. Scalability is excellent and multi-region deployments are possible . The main catch is that write operations are limited to one region, with the ability to failover to another region. But to accomplish this, you need a cloud engineer to implement it.", "title": "Persistence"}, {"location": "janssen-server/planning/platform-goal/", "tags": ["administration", "planning", "platform-goals"], "text": "Mission # Make it easier for organizations to innovate and scale open source, standards-based identity services. Scale # Using Janssen Project software, organizations can build runtime identity services to meet 100% of their requirements for enrollment, authentication, credential management, and authorization. The Janssen Project includes software tools and services for deploying, operating, testing, and developing identity infrastructure at scale. Scale is more than cloud-native design patterns. To truly scale, domains have to consider the people and organizational challenges. To scale domains need to: manage the complexity and cost of integrating multiple technologies, platforms, and vendors that may not be compatible or interoperable ensure the security and compliance of data and transactions across different systems, networks, and jurisdictions, especially when dealing with sensitive or regulated information adapt to the changing and unpredictable demands of customers, markets, and deliver fast and reliable services; domains must develop and share the skills and talent needed to design, implement, and operate scalable identity infrastructure, and foster a culture of innovation and collaboration among teams balance the trade-offs between scaling up (adding more resources within a system) and scaling out (adding more systems across a network), and choosing the optimal architecture and configuration for different workloads and scenarios. At the Janssen Project, we are doing our best to address all these challenges with regard to scaling identity infrastructure. Security # Janssen Project tackles the most challenging security requirements. This means keeping current with OpenID and FIDO self-certifications, creating distributions that enables conformance with FIPS 140-2, and implementing best practices for software development. Janssen Project is unapologetically Java. The reason is simple: Java has the most cryptographic implementations. Java Cryptographic Engines (JCE) are written by many companies and open-source projects. It takes a long time to trust a cryptographic implementation. Not only does Java have the most options for cryptography, but it also has some of the most trusted implementations. And when new algorithms are announced, Java SDKs are usually first. Community # In 2020, Gluu contributed the code to the Linux Foundation Janssen Project. One of the main reasons this was undertaken was to expand the size of the community. Developers don't want to contribute to a project that might change the license at any moment (e.g. Hashicorp, Elastic, MongoDB). There is room for many companies to productize the Janssen Project software. Governments can feel safe using the Janssen Project--it's been recognized as a Digital Public Good . A healthy ecosystem for infrastructure software results in long-term innovation velocity. With the introduction of Agama, we're hoping that developers will have an opportunity to build connectors to third-party systems and services. Gluu is hosting the Agama Lab Explore Catalog to help developers publish their Agama projects, making it easier for the community to find ready-built projects that encourage the re-use of code. Deployment # Developers should have distributions to enable rapid testing for non-production instances. Linux system administrators should have packages for easy installation and update of non-clustered deployments. Cloud-native engineers should have assets for high-end deployments, including high concurrency and high availability.", "title": "Platform Goal"}, {"location": "janssen-server/planning/platform-goal/#mission", "text": "Make it easier for organizations to innovate and scale open source, standards-based identity services.", "title": "Mission"}, {"location": "janssen-server/planning/platform-goal/#scale", "text": "Using Janssen Project software, organizations can build runtime identity services to meet 100% of their requirements for enrollment, authentication, credential management, and authorization. The Janssen Project includes software tools and services for deploying, operating, testing, and developing identity infrastructure at scale. Scale is more than cloud-native design patterns. To truly scale, domains have to consider the people and organizational challenges. To scale domains need to: manage the complexity and cost of integrating multiple technologies, platforms, and vendors that may not be compatible or interoperable ensure the security and compliance of data and transactions across different systems, networks, and jurisdictions, especially when dealing with sensitive or regulated information adapt to the changing and unpredictable demands of customers, markets, and deliver fast and reliable services; domains must develop and share the skills and talent needed to design, implement, and operate scalable identity infrastructure, and foster a culture of innovation and collaboration among teams balance the trade-offs between scaling up (adding more resources within a system) and scaling out (adding more systems across a network), and choosing the optimal architecture and configuration for different workloads and scenarios. At the Janssen Project, we are doing our best to address all these challenges with regard to scaling identity infrastructure.", "title": "Scale"}, {"location": "janssen-server/planning/platform-goal/#security", "text": "Janssen Project tackles the most challenging security requirements. This means keeping current with OpenID and FIDO self-certifications, creating distributions that enables conformance with FIPS 140-2, and implementing best practices for software development. Janssen Project is unapologetically Java. The reason is simple: Java has the most cryptographic implementations. Java Cryptographic Engines (JCE) are written by many companies and open-source projects. It takes a long time to trust a cryptographic implementation. Not only does Java have the most options for cryptography, but it also has some of the most trusted implementations. And when new algorithms are announced, Java SDKs are usually first.", "title": "Security"}, {"location": "janssen-server/planning/platform-goal/#community", "text": "In 2020, Gluu contributed the code to the Linux Foundation Janssen Project. One of the main reasons this was undertaken was to expand the size of the community. Developers don't want to contribute to a project that might change the license at any moment (e.g. Hashicorp, Elastic, MongoDB). There is room for many companies to productize the Janssen Project software. Governments can feel safe using the Janssen Project--it's been recognized as a Digital Public Good . A healthy ecosystem for infrastructure software results in long-term innovation velocity. With the introduction of Agama, we're hoping that developers will have an opportunity to build connectors to third-party systems and services. Gluu is hosting the Agama Lab Explore Catalog to help developers publish their Agama projects, making it easier for the community to find ready-built projects that encourage the re-use of code.", "title": "Community"}, {"location": "janssen-server/planning/platform-goal/#deployment", "text": "Developers should have distributions to enable rapid testing for non-production instances. Linux system administrators should have packages for easy installation and update of non-clustered deployments. Cloud-native engineers should have assets for high-end deployments, including high concurrency and high availability.", "title": "Deployment"}, {"location": "janssen-server/planning/role-based-access-management/", "tags": ["administration", "planning", "RBAC", "Role"], "text": "Using roles to control access to resources makes sense for lots of security use cases. One benefit of RBAC is that it's deterministic-- from an audit perspective, you can tell who had access to what at any point in time. This is harder to achieve when contextual variables play a role in determining access. An OpenID Provider / OAuth Authorization Server like Jans Auth Server certainly has a role to play in the implementation of an RBAC infrastructure, but is not capable of delivering all the functionality your organization will need for a complete solution. For example, you may need a platform to define enterprise roles or to perform role consolidation. This is normally handled by an identity governance tool. Also, Jans Auth Server is not a policy management platform, like * Styra OPA , OSO * Zanzibar , or * Hashicorp Boundary or * Apache Fortress The tools above are just a few open source policy management frameworks. There are more commercial products in this space. Although Jans Auth Server may not be a complete RBAC solution, there are still some RBAC capabilities to consider. When a person authenticates using a web browser, the client can obtain user claims via OpenID Connect. It may make sense to send the role role claim to the client. You may also send the memberOf claim, if your organization uses group membership to manage roles. But what if you need to dynamically compute roles? Or if you don't want to over-share by sending all the roles and groups associated for a person? One strategy is to use the Jans Auth Server Update Token Interception script to render the role claim, either in the OAuth access token, the id_token or the Userinfo JWT.", "title": "Role Based Access Management"}, {"location": "janssen-server/planning/security-best-practices/", "tags": ["administration", "planning", "security", "recommendations"], "text": "Janssen Project distributions are designed to be easy to deploy. Its default security settings may not be strict enough for certain organizations or use cases. This document highlights important security controls and offers best practices for increasing security related to your deployment. Scripts # Make sure only required scripts are enabled. It's extremely important to disable any person authentication or other scripts not in use. Keys # Use RSA keys with a minimum strength of 2048 bits and Elliptic Curve keys with a minimum of 160 bits. Also, check the key rotation policy of your Auth Server. This differs based on your deployment model. A single server can handle key rotation locally, but if you have deployed a cluster, you must manage key rotation centrally. Admin Web Services # Make sure SCIM and the config API are not Internet facing. If you do expose SCIM, you should network restrict access as much as possible. Although SCIM is protected via OAuth or UMA access tokens, because a breach of SCIM would undermine the integrity of authentications, a multi-layer security approach is warranted. There is no use case for an Internet facing Config API--you should tightly control access to this service. Make sure no services are listening on external interfaces except for those that are absolutely required-- tcp/443 for the OpenID and FIDO endpoints. On Linux servers, a list of current listeners can be obtained with netstat -nlpt (for TCP) and netstat -nlpu (for UDP). In particular, make sure the internal databases used by Gluu to store all its configuration are not Internet facing. OpenID # Review the OAuth 2.0 Security Best Current Practice IETF draft. Don't use the implicit flow. In the implicit flow, the client is not authenticated, and a token is returned from the Authorization endpoint. If the response_type in your OpenID Authentication contains token , you are using the implicit flow. Section 2.1.2 of the current OAuth Security Best Practices OAuth working group draft specifically warns against using the implicit flow. If you must use the implicit flow, Review the CORS filter configuration for Jans Auth Server. CORS restricts access to trusted domains to execute browser application requests to Auth Server endpoints. By default, the filter allows any RP to call OpenID endpoints. Review Auth Server properties chosen for sessionIdUnusedLifetime and sessionIdLifetime . Long sessions present higher risks of session hijacking and unauthorized access from shared devices. OAuth Client Security # The table below summarizes the default values for dynamically registered clients. Attribute Default Value applicationType web subjectType public idTokenSignedResponseAlg RS512 userInfoSignedResponseAlg RS512 userInfoEncryptedResponseAlg RSA-OAEP userInfoEncryptedResponseEnc RSA-OAEP accessTokenLifetime 3600 Consider whether support of OpenID Connect Dynamic Client Registration extension is required. If not, disable it by setting dynamicRegistrationEnabled to False . If Dynamic Client Registration is enabled, consider using software statements , and writing a Client Registration interception script to implement extra rules for software statement validation. Check the list of scopes to quickly assess which scopes the clients can potentially add to their registration entry without consent of OP's administrator. Make sure sensitive scopes are dynamicRegistrationScopesParamEnabled set to False. The Auth Server property dynamicRegistrationScopesParamEnabled controls whether default scopes are globally enabled; scopes defined as default will be automatically added to any dynamically registered client entry. For client authentication at the token endpoint, move away from shared secrets-- use either private key authentication or MTLS . A client secret is basically a password for your software application. Utilize asymmetric client authentication. Make sure your OpenID client applications check the state value, and verify that it is the same state posted in the original request. This is necessary to prevent Cross Site Request Forgery (CSRF). Also make sure that clients use a non-static value for state (i.e. a one time non-guessable value). You can also verify the state in the s_hash claim of the id_token in the authentication response. This may sound obvious, but make sure your clients verify the signature of the id_token. The location of the current public keys of the OpenID Provider can be found in the configuration endpoint ( jwks_uri ). It is also recommended that clients implement a unique redirect_uri per OP. This may also sound obvious, but make sure you trust the OpenID Connect client software library that your developers are using to authenticate users. Also make sure OpenID Connect client libraries are updated expeditiously. Suggest to web developers that they read the OpenID Connect Basic Client Implementer's Guide , which provides a more reader-friendly narrative for how to use the OpenID code flow--the main flow for relying parties. Client developers should consider using a Request Object JWT, which prevents hackers from tampering with the request parameters. Request objects can mitigate the Malicious Endpoint Attack and the IDP confusion attack. Mobile developers should read RFC 8252 OAuth 2.0 for Native Apps and follow the recommendations there. It's really important not to store any client secret or private key in the application, because hackers can decompile applications to extract these secrets. That's why RFC 8252 recommends using PKCE to prevent Authorization Code Interception Attack, and use a SHA256 as the code challenge method. Use App Auth if possible for Android , iOS , or JavaScript . If additional client security is needed, consider using the FAPI profile of OpenID Connect, which adds additional signing, encryption and security mitigations. UMA # The UMA protocol enables post-authentication authorization flows. Consider the following system-level properties: umaGrantAccessIfNoPolicies allows access to a resource even if no policies are defined for the related scopes; though it simplifies initial testing, we recommend disabling this feature in production setups umaRestrictResourceToAssociatedClient won't allow any other client except the one that registered the resource initially to acquire a RPT for it; it's recommended to have it enabled for production setups", "title": "Security Best Practices"}, {"location": "janssen-server/planning/security-best-practices/#scripts", "text": "Make sure only required scripts are enabled. It's extremely important to disable any person authentication or other scripts not in use.", "title": "Scripts"}, {"location": "janssen-server/planning/security-best-practices/#keys", "text": "Use RSA keys with a minimum strength of 2048 bits and Elliptic Curve keys with a minimum of 160 bits. Also, check the key rotation policy of your Auth Server. This differs based on your deployment model. A single server can handle key rotation locally, but if you have deployed a cluster, you must manage key rotation centrally.", "title": "Keys"}, {"location": "janssen-server/planning/security-best-practices/#admin-web-services", "text": "Make sure SCIM and the config API are not Internet facing. If you do expose SCIM, you should network restrict access as much as possible. Although SCIM is protected via OAuth or UMA access tokens, because a breach of SCIM would undermine the integrity of authentications, a multi-layer security approach is warranted. There is no use case for an Internet facing Config API--you should tightly control access to this service. Make sure no services are listening on external interfaces except for those that are absolutely required-- tcp/443 for the OpenID and FIDO endpoints. On Linux servers, a list of current listeners can be obtained with netstat -nlpt (for TCP) and netstat -nlpu (for UDP). In particular, make sure the internal databases used by Gluu to store all its configuration are not Internet facing.", "title": "Admin Web Services"}, {"location": "janssen-server/planning/security-best-practices/#openid", "text": "Review the OAuth 2.0 Security Best Current Practice IETF draft. Don't use the implicit flow. In the implicit flow, the client is not authenticated, and a token is returned from the Authorization endpoint. If the response_type in your OpenID Authentication contains token , you are using the implicit flow. Section 2.1.2 of the current OAuth Security Best Practices OAuth working group draft specifically warns against using the implicit flow. If you must use the implicit flow, Review the CORS filter configuration for Jans Auth Server. CORS restricts access to trusted domains to execute browser application requests to Auth Server endpoints. By default, the filter allows any RP to call OpenID endpoints. Review Auth Server properties chosen for sessionIdUnusedLifetime and sessionIdLifetime . Long sessions present higher risks of session hijacking and unauthorized access from shared devices.", "title": "OpenID"}, {"location": "janssen-server/planning/security-best-practices/#oauth-client-security", "text": "The table below summarizes the default values for dynamically registered clients. Attribute Default Value applicationType web subjectType public idTokenSignedResponseAlg RS512 userInfoSignedResponseAlg RS512 userInfoEncryptedResponseAlg RSA-OAEP userInfoEncryptedResponseEnc RSA-OAEP accessTokenLifetime 3600 Consider whether support of OpenID Connect Dynamic Client Registration extension is required. If not, disable it by setting dynamicRegistrationEnabled to False . If Dynamic Client Registration is enabled, consider using software statements , and writing a Client Registration interception script to implement extra rules for software statement validation. Check the list of scopes to quickly assess which scopes the clients can potentially add to their registration entry without consent of OP's administrator. Make sure sensitive scopes are dynamicRegistrationScopesParamEnabled set to False. The Auth Server property dynamicRegistrationScopesParamEnabled controls whether default scopes are globally enabled; scopes defined as default will be automatically added to any dynamically registered client entry. For client authentication at the token endpoint, move away from shared secrets-- use either private key authentication or MTLS . A client secret is basically a password for your software application. Utilize asymmetric client authentication. Make sure your OpenID client applications check the state value, and verify that it is the same state posted in the original request. This is necessary to prevent Cross Site Request Forgery (CSRF). Also make sure that clients use a non-static value for state (i.e. a one time non-guessable value). You can also verify the state in the s_hash claim of the id_token in the authentication response. This may sound obvious, but make sure your clients verify the signature of the id_token. The location of the current public keys of the OpenID Provider can be found in the configuration endpoint ( jwks_uri ). It is also recommended that clients implement a unique redirect_uri per OP. This may also sound obvious, but make sure you trust the OpenID Connect client software library that your developers are using to authenticate users. Also make sure OpenID Connect client libraries are updated expeditiously. Suggest to web developers that they read the OpenID Connect Basic Client Implementer's Guide , which provides a more reader-friendly narrative for how to use the OpenID code flow--the main flow for relying parties. Client developers should consider using a Request Object JWT, which prevents hackers from tampering with the request parameters. Request objects can mitigate the Malicious Endpoint Attack and the IDP confusion attack. Mobile developers should read RFC 8252 OAuth 2.0 for Native Apps and follow the recommendations there. It's really important not to store any client secret or private key in the application, because hackers can decompile applications to extract these secrets. That's why RFC 8252 recommends using PKCE to prevent Authorization Code Interception Attack, and use a SHA256 as the code challenge method. Use App Auth if possible for Android , iOS , or JavaScript . If additional client security is needed, consider using the FAPI profile of OpenID Connect, which adds additional signing, encryption and security mitigations.", "title": "OAuth Client Security"}, {"location": "janssen-server/planning/security-best-practices/#uma", "text": "The UMA protocol enables post-authentication authorization flows. Consider the following system-level properties: umaGrantAccessIfNoPolicies allows access to a resource even if no policies are defined for the related scopes; though it simplifies initial testing, we recommend disabling this feature in production setups umaRestrictResourceToAssociatedClient won't allow any other client except the one that registered the resource initially to acquire a RPT for it; it's recommended to have it enabled for production setups", "title": "UMA"}, {"location": "janssen-server/planning/self-service-password-2fa/", "tags": ["administration", "planning", "2FA", "self-service", "Account Recovery", "Jans casa"], "text": "If your domain offers two-factor authentication, it's a good idea to enable end users to manage their various credentials. Google does a great job in this regard. Check out 2-Step Verification . What's great about this page is that Google lets you manage all your different credentials on one page. You can build a page like Google on your own website. You need to be able to list, add, and remove 2FA credentials for a given user's account. But another good option is the Jans Casa web application.", "title": "Self-Service Password/2FA Portal"}, {"location": "janssen-server/planning/stepped-up-auth/", "tags": ["administration", "planning", "stepped-up authentication"], "text": "The holy grail of security policies since the introduction of RSA OTP tokens, stepped-up authentication is when the subject is presented with an additional authentication requirement, usually in response to perceived risk. As Jans How do you decide when to invoke stepped-up authentication? As Auth Server is not a policy enforcement point, or a policy management system, these two aspects are out of scope. But once you make a runtime decision that you need more evidence of identity, the OpenID Connect Authentication Request has a few features that can help you out. The first is prompt=login . This is a hint from the Relying Party to the OpenID Provider that re-authentication is needed. Not all OpenID Connect providers support this feature (for example, Google does not). However Auth Server does currently support this parameter, although there is a feature request to make it optional. The second is acr_values . In Auth Server, this provides a hint to the Auth Server to invoke a specific Person Authentication interception script. Typically, this would specify your workflow for additional authentication. If you are using Agama, you can also provide a hint for which Agama flow to invoke by adding __. Another more esoteric strategy is to use UMA claims gathering. In this flow, the subject's browser is directed to the claims gathering endpoint (i.e. front channel), at which point the claims gathering script could invoke an OpenID authentication, using the prompt and acr_values parameters mentioned above. If you want to see an example of how a client implements stepped-up authentication, you should checkout this mod_auth_openidc wiki page .", "title": "Stepped-up Authentication"}, {"location": "janssen-server/planning/timeout-management/", "tags": ["administration", "planning", "timeout"], "text": "Warning: business expectations regarding timeouts may drive you crazy. There are several timeout values in Janssen Auth Server. Also, web apps and mobile apps may have their own timeout thresholds. The holy grail of timeouts is when everything times out at the same time--IDP and applications. This is rarely attainable. Normally the application needs to handle gracefully the case when the IDP session expires first. And if the application session expires first, it may need to trigger a logout event at the OpenID Provider. Below is a list of some of the Auth Server configuration properties for timeouts that you should consider: sessionIdCookieLifetime sessionIdLifetime sessionIdUnusedLifetime sessionIdUnauthenticatedUnusedLifetime spontaneousScopeLifetime refreshTokenLifetime idTokenLifetime accessTokenLifetime cleanServiceInterval dynamicRegistrationExpirationTime refreshTokenExtendLifetimeOnRotation CIBA, UMA and Device Flow : have their own specific timeouts.", "title": "Timeout Management"}, {"location": "janssen-server/planning/use-cases/", "tags": ["administration", "planning", "use-cases", "architecture"], "text": "Browser Single Sign-On (B-SS0) # Web browser SSO is one of the main use cases for Janssen. The OpenID Connect interfaces of the Auth Server provide the identity layer that manages authentication and B-SSO. Auth Server tracks web browser sessions via a cookie. An end user may actually have several active sessions, although only one session is active. For example, below is a hypothetical session cookie: session_id: c691e83d-eb1b-41f0-b453-fab905681b5b current_sessions: [\"de510ab6-b06c-4393-86d8-12a7c501aafe\", \"c691e83d-eb1b-41f0-b453-fab905681b5b\"] To switch sessions, an RP can redirect to the Jans Auth Server OpenID Connect Provider authorization endpoint with the parameters prompt=select_account . Native Single Sign-On (N-SS0) # On most mobile platforms, mobile apps signed by the same vendor certs can share information via the system \"keychain\" (Account Manager on Android). OpenID Mobile SSO specifies a new scope, extends the token endpoint, and profiles the OAuth2 Token Exchange spec allowing mobile apps to share identity between apps produced and signed by the same vendor (i.e. signed with the same vendor certificate). Single Logout (SLO) # The bane of identity engineers everywhere, Auth Server does offer some endpoints that enable SLO. Janssen Auth Server implements Back-Channel Logout and Session Management . But the most commonly used strategy is Front-Channel Logout . This works by displaying a web page with numerous iFrames, each with the respective logout URL for each application. The reason SLO is so hard is that logout is inherently an asynchronous use case. When you need a bunch of websites to receive a notification, some of those notifications may fail. Ideally, you'd replay messages that aren't received. But end users want a fast logout response, and don't want to wait for all the applications to confirm they received and acted on the notification. So making logout synchronous is a round-hole / square-peg situation. But with that said, Auth Server supports it. API Access Management # Janssen Auth Server is frequently used to issue access tokens to authenticate software clients that needs to call an API. The OAuth WG has published many useful specifications about how to do this securely, and Janssen implements many of these RFCs and drafts. In OAuth parlance, Jans Auth Server is the Authorization Server; and Jans Client API is a service that helps clients with advanced features like MTLS and private key authentication. As OAuth scopes are frequently used to control the extent of access of clients, many domains are using Jans Auth Server to dynamically render scopes based on the identity of the client, or the security context. The Jans Auth Server also implements OAuth and OpenID client registration API. Finally, Jans Auth Server publishes an SSA endpoint, for OAuth software statement assertions which enables trusted services to request an SSA that specifies what type of clients can register. All of these features mean that Jans Auth Server is an essential tool as part of your API access management infrastructure. Multifactor Authentication # OpenID Connect is a web identity layer. Auth Server displays and processes a series of web pages to authenticate a person, and then shares user claims with the applications that requested them. Out of the box, Auth Server supports many MFA workflows, including FIDO, passkeys, OATH OTP (HOTP, TOTP), SMS (via Twilio or SMPP), and many more. But you're not limited to the MFA that comes out of the box. Using Person Authentication Scripts, you can implement any authentication workflow that you can imagine. You can also use the Janssen Project's Agama programming language to implement multi-step authentication workflows. Mobile Authentication # One of the initial requirements for OpenID was to support mobile apps (because SAML is terrible for mobile apps). OpenID and OAuth have developed several mitigations that make mobile authentication more secure, which are described in RFC 8252 . However, due to the complexity of cookie sharing between the mobile phone browser SDK, and the mobile browser (assuming you are using the system browser), your results may vary if you actually want SSO. Recently, OpenID has published a new specification draft for Native SSO for Mobile Apps , that is on the roadmap . There are some other hacky ways you can implement mobile authentication, for example, using the OAuth password grant--but this is possible only for first-party applications, and is generally discouraged because there is no way to securely store a client secret in the mobile application, which hackers can easily decompile. Open Banking # You'll notice that the Gluu Open Banking Identity Platform is certified for Financial-grade API (FAPI) 1.0 Final--this is Gluu's distribution of the Janssen Auth Server profiled for banking. If you want to implement an OP for open banking, Jans Auth Server is one of the few comprehensive open-source platforms that will enable you to do so. Social Sign-in # This could really be covered under the MFA section. But it's not uncommon that as part of an authentication workflow, Auth Server may redirect you to an external identity provider, which then sends you back to Auth Server with some kind of reference id or assertion. Out of the box, Jans supports the top three social sites: Google, Apple, and Facebook (which account for 80% of social login). But of course, you can implement any social login using an Agama project. Registration # It's not that uncommon that an authentication workflow is used to create an account for a person in an identity provider. In fact, it's so common, that the OpenID working group recently created a spec to standardize a parameter in the authentication request to signal to the OpenID Provider that this is what's happening: prompt=create . As we're just displaying a series of web pages, we can display a registration form, process the form (with some kind of remote identity proofing?), send an email, SMS, Telegram messages, or whatever. Also, frequently social login is tied to registration--the first time you login with an external IDP, Auth Server creates an account on the fly with the user claims sent by the remote IDP. Authorization # Frequently people conflate the identity layer with the authorization layer. RBAC is still an important security paradigm. So it makes sense to people that the place where you store information about a person's roles is where you define policies about what resources a role can access (i.e. policies). Recently, centralized authorization has had an active resurgence. Companies like Styra , Oso , and HashiCorp have introduced innovative centralized authorization software. These systems, acting as a \"policy decision point\", enable you to define policies, and can evaluate these policies at runtime. Note: they rely on \"policy enforcement points\" to call their endpoints, supplying the data which is input to policies. With that said, there are places in Auth Server where you can define or impact authorization (besides user claims). In particular, OAuth scopes are used to convey the extent of access in an access token, that when presented to an API by a software client, enables access control. However, the scope is still input to policy, and may in fact be just one more piece of data considered by a policy decision point. And one more caveat... the \"authorization\" in an OAuth \"authorization server\", was originally meant to convey the authorization of the person who was trying to access something. Whether a person consented to share information, or grant a client the ability to act on their behalf, is another important consideration. So does \"Auth Server\" provide authorization? It depends! Consent Gathering # Through the \"front channel\" (i.e. the browser), Auth Server can interact with a person by displaying web pages. OpenID Connect and OAuth scopes trigger the authorization phase (after authentication). By default, the scopes requested by the client and their respective descriptions are displayed for approval. However, like all pages in Auth Server, these pages can be customized to meet your exact requirements. Auth Server also implements the User Managed Access Protocol (\"UMA\"). This profile of OAuth2 enables consent to be sought from a person even after the initial authentication has taken place. This phase is also called \"claims gathering\", but one of the claims could be whether a person consents to something. Note: Authorizations are stored relative to a person's entity in the database. How a person views and revokes consent is outside the scope of Auth Server. To view a person's consents, you need to use the config API, as this information is not shared via OpenID Connect or SCIM.", "title": "Use Cases"}, {"location": "janssen-server/planning/use-cases/#browser-single-sign-on-b-ss0", "text": "Web browser SSO is one of the main use cases for Janssen. The OpenID Connect interfaces of the Auth Server provide the identity layer that manages authentication and B-SSO. Auth Server tracks web browser sessions via a cookie. An end user may actually have several active sessions, although only one session is active. For example, below is a hypothetical session cookie: session_id: c691e83d-eb1b-41f0-b453-fab905681b5b current_sessions: [\"de510ab6-b06c-4393-86d8-12a7c501aafe\", \"c691e83d-eb1b-41f0-b453-fab905681b5b\"] To switch sessions, an RP can redirect to the Jans Auth Server OpenID Connect Provider authorization endpoint with the parameters prompt=select_account .", "title": "Browser Single Sign-On (B-SS0)"}, {"location": "janssen-server/planning/use-cases/#native-single-sign-on-n-ss0", "text": "On most mobile platforms, mobile apps signed by the same vendor certs can share information via the system \"keychain\" (Account Manager on Android). OpenID Mobile SSO specifies a new scope, extends the token endpoint, and profiles the OAuth2 Token Exchange spec allowing mobile apps to share identity between apps produced and signed by the same vendor (i.e. signed with the same vendor certificate).", "title": "Native Single Sign-On (N-SS0)"}, {"location": "janssen-server/planning/use-cases/#single-logout-slo", "text": "The bane of identity engineers everywhere, Auth Server does offer some endpoints that enable SLO. Janssen Auth Server implements Back-Channel Logout and Session Management . But the most commonly used strategy is Front-Channel Logout . This works by displaying a web page with numerous iFrames, each with the respective logout URL for each application. The reason SLO is so hard is that logout is inherently an asynchronous use case. When you need a bunch of websites to receive a notification, some of those notifications may fail. Ideally, you'd replay messages that aren't received. But end users want a fast logout response, and don't want to wait for all the applications to confirm they received and acted on the notification. So making logout synchronous is a round-hole / square-peg situation. But with that said, Auth Server supports it.", "title": "Single Logout (SLO)"}, {"location": "janssen-server/planning/use-cases/#api-access-management", "text": "Janssen Auth Server is frequently used to issue access tokens to authenticate software clients that needs to call an API. The OAuth WG has published many useful specifications about how to do this securely, and Janssen implements many of these RFCs and drafts. In OAuth parlance, Jans Auth Server is the Authorization Server; and Jans Client API is a service that helps clients with advanced features like MTLS and private key authentication. As OAuth scopes are frequently used to control the extent of access of clients, many domains are using Jans Auth Server to dynamically render scopes based on the identity of the client, or the security context. The Jans Auth Server also implements OAuth and OpenID client registration API. Finally, Jans Auth Server publishes an SSA endpoint, for OAuth software statement assertions which enables trusted services to request an SSA that specifies what type of clients can register. All of these features mean that Jans Auth Server is an essential tool as part of your API access management infrastructure.", "title": "API Access Management"}, {"location": "janssen-server/planning/use-cases/#multifactor-authentication", "text": "OpenID Connect is a web identity layer. Auth Server displays and processes a series of web pages to authenticate a person, and then shares user claims with the applications that requested them. Out of the box, Auth Server supports many MFA workflows, including FIDO, passkeys, OATH OTP (HOTP, TOTP), SMS (via Twilio or SMPP), and many more. But you're not limited to the MFA that comes out of the box. Using Person Authentication Scripts, you can implement any authentication workflow that you can imagine. You can also use the Janssen Project's Agama programming language to implement multi-step authentication workflows.", "title": "Multifactor Authentication"}, {"location": "janssen-server/planning/use-cases/#mobile-authentication", "text": "One of the initial requirements for OpenID was to support mobile apps (because SAML is terrible for mobile apps). OpenID and OAuth have developed several mitigations that make mobile authentication more secure, which are described in RFC 8252 . However, due to the complexity of cookie sharing between the mobile phone browser SDK, and the mobile browser (assuming you are using the system browser), your results may vary if you actually want SSO. Recently, OpenID has published a new specification draft for Native SSO for Mobile Apps , that is on the roadmap . There are some other hacky ways you can implement mobile authentication, for example, using the OAuth password grant--but this is possible only for first-party applications, and is generally discouraged because there is no way to securely store a client secret in the mobile application, which hackers can easily decompile.", "title": "Mobile Authentication"}, {"location": "janssen-server/planning/use-cases/#open-banking", "text": "You'll notice that the Gluu Open Banking Identity Platform is certified for Financial-grade API (FAPI) 1.0 Final--this is Gluu's distribution of the Janssen Auth Server profiled for banking. If you want to implement an OP for open banking, Jans Auth Server is one of the few comprehensive open-source platforms that will enable you to do so.", "title": "Open Banking"}, {"location": "janssen-server/planning/use-cases/#social-sign-in", "text": "This could really be covered under the MFA section. But it's not uncommon that as part of an authentication workflow, Auth Server may redirect you to an external identity provider, which then sends you back to Auth Server with some kind of reference id or assertion. Out of the box, Jans supports the top three social sites: Google, Apple, and Facebook (which account for 80% of social login). But of course, you can implement any social login using an Agama project.", "title": "Social Sign-in"}, {"location": "janssen-server/planning/use-cases/#registration", "text": "It's not that uncommon that an authentication workflow is used to create an account for a person in an identity provider. In fact, it's so common, that the OpenID working group recently created a spec to standardize a parameter in the authentication request to signal to the OpenID Provider that this is what's happening: prompt=create . As we're just displaying a series of web pages, we can display a registration form, process the form (with some kind of remote identity proofing?), send an email, SMS, Telegram messages, or whatever. Also, frequently social login is tied to registration--the first time you login with an external IDP, Auth Server creates an account on the fly with the user claims sent by the remote IDP.", "title": "Registration"}, {"location": "janssen-server/planning/use-cases/#authorization", "text": "Frequently people conflate the identity layer with the authorization layer. RBAC is still an important security paradigm. So it makes sense to people that the place where you store information about a person's roles is where you define policies about what resources a role can access (i.e. policies). Recently, centralized authorization has had an active resurgence. Companies like Styra , Oso , and HashiCorp have introduced innovative centralized authorization software. These systems, acting as a \"policy decision point\", enable you to define policies, and can evaluate these policies at runtime. Note: they rely on \"policy enforcement points\" to call their endpoints, supplying the data which is input to policies. With that said, there are places in Auth Server where you can define or impact authorization (besides user claims). In particular, OAuth scopes are used to convey the extent of access in an access token, that when presented to an API by a software client, enables access control. However, the scope is still input to policy, and may in fact be just one more piece of data considered by a policy decision point. And one more caveat... the \"authorization\" in an OAuth \"authorization server\", was originally meant to convey the authorization of the person who was trying to access something. Whether a person consented to share information, or grant a client the ability to act on their behalf, is another important consideration. So does \"Auth Server\" provide authorization? It depends!", "title": "Authorization"}, {"location": "janssen-server/planning/use-cases/#consent-gathering", "text": "Through the \"front channel\" (i.e. the browser), Auth Server can interact with a person by displaying web pages. OpenID Connect and OAuth scopes trigger the authorization phase (after authentication). By default, the scopes requested by the client and their respective descriptions are displayed for approval. However, like all pages in Auth Server, these pages can be customized to meet your exact requirements. Auth Server also implements the User Managed Access Protocol (\"UMA\"). This profile of OAuth2 enables consent to be sought from a person even after the initial authentication has taken place. This phase is also called \"claims gathering\", but one of the claims could be whether a person consents to something. Note: Authorizations are stored relative to a person's entity in the database. How a person views and revokes consent is outside the scope of Auth Server. To view a person's consents, you need to use the config API, as this information is not shared via OpenID Connect or SCIM.", "title": "Consent Gathering"}, {"location": "janssen-server/planning/vm-cluster/", "tags": ["administration", "planning", "vm", "cluster"], "text": "Note For high availability, we recommend using the Cloud-Native(CN) deployment instead of VM cluster deployments. What if you need four or five nines availability, but cloud-native is not an option? You could cluster Janssen using VMs, but you'll have to do some legwork, because we don't publish tools for this task. This planning guide will cover some of the things you'll need to consider. Hostname : Remember when you run the Linux setup to use the hostname of the cluster, not the hostname of the individual server. This is important because the OpenID Provider metadata needs to use the public hostname (i.e. the URLs you'll find at /.well-known/openid-configuration ) Load Balancing / SSL : As Auth Server and FIDO (the two Internet facing components) are stateless, you can use any load balancer routing algorithm, even round robin. You can also use the load balancer to terminate SSL. Database : The web services Janssen Components share the database, so you'll have to use database replication. You could also use a cloud database that takes care of replication for you. Cache : You can't use IN-MEMORY cache which would have no way to replicate to the other nodes in the network. You could use the Database for caching, although this will impact performance, although it's only an issue for high concurrency use cases. But if you really need a very high concurrency, our recommendation is to use Redis for caching, which has less cache hit misses than Memcached. Key management : Where do you store the private keys? If on the file system, you'll have to make sure that they get securely copied. This is trickier than it sounds because of key rotation. OpenID Connect working group suggests key rotation every two days, to make sure developers who write OpenID applications handle key rotation properly in their code, and don't hardcode the metadata, but retrieve it from the OpenID configuration endpoint. Customizations : You must copy any libraries, xhtml pages, CSS or javascript must be available on all servers.", "title": "VM Cluster"}, {"location": "janssen-server/planning/vm-single-instance/", "tags": ["administration", "planning", "vm", "single instance"], "text": "While an active-active cluster enables you to achieve four or five nines uptime, you may want to consider a single VM instance if simplicity of operation trumps availability. If you do a good job at monitoring, and can restore from backup quickly, it's certainly possible to meet an SLA of 99.9% availability using just one server. Janssen has Linux packages available for SUSE, Red Hat and Ubuntu. One operational consideration is that you should hold the version of Jans Auth Server, to avoid update during the normal package update process. As many applications may rely on a central IDP, you want to plan updates and have a rollback plan if something goes wrong. An automated, unattended update process for the IDP is too risky. An important security tradeoff when you run Janssen on a single VM is that services which you want to control access to are running on a server with an Internet-facing ethernet interface: the Config API, database, and SCIM server. Even though these services are running on localhost , if the Internet facing interface is compromised, network protection could be bypassed. The main advantage of running a single VM is simplicity. Your sys admins won't need any special training. And it will be easy to install, backup, monitor, and configure your deployment. If you have many autonomous domains, each with its own brand and user identity management process, the simplicity of running a single IDP might be the best solution. If three nines are acceptable to your business, the expense of deploying and operating a cluster may not be justified.", "title": "VM Single Instance"}, {"location": "janssen-server/recipes/ACRouter/", "text": "Janssen's authentication server can integrate with any number of authentication mechanisms from different vendors. Factoring the pros and cons of each method, organizations can offer a diverse set of options. A users can register multiple types of credentials and use any preferred credential to perform a login. An ACRouter Script is a PersonAuthenticationType script orchestrates a 2FA flow by delegating specific implementation details of authentication methods to other scripts. This allows the flow to present users with alternatives in case some credential is not working as expected or is lost. Authentication flow # sequenceDiagram autonumber title User selects authentication mechanism User agent->>Jans AS: Invoke /authorize endpoint Jans AS->>User agent: Present \"username\" only screen <br/> OR <br/>username - password screen User agent->>Jans AS: Present username <br/> OR username and password Jans AS ->> Jans AS: verify user Jans AS->>User agent: Show UI for preferred authentication method, <br>and also a link \"Alternate way to sign in\" loop n times - (enter creds or select alternate way to sign in) User agent->>Jans AS: Enter credentials (Or click on \"Alternate way to sign in\") Jans AS->>User agent: Present page for authentication <br/> or <br/> present alternate authentication mechanisms end Jans AS->Jans AS: 8. validate id_token,<br/>create internal Jans session opt if new user Jans AS->Jans AS: 9. Dynamic enrollment or registration end Jans AS->User agent: 10. write Jans session cookie An ACRouter script : # Currently, the Jans Auth server comes with 2 PersonAuthenticationType interception scripts that integrate multiple authentication methods and offer alternative options to users for sign-in. Casa Script The casa script offers a 2 steps authentication flow with login and password prompted in the first step and a user-preferred authentication mechanism in the second step. Passwordless script The passwordless script offers a 2 steps authentication flow with username prompted in the first step and a user-preferred authentication mechanism in the second step. Casa App for enrollment of a variety of credentials: # Casa is a self-service web portal for end-users can be used to 1. Enroll, delete and manage two-factor authentication (2FA) credentials for their account (e.g. FIDO security keys, mobile apps, phone numbers, etc.) 1. Turn 2FA on and off Adding a new authentication method as an \"alternative authentication method\": # Step 1: Write a custom script: # Ensure the following preconditions are met so that the authentication mehtod integrates seamlessly within flow: 1. The orchestrator script looks for authentication method scripts under /opt/jans/python/libs . Write a custom script that focuses only on authentication. The script file name should follow naming convention like orchestratorName-external_acrName e.g. casa-external_fido2 or pwdless-external_fido2 1. For step 1, prepareForStep must only return True 1. For step 1, getExtraParametersForStep must only return None 1. For step 1, the authenticate routine must check if there is already an authenticated user, and if so bypass validating the username and password. This is because a user may have previously attempted authentication with a different method. 1. Keep in mind that getPageForStep won't be called when step=1 in your script. The orchestrator script i.e. casa or passwordless script takes charge of this specific step/method combination 1. Add a hasEnrollments routine with a signature like this def hasEnrollments(self, configurationAttributes, user): hasEnrollments must return True or False , describing whether user has one or more credentials enrolled for the type you are interested in Objects: Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference User User object Reference Step2: Modification to web-pages: # Ensure that custom pages returned by getPageForStep for step 2 (or higher) contain the fragment: <ui:include src=\"/casa/casa.xhtml\" /> This will display a set of links for the user to navigate to alternate 2FA pages. The list will be shown when clicking on a link which should be provided this way: <a href=\"javascript:showAlternative('ELEMENT_ID')\" id=\"alter_link\" class=\"green hover-green f7-cust\">#{msgs['casa.alternative']}</a> Here ELEMENT_ID is the identifier for the HTML node that wraps all visual elements of your page (excluding casa.xhtml ). It is required to preserve alter_link as id for the a tag. Place the modified xhtml page under the path specified in getPageForStep , for e.g. /opt/jans/jetty/jans-auth/custom/pages/casa/fido2.xhtml Step3: Handle enrollment using the Casa app # Step 4: Enable the ACRouter script i.e. passwordless or casa script # Once your script is enabled in the Jans-auth server, you can test it for authentication purposes. Try your script by creating an authentication request passing casa or passwordless as acr value.", "title": "User Journeys"}, {"location": "janssen-server/recipes/ACRouter/#authentication-flow", "text": "sequenceDiagram autonumber title User selects authentication mechanism User agent->>Jans AS: Invoke /authorize endpoint Jans AS->>User agent: Present \"username\" only screen <br/> OR <br/>username - password screen User agent->>Jans AS: Present username <br/> OR username and password Jans AS ->> Jans AS: verify user Jans AS->>User agent: Show UI for preferred authentication method, <br>and also a link \"Alternate way to sign in\" loop n times - (enter creds or select alternate way to sign in) User agent->>Jans AS: Enter credentials (Or click on \"Alternate way to sign in\") Jans AS->>User agent: Present page for authentication <br/> or <br/> present alternate authentication mechanisms end Jans AS->Jans AS: 8. validate id_token,<br/>create internal Jans session opt if new user Jans AS->Jans AS: 9. Dynamic enrollment or registration end Jans AS->User agent: 10. write Jans session cookie", "title": "Authentication flow"}, {"location": "janssen-server/recipes/ACRouter/#an-acrouter-script", "text": "Currently, the Jans Auth server comes with 2 PersonAuthenticationType interception scripts that integrate multiple authentication methods and offer alternative options to users for sign-in. Casa Script The casa script offers a 2 steps authentication flow with login and password prompted in the first step and a user-preferred authentication mechanism in the second step. Passwordless script The passwordless script offers a 2 steps authentication flow with username prompted in the first step and a user-preferred authentication mechanism in the second step.", "title": "An ACRouter script:"}, {"location": "janssen-server/recipes/ACRouter/#casa-app-for-enrollment-of-a-variety-of-credentials", "text": "Casa is a self-service web portal for end-users can be used to 1. Enroll, delete and manage two-factor authentication (2FA) credentials for their account (e.g. FIDO security keys, mobile apps, phone numbers, etc.) 1. Turn 2FA on and off", "title": "Casa App for enrollment of a variety of credentials:"}, {"location": "janssen-server/recipes/ACRouter/#adding-a-new-authentication-method-as-an-alternative-authentication-method", "text": "", "title": "Adding a new authentication method as an \"alternative authentication method\":"}, {"location": "janssen-server/recipes/ACRouter/#step-1-write-a-custom-script", "text": "Ensure the following preconditions are met so that the authentication mehtod integrates seamlessly within flow: 1. The orchestrator script looks for authentication method scripts under /opt/jans/python/libs . Write a custom script that focuses only on authentication. The script file name should follow naming convention like orchestratorName-external_acrName e.g. casa-external_fido2 or pwdless-external_fido2 1. For step 1, prepareForStep must only return True 1. For step 1, getExtraParametersForStep must only return None 1. For step 1, the authenticate routine must check if there is already an authenticated user, and if so bypass validating the username and password. This is because a user may have previously attempted authentication with a different method. 1. Keep in mind that getPageForStep won't be called when step=1 in your script. The orchestrator script i.e. casa or passwordless script takes charge of this specific step/method combination 1. Add a hasEnrollments routine with a signature like this def hasEnrollments(self, configurationAttributes, user): hasEnrollments must return True or False , describing whether user has one or more credentials enrolled for the type you are interested in Objects: Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference User User object Reference", "title": "Step 1: Write a custom script:"}, {"location": "janssen-server/recipes/ACRouter/#step2-modification-to-web-pages", "text": "Ensure that custom pages returned by getPageForStep for step 2 (or higher) contain the fragment: <ui:include src=\"/casa/casa.xhtml\" /> This will display a set of links for the user to navigate to alternate 2FA pages. The list will be shown when clicking on a link which should be provided this way: <a href=\"javascript:showAlternative('ELEMENT_ID')\" id=\"alter_link\" class=\"green hover-green f7-cust\">#{msgs['casa.alternative']}</a> Here ELEMENT_ID is the identifier for the HTML node that wraps all visual elements of your page (excluding casa.xhtml ). It is required to preserve alter_link as id for the a tag. Place the modified xhtml page under the path specified in getPageForStep , for e.g. /opt/jans/jetty/jans-auth/custom/pages/casa/fido2.xhtml", "title": "Step2: Modification to web-pages:"}, {"location": "janssen-server/recipes/ACRouter/#step3-handle-enrollment-using-the-casa-app", "text": "", "title": "Step3: Handle enrollment using the Casa app"}, {"location": "janssen-server/recipes/ACRouter/#step-4-enable-the-acrouter-script-ie-passwordless-or-casa-script", "text": "Once your script is enabled in the Jans-auth server, you can test it for authentication purposes. Try your script by creating an authentication request passing casa or passwordless as acr value.", "title": "Step 4: Enable the ACRouter script i.e. passwordless or casa script"}, {"location": "janssen-server/recipes/benchmark/", "tags": ["administration", "helm", "kubernetes", "benchmarking"], "text": "Overview # The Janssen Server has been optimized with several container strategies that allow scaling microservices and orchestrating them using Kubernetes. In this tutorial we will be running a load test from three different regions on a janssen setup on three different regions. For simplicity, we will be using microk8s however we do recommend users to use the kubernetes cluster providers that they will be using in production. For instance, we run our loadtests across EKS, GKE, AKS and DOKS. With this procedure the following with a 10 million user database is expected: Results # Note The authorization code flow hits a total of 4 steps, 3 authorization steps /token , /authorize , /jans-auth/login and 1 redirect. Flow Authentications per second Authorization code flow 800-1000 Installation # As mentioned in the overview we recommend using the same Kubernetes cluster as planned in production. More guides to install on different clouds can be found here . Persistence # We recommend your persistence in production to be HA, backup supported and point in time recovery supported. Below is a table of the persistence used and resources set for this test. Persistence # of nodes RAM(GiB) vCPU Total RAM (GiB) Total vCPU MySQL 1 52 8 52 8 Set up the cluster # Kubernetes Cluster Load Test Resources # Note Instance type can be selected to best suit the deployment intended. Keep in mind when selecting the instance type to strive for a 10 or up to 10 network bandwidth (Gbps). Below details the exact resources needed for this tutorial. This is in addition to the persistence resources listed above. Resourcing is critical as timeouts in connections can occur, resulting in failed authentications or cutoffs. Regions # of nodes RAM(GiB) vCPU Total RAM (GiB) Total vCPU US-West 1 96 48 96 48 US-East 1 96 48 96 48 EU-Central 1 96 48 96 48 Grand Total 288 GB 144 A Kubernetes cluster can be created with three nodes or more in one region and that's fine as long as the nodes are in multiple zones. We will continue with the above table and using microk8s . Create three ubuntu 22.04 nodes and run on each one the following: sudo snap install microk8s --classic sudo snap alias microk8s.kubectl kubectl 2. Designate one of the nodes as the master. We will choose the us-west node to be our master. On the master node run: Execute : microk8s.enable ingress dashboard observability dns metrics-server hostpath-storage registry All the other microk8s nodes must be resolvable from within the master. If fqdns are not globally resolved (registered) open the /etc/hosts file in the master node and map each hostname of the other nodes. YThe hostname of the other nodes can be obtained by executing the command hostname . # If the hostnames are not globally resolvable on master echo \"192.123.123.123 ubuntu-us-east\" >> /etc/hosts echo \"192.124.124.124 ubuntu-eu-central\" >> /etc/hosts 3. Execute: microk8s add-node Copy the output of the command above with --worker i.e. microk8s join 192.12.12.12:25000/88687d1cc5ecdee0db5014c4df9b82cb/adedf6a730eb --worker and execute it in the other nodes (worker nodes) to join them. Step iii ( this step) needs to be repeated for each worker node. Make sure helm is installed. Prepare your override.yaml . Copy the below into a file named override.yaml. At the time of writing this we are using image tags 0.0.0-nightly_dev which are the bleeding edge images for release 0.0.0-nightly . Stable images such as 0.0.0-nightly-1 should be used. config : image : repository : ghcr.io/janssenproject/jans/configurator tag : 0.0.0-nightly_dev countryCode : US email : support@gluu.org orgName : Gluu city : Austin configmap : cnSqlDbName : test cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : mycool.cloud.mysql cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# global : auth-server : enabled : true config-api : enabled : true cnPersistenceType : sql cloud : testEnviroment : false fqdn : example.gluu.info isFqdnRegistered : true # In the event the fqdn above is not resolvable from the internet comment the above line and uncomment the below two setting your lbIp to your master ndoe ip. #isFqdnRegistered: false #lbIp: 192.12.12.12 istio : enabled : false ingress : false nginx-ingress : enabled : true fido2 : enabled : false ingress : fido2ConfigEnabled : false scim : enabled : false ingress : scimConfigEnabled : false scimEnabled : false auth-server : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/auth-server tag : 0.0.0-nightly_dev config-api : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/config-api tag : 0.0.0-nightly_dev persistence : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/persistence-loader tag : 0.0.0-nightly_dev nginx-ingress : ingress : path : / hosts : - example.gluu.info tls : - secretName : tls-certificate hosts : - example.gluu.info Run the following: kubectl create ns jans helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml Load-test # Our tests used 10 million users that were loaded. We have created a docker image to load users. That same image is also used to load test Janssen using jmeter tests for the Authorization code flow. More tests will come!. This image will load users and use a unique password for each user. Loading users # Loading users requires a hefty but temporary amount of resources. By default, the resources ask for 10 vCPU and 5 Gis. However, to speed up the process increase the number of CPUs as the job in step two below uses parallel tasks. If left as is 10 million users would load in around 17 hours or so. Create a folder called add_users . mkdir -p add_users && cd add_users Copy the following yaml into the folder under the name load_users.yaml . Open the file and modify the required parameters. Note that the following environments can be used as configmaps data to configure the pod. ENV Description Default TEST_USERS_PREFIX_STRING The user prefix string attached to the test users loaded test_user USER_NUMBER_STARTING_POINT The user number to start from . This is appended to the username i.e test_user0 0 USER_NUMBER_ENDING_POINT The user number to end at. 50000000 LOAD_USERS_TO_RDBMS Enable loading users to RDBMS persistence. true or false == `` false USER_SPLIT_PARALLEL_THREADS The number of parallel threads to break the total number users across. This number heavily effects vCPU usage. 20 RDBMS_TYPE RDBMS type if mysql or pgsql is the persistence to load users in. mysql RDBMS_DB RDBMS Database name if mysql or pgsql is the persistence to load users in. jans RDBMS_USER RDBMS user if mysql or pgsql is the persistence to load users in. jans RDBMS_PASSWORD RDBMS user password if mysql or pgsql is the persistence to load users in. . `` RDBMS_HOST RDBMS host if mysql or pgsql is the persistence to load users in. localhost Tips: To speed the loading process, increase the vCPU requests and limits of the pod. Create a namespace for load-testing. kubectl create ns load Create load_users.yaml kubectl create -f load_users.yaml -n load cd .. Wait until all the users are up before moving forward. Tail the logs by running kubectl logs deployment/load-users -n load . Load testing # Authorization code flow # Resources needed for Authorization code client jmeter test # The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU Authorization code flow jmeter test 20 8 1.3 190 24 Grand Total 190 GiB 24 Setup Client # Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > auth_code_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"Auth Code Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"Auth Code Flow Load Testing Client\" } EOF 3. Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = auth_code_client.json Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_auth_code.yaml under AUTHZ_CLIENT_ID , AUTHZ_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_auth_code.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-authz -n load --replicas=20 Resource Owner Password Credentials (ROPC) flow # Resources needed for ROPC client jmeter test # The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU ROPC flow jmeter test 20 8 1.3 190 24 Grand Total 190 GiB 24 Setup Client # Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > ropc_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"ROPC Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\", \"password\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"ROPC Flow Load Testing Client\" } EOF Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = ropc_client.json Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_ropc.yaml under ROPC_CLIENT_ID , ROPC_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_ropc.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-ropc -n load --replicas=20 DCR flow # Resources needed for DCR client jmeter test # The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU DCR test 20 8 1.3 190 24 Grand Total 190 GiB 24 Setup Client # Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > dcr_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"DCR Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\", \"password\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"DCR Flow Load Testing Client\" } EOF Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = dcr_client.json You will need to load the sectorIdentifier into your persistence.For MySQL that statement would be the following taking into account the FQDN : INSERT INTO jansSectorIdentifier ( doc_id , dn , jansId , jansRedirectURI , objectClass ) VALUES ( 'a55ede29-8f5a-461d-b06e-76caee8d40b5' , 'jansId=a55ede29-8f5a-461d-b06e-76caee8d40b5,ou=sector_identifiers,o=jans' , 'a55ede29-8f5a-461d-b06e-76caee8d40b5' , '{\"v\": [\"https://www.jans.org\", \"http://localhost:80/jans-auth-rp/home.htm\", \"https://localhost:8443/jans-auth-rp/home.htm\", \"https://$FQDN/jans-auth-rp/home.htm\", \"https://$FQDN/jans-auth-client/test/resources/jwks.json\", \"https://client.example.org/callback\", \"https://client.example.org/callback2\", \"https://client.other_company.example.net/callback\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\"]}' , 'jansSectorIdentifier' ); Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_ropc.yaml under DCR_CLIENT_ID , DCR_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_dcr.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-ropc -n load --replicas=20", "title": "Benchmark"}, {"location": "janssen-server/recipes/benchmark/#overview", "text": "The Janssen Server has been optimized with several container strategies that allow scaling microservices and orchestrating them using Kubernetes. In this tutorial we will be running a load test from three different regions on a janssen setup on three different regions. For simplicity, we will be using microk8s however we do recommend users to use the kubernetes cluster providers that they will be using in production. For instance, we run our loadtests across EKS, GKE, AKS and DOKS. With this procedure the following with a 10 million user database is expected:", "title": "Overview"}, {"location": "janssen-server/recipes/benchmark/#results", "text": "Note The authorization code flow hits a total of 4 steps, 3 authorization steps /token , /authorize , /jans-auth/login and 1 redirect. Flow Authentications per second Authorization code flow 800-1000", "title": "Results"}, {"location": "janssen-server/recipes/benchmark/#installation", "text": "As mentioned in the overview we recommend using the same Kubernetes cluster as planned in production. More guides to install on different clouds can be found here .", "title": "Installation"}, {"location": "janssen-server/recipes/benchmark/#persistence", "text": "We recommend your persistence in production to be HA, backup supported and point in time recovery supported. Below is a table of the persistence used and resources set for this test. Persistence # of nodes RAM(GiB) vCPU Total RAM (GiB) Total vCPU MySQL 1 52 8 52 8", "title": "Persistence"}, {"location": "janssen-server/recipes/benchmark/#set-up-the-cluster", "text": "", "title": "Set up the cluster"}, {"location": "janssen-server/recipes/benchmark/#kubernetes-cluster-load-test-resources", "text": "Note Instance type can be selected to best suit the deployment intended. Keep in mind when selecting the instance type to strive for a 10 or up to 10 network bandwidth (Gbps). Below details the exact resources needed for this tutorial. This is in addition to the persistence resources listed above. Resourcing is critical as timeouts in connections can occur, resulting in failed authentications or cutoffs. Regions # of nodes RAM(GiB) vCPU Total RAM (GiB) Total vCPU US-West 1 96 48 96 48 US-East 1 96 48 96 48 EU-Central 1 96 48 96 48 Grand Total 288 GB 144 A Kubernetes cluster can be created with three nodes or more in one region and that's fine as long as the nodes are in multiple zones. We will continue with the above table and using microk8s . Create three ubuntu 22.04 nodes and run on each one the following: sudo snap install microk8s --classic sudo snap alias microk8s.kubectl kubectl 2. Designate one of the nodes as the master. We will choose the us-west node to be our master. On the master node run: Execute : microk8s.enable ingress dashboard observability dns metrics-server hostpath-storage registry All the other microk8s nodes must be resolvable from within the master. If fqdns are not globally resolved (registered) open the /etc/hosts file in the master node and map each hostname of the other nodes. YThe hostname of the other nodes can be obtained by executing the command hostname . # If the hostnames are not globally resolvable on master echo \"192.123.123.123 ubuntu-us-east\" >> /etc/hosts echo \"192.124.124.124 ubuntu-eu-central\" >> /etc/hosts 3. Execute: microk8s add-node Copy the output of the command above with --worker i.e. microk8s join 192.12.12.12:25000/88687d1cc5ecdee0db5014c4df9b82cb/adedf6a730eb --worker and execute it in the other nodes (worker nodes) to join them. Step iii ( this step) needs to be repeated for each worker node. Make sure helm is installed. Prepare your override.yaml . Copy the below into a file named override.yaml. At the time of writing this we are using image tags 0.0.0-nightly_dev which are the bleeding edge images for release 0.0.0-nightly . Stable images such as 0.0.0-nightly-1 should be used. config : image : repository : ghcr.io/janssenproject/jans/configurator tag : 0.0.0-nightly_dev countryCode : US email : support@gluu.org orgName : Gluu city : Austin configmap : cnSqlDbName : test cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : mycool.cloud.mysql cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# global : auth-server : enabled : true config-api : enabled : true cnPersistenceType : sql cloud : testEnviroment : false fqdn : example.gluu.info isFqdnRegistered : true # In the event the fqdn above is not resolvable from the internet comment the above line and uncomment the below two setting your lbIp to your master ndoe ip. #isFqdnRegistered: false #lbIp: 192.12.12.12 istio : enabled : false ingress : false nginx-ingress : enabled : true fido2 : enabled : false ingress : fido2ConfigEnabled : false scim : enabled : false ingress : scimConfigEnabled : false scimEnabled : false auth-server : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/auth-server tag : 0.0.0-nightly_dev config-api : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/config-api tag : 0.0.0-nightly_dev persistence : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/persistence-loader tag : 0.0.0-nightly_dev nginx-ingress : ingress : path : / hosts : - example.gluu.info tls : - secretName : tls-certificate hosts : - example.gluu.info Run the following: kubectl create ns jans helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml", "title": "Kubernetes Cluster Load Test Resources"}, {"location": "janssen-server/recipes/benchmark/#load-test", "text": "Our tests used 10 million users that were loaded. We have created a docker image to load users. That same image is also used to load test Janssen using jmeter tests for the Authorization code flow. More tests will come!. This image will load users and use a unique password for each user.", "title": "Load-test"}, {"location": "janssen-server/recipes/benchmark/#loading-users", "text": "Loading users requires a hefty but temporary amount of resources. By default, the resources ask for 10 vCPU and 5 Gis. However, to speed up the process increase the number of CPUs as the job in step two below uses parallel tasks. If left as is 10 million users would load in around 17 hours or so. Create a folder called add_users . mkdir -p add_users && cd add_users Copy the following yaml into the folder under the name load_users.yaml . Open the file and modify the required parameters. Note that the following environments can be used as configmaps data to configure the pod. ENV Description Default TEST_USERS_PREFIX_STRING The user prefix string attached to the test users loaded test_user USER_NUMBER_STARTING_POINT The user number to start from . This is appended to the username i.e test_user0 0 USER_NUMBER_ENDING_POINT The user number to end at. 50000000 LOAD_USERS_TO_RDBMS Enable loading users to RDBMS persistence. true or false == `` false USER_SPLIT_PARALLEL_THREADS The number of parallel threads to break the total number users across. This number heavily effects vCPU usage. 20 RDBMS_TYPE RDBMS type if mysql or pgsql is the persistence to load users in. mysql RDBMS_DB RDBMS Database name if mysql or pgsql is the persistence to load users in. jans RDBMS_USER RDBMS user if mysql or pgsql is the persistence to load users in. jans RDBMS_PASSWORD RDBMS user password if mysql or pgsql is the persistence to load users in. . `` RDBMS_HOST RDBMS host if mysql or pgsql is the persistence to load users in. localhost Tips: To speed the loading process, increase the vCPU requests and limits of the pod. Create a namespace for load-testing. kubectl create ns load Create load_users.yaml kubectl create -f load_users.yaml -n load cd .. Wait until all the users are up before moving forward. Tail the logs by running kubectl logs deployment/load-users -n load .", "title": "Loading users"}, {"location": "janssen-server/recipes/benchmark/#load-testing", "text": "", "title": "Load testing"}, {"location": "janssen-server/recipes/benchmark/#authorization-code-flow", "text": "", "title": "Authorization code flow"}, {"location": "janssen-server/recipes/benchmark/#resources-needed-for-authorization-code-client-jmeter-test", "text": "The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU Authorization code flow jmeter test 20 8 1.3 190 24 Grand Total 190 GiB 24", "title": "Resources needed for Authorization code client jmeter test"}, {"location": "janssen-server/recipes/benchmark/#setup-client", "text": "Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > auth_code_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"Auth Code Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"Auth Code Flow Load Testing Client\" } EOF 3. Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = auth_code_client.json Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_auth_code.yaml under AUTHZ_CLIENT_ID , AUTHZ_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_auth_code.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-authz -n load --replicas=20", "title": "Setup Client"}, {"location": "janssen-server/recipes/benchmark/#resource-owner-password-credentials-ropc-flow", "text": "", "title": "Resource Owner Password Credentials (ROPC) flow"}, {"location": "janssen-server/recipes/benchmark/#resources-needed-for-ropc-client-jmeter-test", "text": "The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU ROPC flow jmeter test 20 8 1.3 190 24 Grand Total 190 GiB 24", "title": "Resources needed for ROPC client jmeter test"}, {"location": "janssen-server/recipes/benchmark/#setup-client_1", "text": "Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > ropc_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"ROPC Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\", \"password\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"ROPC Flow Load Testing Client\" } EOF Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = ropc_client.json Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_ropc.yaml under ROPC_CLIENT_ID , ROPC_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_ropc.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-ropc -n load --replicas=20", "title": "Setup Client"}, {"location": "janssen-server/recipes/benchmark/#dcr-flow", "text": "", "title": "DCR flow"}, {"location": "janssen-server/recipes/benchmark/#resources-needed-for-dcr-client-jmeter-test", "text": "The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU DCR test 20 8 1.3 190 24 Grand Total 190 GiB 24", "title": "Resources needed for DCR client jmeter test"}, {"location": "janssen-server/recipes/benchmark/#setup-client_2", "text": "Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > dcr_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"DCR Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\", \"password\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"DCR Flow Load Testing Client\" } EOF Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = dcr_client.json You will need to load the sectorIdentifier into your persistence.For MySQL that statement would be the following taking into account the FQDN : INSERT INTO jansSectorIdentifier ( doc_id , dn , jansId , jansRedirectURI , objectClass ) VALUES ( 'a55ede29-8f5a-461d-b06e-76caee8d40b5' , 'jansId=a55ede29-8f5a-461d-b06e-76caee8d40b5,ou=sector_identifiers,o=jans' , 'a55ede29-8f5a-461d-b06e-76caee8d40b5' , '{\"v\": [\"https://www.jans.org\", \"http://localhost:80/jans-auth-rp/home.htm\", \"https://localhost:8443/jans-auth-rp/home.htm\", \"https://$FQDN/jans-auth-rp/home.htm\", \"https://$FQDN/jans-auth-client/test/resources/jwks.json\", \"https://client.example.org/callback\", \"https://client.example.org/callback2\", \"https://client.other_company.example.net/callback\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\"]}' , 'jansSectorIdentifier' ); Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_ropc.yaml under DCR_CLIENT_ID , DCR_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_dcr.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-ropc -n load --replicas=20", "title": "Setup Client"}, {"location": "janssen-server/recipes/device-flow-config/", "tags": ["administration", "recipes", "device flow"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Authentication via Device Flow"}, {"location": "janssen-server/recipes/device-flow-config/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/recipes/device-flow-config/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/recipes/device-flow-config/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/recipes/inbound-oidc/", "tags": ["administration", "recipe", "openid-connect", "inbound", "authentication"], "text": "Inbound OpenId-Connect Authentication # In this tutorial, we will see how you can integrate any inbound external oauth2 provider authentication in the Janssen server. If you are looking for social login support then check out passport module for that. We will use interception authentication script which is a PersonAuthenticationType script for whole flow. Currently, It supports Authorization Code Flow and client_secret_post token endpoint auth method. Authentication Flow # You can add any external OAuth2 server authentication option and provision authenticated users to your Janssen server A.K.A. Inbound-identity. sequenceDiagram title OIDC Inbound Identity Flow participant browser as Browser participant rp as RP participant jans as Jans Authz Server participant eidp as External Provider autonumber browser->>rp: Request page browser->>jans: Invoke /authorize endpoint jans->>browser: Present \"Login with OAuth2\" button browser->>browser: User click on button browser->>eidp: Redirect login request loop n times - (multistep authentication) eidp->>browser: Present login screen browser->>eidp: Present login credentials end eidp->>eidp: Authenticate user eidp->>jans: Redirect to callback url with success response(code) jans->>jans: Validate code, id_token, userinfo opt if new user jans->>jans: Dynamic enrollment or registration end jans->>jans: Create internal Jans session jans->>rp: Redirect with Success response rp->>rp: Validate response rp->>browser: Page is accessed Prerequisites # The external oauth2 server authentication script External OAuth2 Provider credentials: you can choose any external OP server that follows OAuth2 standards and authentication features. RP application: This is your application that will be used by your users and where you want to add this auth feature. Configure Janssen server # 1. Add Custom Script # Create cs.json with the contents of a CUSTOM script. Edit the cs.json file's contents to reflect the addition of the oidc custom script. Populate the script field with oidc-jans-script.py script. Download oidc-jans-script.py script from here. This script needs to accept one property oidc_creds_file . which is a JSON file with your external oauth2 server details: // oidc_creds_file: /opt/oidc.json { \"op_server\": \"https://your.external.oauth2.server\", \"client_id\": \"xxxxxxxxxxxxxxxx-xxxxx-external-oauth2\", \"client_secret\": \"xxxxxxxxxxxxxx-xxxxx-external-oauth2\", \"authorization_uri\": \"https://your.external.oauth2.server/xx/xxxx\", \"token_uri\": \"https://your.external.oauth2.server/oauth/xx/xxx\", \"userinfo_uri\": \"https://your.external.oauth2.server/xxx/xxx\", \"redirect_uri\": \"https://your.jans.server/jans-auth/postlogin.htm\", \"scope\": \"openid profile email\", \"auto_redirect\": false, \"title\": \"Login with OAuth2\" } Property Description op_server Your external OAuth2 server FQDN client_id Client id of your external OAuth2 server client_secret Client secret of your external OAuth2 server authorization_uri Authorization endpoint of your external OAuth2 server token_uri Token endpoint of your external OAuth2 server userinfo_uri Userinfo endpoint of your external OAuth2 server redirect_uri Sample: https://<your.jans.server>/jans-auth/postlogin.htm , This is redirect URL where your OAuth2 server redirect back with code . Use this same URL to configure redirect urls at your external OAuth2 server. scope OAuth scopes auto_redirect If true, it will automatically redirect to external OAuth2 server otherwise you will get one button on jans login page. title This property is used to set text for a button which is shown on jans login page name field should reflect the use case i.e. oidc script_type field should be PERSON_AUTHENTICATION cs.json example: { \"dn\": null, \"inum\": null, \"name\": \"oidc\", \"aliases\": [], \"description\": \"OIDC Inbound custom script\", \"script\": \"_file /root/oidc-jans-script.py\", \"scriptType\": \"PERSON_AUTHENTICATION\", \"programmingLanguage\": \"JYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": [ { \"value1\": \"oidc_creds_file\", \"value2\": \"/opt/oidc.json\", \"description\": \"External server details\", \"hide\": true } ], \"level\": \"integer\", \"revision\": 0, \"enabled\": true, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } Add the custom script jans cli --operation-id post-config-scripts --data /tmp/cs.json 2. Login Page Setup # OIDC Script needs a login page Download oidc-jans-login.xhtml from here Place it here /opt/jans/jetty/jans-auth/custom/pages/auth/oidc/ . If folders are not there then create them in the same order. Rename it to oidc.xhtml . Restart jans-auth server service jans-auth restart Check here for more details on custom login page. Now oidc script is an available authentication mechanism for your Janssen Server. This means that using OpenID Connect acr_values , applications can now request your external auth server for authentication. !!! Note To make sure oidc script has been enabled successfully, you can check your Janssen Server's OpenID Connect configuration by navigating to the following URL: https://<hostname>/.well-known/openid-configuration . Find acr_values_supported: and you should see oidc . Test with RP Client # RP(Relying party) is an application that will be used by your users when you want to add authentication and protect resources. Once you initiate auth request from your RP Application make sure to add acr_values=oidc in the request. acr_values is your script name as configured above.", "title": "Inbound OIDC"}, {"location": "janssen-server/recipes/inbound-oidc/#inbound-openid-connect-authentication", "text": "In this tutorial, we will see how you can integrate any inbound external oauth2 provider authentication in the Janssen server. If you are looking for social login support then check out passport module for that. We will use interception authentication script which is a PersonAuthenticationType script for whole flow. Currently, It supports Authorization Code Flow and client_secret_post token endpoint auth method.", "title": "Inbound OpenId-Connect Authentication"}, {"location": "janssen-server/recipes/inbound-oidc/#authentication-flow", "text": "You can add any external OAuth2 server authentication option and provision authenticated users to your Janssen server A.K.A. Inbound-identity. sequenceDiagram title OIDC Inbound Identity Flow participant browser as Browser participant rp as RP participant jans as Jans Authz Server participant eidp as External Provider autonumber browser->>rp: Request page browser->>jans: Invoke /authorize endpoint jans->>browser: Present \"Login with OAuth2\" button browser->>browser: User click on button browser->>eidp: Redirect login request loop n times - (multistep authentication) eidp->>browser: Present login screen browser->>eidp: Present login credentials end eidp->>eidp: Authenticate user eidp->>jans: Redirect to callback url with success response(code) jans->>jans: Validate code, id_token, userinfo opt if new user jans->>jans: Dynamic enrollment or registration end jans->>jans: Create internal Jans session jans->>rp: Redirect with Success response rp->>rp: Validate response rp->>browser: Page is accessed", "title": "Authentication Flow"}, {"location": "janssen-server/recipes/inbound-oidc/#prerequisites", "text": "The external oauth2 server authentication script External OAuth2 Provider credentials: you can choose any external OP server that follows OAuth2 standards and authentication features. RP application: This is your application that will be used by your users and where you want to add this auth feature.", "title": "Prerequisites"}, {"location": "janssen-server/recipes/inbound-oidc/#configure-janssen-server", "text": "", "title": "Configure Janssen server"}, {"location": "janssen-server/recipes/inbound-oidc/#1-add-custom-script", "text": "Create cs.json with the contents of a CUSTOM script. Edit the cs.json file's contents to reflect the addition of the oidc custom script. Populate the script field with oidc-jans-script.py script. Download oidc-jans-script.py script from here. This script needs to accept one property oidc_creds_file . which is a JSON file with your external oauth2 server details: // oidc_creds_file: /opt/oidc.json { \"op_server\": \"https://your.external.oauth2.server\", \"client_id\": \"xxxxxxxxxxxxxxxx-xxxxx-external-oauth2\", \"client_secret\": \"xxxxxxxxxxxxxx-xxxxx-external-oauth2\", \"authorization_uri\": \"https://your.external.oauth2.server/xx/xxxx\", \"token_uri\": \"https://your.external.oauth2.server/oauth/xx/xxx\", \"userinfo_uri\": \"https://your.external.oauth2.server/xxx/xxx\", \"redirect_uri\": \"https://your.jans.server/jans-auth/postlogin.htm\", \"scope\": \"openid profile email\", \"auto_redirect\": false, \"title\": \"Login with OAuth2\" } Property Description op_server Your external OAuth2 server FQDN client_id Client id of your external OAuth2 server client_secret Client secret of your external OAuth2 server authorization_uri Authorization endpoint of your external OAuth2 server token_uri Token endpoint of your external OAuth2 server userinfo_uri Userinfo endpoint of your external OAuth2 server redirect_uri Sample: https://<your.jans.server>/jans-auth/postlogin.htm , This is redirect URL where your OAuth2 server redirect back with code . Use this same URL to configure redirect urls at your external OAuth2 server. scope OAuth scopes auto_redirect If true, it will automatically redirect to external OAuth2 server otherwise you will get one button on jans login page. title This property is used to set text for a button which is shown on jans login page name field should reflect the use case i.e. oidc script_type field should be PERSON_AUTHENTICATION cs.json example: { \"dn\": null, \"inum\": null, \"name\": \"oidc\", \"aliases\": [], \"description\": \"OIDC Inbound custom script\", \"script\": \"_file /root/oidc-jans-script.py\", \"scriptType\": \"PERSON_AUTHENTICATION\", \"programmingLanguage\": \"JYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": [ { \"value1\": \"oidc_creds_file\", \"value2\": \"/opt/oidc.json\", \"description\": \"External server details\", \"hide\": true } ], \"level\": \"integer\", \"revision\": 0, \"enabled\": true, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } Add the custom script jans cli --operation-id post-config-scripts --data /tmp/cs.json", "title": "1. Add Custom Script"}, {"location": "janssen-server/recipes/inbound-oidc/#2-login-page-setup", "text": "OIDC Script needs a login page Download oidc-jans-login.xhtml from here Place it here /opt/jans/jetty/jans-auth/custom/pages/auth/oidc/ . If folders are not there then create them in the same order. Rename it to oidc.xhtml . Restart jans-auth server service jans-auth restart Check here for more details on custom login page. Now oidc script is an available authentication mechanism for your Janssen Server. This means that using OpenID Connect acr_values , applications can now request your external auth server for authentication. !!! Note To make sure oidc script has been enabled successfully, you can check your Janssen Server's OpenID Connect configuration by navigating to the following URL: https://<hostname>/.well-known/openid-configuration . Find acr_values_supported: and you should see oidc .", "title": "2. Login Page Setup"}, {"location": "janssen-server/recipes/inbound-oidc/#test-with-rp-client", "text": "RP(Relying party) is an application that will be used by your users when you want to add authentication and protect resources. Once you initiate auth request from your RP Application make sure to add acr_values=oidc in the request. acr_values is your script name as configured above.", "title": "Test with RP Client"}, {"location": "janssen-server/recipes/locking-accounts/", "tags": ["administration", "recipes"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Locking or Disabling Accounts"}, {"location": "janssen-server/recipes/locking-accounts/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/recipes/locking-accounts/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/recipes/locking-accounts/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/recipes/password-expirations/", "tags": ["administration", "recipes"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Password Expirations"}, {"location": "janssen-server/recipes/password-expirations/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/recipes/password-expirations/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/recipes/password-expirations/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/recipes/registration/", "tags": ["administration", "recipes"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Registration"}, {"location": "janssen-server/recipes/registration/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/recipes/registration/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/recipes/registration/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/recipes/social-login/", "tags": ["administration", "Social login", "Google", "Apple", "Facebook"], "text": "Implementing Social logins # You can use a PersonAuthenticationType script to allow users to sign using credentials from popular Social Identity providers or Inbound Identity Providers like Facebook, Google and Apple. After users authenticate, we provision their Social Identity Provider credentials into the Jans-auth server. No additional username, password, credentials are needed for this user. Facebook Google Apple Following is a high-level diagram depicting a typical flow - user authentication on a Social Identity Platform and subsequent user provisioning on Jans-Auth server. You can copy paste this sequence in https://sequencediagram.org/ title Social login Jans AS<-User agent: 1. Invoke /authorize endpoint Jans AS->User agent: 2. Discovery: Present list of remote IDPs (Google, Apple, FB...) User agent->Jans AS: 3. Select IDP (e.g. click on button) Jans AS->Social login Identity Provider: 4. Redirects login request to IDP loop n times - (multistep authentication) Social login Identity Provider->User agent: 5. present login screen User agent->Social login Identity Provider: 6. present credentials end Social login Identity Provider->Jans AS: 7. return id_token, user claims Jans AS->Jans AS: 8. validate id_token,\\ncreate internal Jans session opt if new user Jans AS->Jans AS: 9. Dynamic enrollment or registration end Jans AS->User agent: 10. write Jans session cookie User provisioning # After a user has logged in at an external provider a new record is added in local database - or updated if the user is known. To determine if a user was already added, a string is composed with the provider name and the user ID. For example, if user \"MrBrown123\" has logged in at Twitter, the string would look like passport-twitter:mrbrown123 . A database search is performed for a match in the people branch for an entry where attribute jansExtUid equals passport-twitter:mrbrown123 . If there are no matches, an entry is added using the values received from the external provider (after having applied the corresponding attribute mapping) attaching the computed value for jansExtUid . The user profile can contain single or multivalued attributes. \ud83d\udcdd The prefix passport-<provider-name> is used to keep the code compatible with the Passport.js implementation for Inbound Identity", "title": "Social Login"}, {"location": "janssen-server/recipes/social-login/#implementing-social-logins", "text": "You can use a PersonAuthenticationType script to allow users to sign using credentials from popular Social Identity providers or Inbound Identity Providers like Facebook, Google and Apple. After users authenticate, we provision their Social Identity Provider credentials into the Jans-auth server. No additional username, password, credentials are needed for this user. Facebook Google Apple Following is a high-level diagram depicting a typical flow - user authentication on a Social Identity Platform and subsequent user provisioning on Jans-Auth server. You can copy paste this sequence in https://sequencediagram.org/ title Social login Jans AS<-User agent: 1. Invoke /authorize endpoint Jans AS->User agent: 2. Discovery: Present list of remote IDPs (Google, Apple, FB...) User agent->Jans AS: 3. Select IDP (e.g. click on button) Jans AS->Social login Identity Provider: 4. Redirects login request to IDP loop n times - (multistep authentication) Social login Identity Provider->User agent: 5. present login screen User agent->Social login Identity Provider: 6. present credentials end Social login Identity Provider->Jans AS: 7. return id_token, user claims Jans AS->Jans AS: 8. validate id_token,\\ncreate internal Jans session opt if new user Jans AS->Jans AS: 9. Dynamic enrollment or registration end Jans AS->User agent: 10. write Jans session cookie", "title": "Implementing Social logins"}, {"location": "janssen-server/recipes/social-login/#user-provisioning", "text": "After a user has logged in at an external provider a new record is added in local database - or updated if the user is known. To determine if a user was already added, a string is composed with the provider name and the user ID. For example, if user \"MrBrown123\" has logged in at Twitter, the string would look like passport-twitter:mrbrown123 . A database search is performed for a match in the people branch for an entry where attribute jansExtUid equals passport-twitter:mrbrown123 . If there are no matches, an entry is added using the values received from the external provider (after having applied the corresponding attribute mapping) attaching the computed value for jansExtUid . The user profile can contain single or multivalued attributes. \ud83d\udcdd The prefix passport-<provider-name> is used to keep the code compatible with the Passport.js implementation for Inbound Identity", "title": "User provisioning"}, {"location": "janssen-server/recipes/stepped-up-authn/", "text": "tags: - administration - recipes - stepped-up authentication - Update token - modify access token - scope What is Stepped Up Authentication ? # While navigating through an application, a user is challenged to produce an additional authentication when a certain API (of higher criticality) accessed by the client, does not have the needed scope. Consider the following sequence of events : 1. A user is logged in to an app using very basic authentication mechanism. Say login- password. 2. The user navigates through the app. 3. When the user attempts to access a critical resource, he is presented with another authentication step say otp. 4. The user, after successful authentication, has the needed access token to access the critical resource. sequenceDiagram title Stepped-up Authentication actor Person participant Browser participant Website participant Auth Server participant API autonumber Website->>API: request some endpoint API->>API: Enforce<br> presence of <br> 'otp' scope<br> in access_token API->>Website: 3. 401 Unauthorized<br>WWW-Authenticate: Bearer error=\"insufficient_user_authentication\" Website->>Browser: Enforce additional challenge on the user<br> (Enter OTP) Person->>Browser:Enter OTP Browser->>Auth Server: /authorize endpoint Note right of Auth Server: Stepped-up Authentication Auth Server->>Auth Server:Validate OTP (Person authentication script) Note right of Auth Server: Modify scope of AT Auth Server->>Auth Server: Modify scope of AT to include OTP (Update token script) Auth Server->> Website: Return Access Token with scope containing OTP Implementation details : # This implementation has been broken down to 5 parts highlighted in different colours. The details contain sample code that can be used to be build the flow using Person Authentication Scripts and Update Token Scripts sequenceDiagram title Implementation Stepped-up authn in Janssen's Authentication server actor Person participant Browser participant Website participant Auth Server participant API autonumber rect rgb(255, 223, 211) Website->>Browser: html login form Person->>Browser: Update PII Browser->>Website: POST Website->>Auth Server: login request /authorize?response_type=code id_token Auth Server->> Auth Server: UpdateTokenScript - place user info in id_token <br>e.g. encrypted inum Auth Server ->>Website: return id_token and code end rect rgb(211,211,211) Website->> Website: Extract the user info from id_token and save in website's session (not to be confused with Auth Server session) end rect rgb(212, 238, 227) Website->>API: request some endpoint API->>API: Enforce<br> presence of <br> 'otp' scope<br> in access_token API->>Website: 401 Unauthorized<br>WWW-Authenticate: <br>Bearer error=\"insufficient_user_authentication\" Website->>Browser: redirect to AS end rect rgb(186,225,255) Browser->>Auth Server: authorize?acr_values=otp<br>&client_id=1234<br>&scope=otp + other scopes<br>&response_type=code<br>&client_id=____<br>&redirect_uri=____<br>&state=_____<br>&nonce=____<br>&prompt=login&<br>login_hint=encrypted_inum Auth Server->>Auth Server: Get encrypted user inum,<br>from login_hint, and decrypt<br>return None, if inum not found<br> Auth Server->>Browser: Display OTP Page Person->>Browser: enter OTP Browser->>Auth Server: POST OTP form Auth Server->>Auth Server: validate OTP Auth Server->>Auth Server: add session variable scope_enforce= otp Auth Server->>Browser: redirect to callback Browser->>Website: callback URI Website->>Auth Server: /token + client creds Auth Server->>Auth Server: Update token script is invoked. <br> read session variable scope-enforce <br> update scope of AT to include otp Auth Server->>Website: access_token, id_token,<br>refresh_token end rect rgb(255,255,186) Website->>API: request some endpoint<br>(with new access_token) API->>API: verify the acess_token. It should contain the necessary scope i.e otp end Step A: Ensure id_token has some info to identify the user: # When the user logs in for the very first time and performs basic authentication, the Update Token script can be used to place a custom claim containing some user information like User permissions User personal information Internal user identifier. In this example, we store the encrypted inum of the user as a \"custom claim\" in the id_token. A good practice is to not put the primary key / user identifier in plain text UpdateToken script: def modifyIdToken(self, jsonWebResponse, context): print \"Update token script. Modify idToken: %s\" % jsonWebResponse sessionIdService = CdiUtil.bean(SessionIdService) session = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence userService = CdiUtil.bean(UserService) user_name = session.getSessionAttributes().get(\"auth_user\") foundUser = userService.getUserByAttribute(\"uid\", user_name) userInum = foundUser.getAttribute(\"inum\") encryptedInum = CdiUtil.bean(EncryptionService).encrypt(userInum) print encryptedInum #custom claim in id_token jsonWebResponse.getClaims().setClaim(\"someFancyName\", encryptedInum) return True Step B: Website (RP) extracts the user info from id_token: # The Website (RP / client) should extract the user info from id_token and save it in the website's session. The website's session should not be confused with the Auth Server's session. The Auth Server sessions are state-less and any session related information that the website wishes to consume can only be that which can be extracted from an id_token. Step C: Critical Resource accessed by user. # Website detects critical resource, examines the Access token presented by the client. Redirects to RP for stepped-up authentication Step D: Stepped-up authentication # Website calls /authorize endpoint with login_hint=encrypted_inum, which was previously extracted from id_token in Step B Use login_hint , id_token_hint or request -jwe to identify the user in Person Authentication script used to perform the additional authentication step. Stepped-up Authn Person Authentication script: def prepareForStep(self, configurationAttributes, requestParameters, step): print \"OTP test. Prepare for steps %s\" %step if (step ==1): try: userService = CdiUtil.bean(UserService) encryptedInum = ServerUtil.getFirstValue(requestParameters, \"login_hint\") identity = CdiUtil.bean(Identity) print encryptedInum inum = CdiUtil.bean(EncryptionService).decrypt(encryptedInum) foundUser = userService.getUserByInum(inum ) print foundUser username = foundUser.getUserId() print \"username is %s \" % username identity.setWorkingParameter(\"uusername\", username ) return True except: print \"OTP. Exception: '%s'\" % (sys.exc_info()[1]) return False else: return False 3. Validate user otp 4. \"enforce_scope=otp\", add to session def authenticate(self, configurationAttributes, requestParameters, step): print(\"OTP, authentication for step %s\" %step) authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) userService = CdiUtil.bean(UserService) username = identity.getWorkingParameter(\"username\") print username #Here we set hard coded otp otp = '12345' inputOtp = ServerUtil.getFirstValue(requestParameters, \"loginForm:otpCode\") print(\"Client end otp %s \" %inputOtp) print(\"Server end otp %s\" %otp) if otp == inputOtp: print \"OTP Authenticated\" print CdiUtil.bean(SessionIdService).getSessionId() authenticationService.authenticate('username') # adding to session identity.setWorkingParameter(\"enforce_scope\",\"otp\") return True else: print(\"Wrong otp\") return errorMessage(\"Wrong otp entered\") return False 5: Update AT with relevant scope * Check the session variable \"enforce_scope\" and add the \"scope\" to the Access token. * You can also modify Access token header claims and regular claims using the modifyAccessToken in the Update Token Script. Update Token script: def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence enforce_scope = sessionId.getSessionAttributes().get(\"enforce_scope \") if enforce_scope not None: context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"existingScope1\", \"existingScope2\", \"mynewscope\")) context.getHeader().setClaim(\"custom_header_name\", \"custom_header_value\") context.getClaims().setClaim(\"claim_name\", \"claimValue\") Step E: Access the critical resource with new Access token: # The access token contains needed scope because the scopes were updated in Step D, point 5 Update token script # from io.jans.as.server.service import AuthenticationService from io.jans.as.server.service import UserService from io.jans.as.server.service import SessionIdService from io.jans.as.server.util import ServerUtil from io.jans.service.cdi.util import CdiUtil from io.jans.as.service.common import EncryptionService from io.jans.model.custom.script.type.token import UpdateTokenType class UpdateToken(UpdateTokenType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"Update token script. Initializing ...\" print \"Update token script. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Update token script. Destroying ...\" print \"Update token script. Destroyed successfully\" return True def getApiVersion(self): return 11 def modifyIdToken(self, jsonWebResponse, context): print \"Update token script. Modify idToken: %s\" % jsonWebResponse sessionIdService = CdiUtil.bean(SessionIdService) session = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence userService = CdiUtil.bean(UserService) user_name = session.getSessionAttributes().get(\"auth_user\") foundUser = userService.getUserByAttribute(\"uid\", user_name) userInum = foundUser.getAttribute(\"inum\") print userInum encryptedInum = CdiUtil.bean(EncryptionService).encrypt(userInum) print encryptedInum #custom claim in id_token jsonWebResponse.getClaims().setClaim(\"someFancyName\", encryptedInum) #print \"Update token script. After modify idToken: %s\" % jsonWebResponse #jsonWebResponse.getClaims().setClaim(\"someFancyName\", \"madhu\") return True def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence enforce_scope = sessionId.getSessionAttributes().get(\"enforce_scope\") if enforce_scope is not None: context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"openid\", \"profile\", \"otp\")) return True def modifyRefreshToken(self, refreshToken, context): return True def getRefreshTokenLifetimeInSeconds(self, context): return 0 def getIdTokenLifetimeInSeconds(self, context): return 0 def getAccessTokenLifetimeInSeconds(self, context): return 0 OTP script # from io.jans.as.server.util import ServerUtil from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.as.server.service import UserService from io.jans.as.server.service import SessionIdService from org.jans.as.server.service import CookieService from javax.faces.application import FacesMessage from org.gluu.jsf2.message import FacesMessages from org.gluu.jsf2.service import FacesService from io.jans.util import StringHelper from java.util import Arrays def errorMessage(errorInfo): facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() facesMessages.clear() facesMessages.add(FacesMessage.SEVERITY_ERROR, errorInfo) return False class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"OTP test. Initialization\" self.auth_user = None self.isUserAuthenticated = False self.isValidOtp = False print \"OTP test. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"OTP test. Destroy\" print \"OTP test. Destroyed successfully\" return True def getAuthenticationMethodClaims(self, requestParameters): return None def getApiVersion(self): return 11 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): print(\"OTP test, authentication for step %s\" %step) authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) userService = CdiUtil.bean(UserService) username = identity.getWorkingParameter(\"uusername\") print \"username is %s \" , username if(username is not None): userAuthenticated = authenticationService.authenticate(username) print(\"User present in session\") if(not userAuthenticated): print (\"Not authenticated\") return False #Here we set hard coded otp otp = '12345' inputOtp = ServerUtil.getFirstValue(requestParameters, \"loginForm:otpCode\") print(\"Client end otp %s \" %inputOtp) print(\"Server end otp %s\" %otp) if otp == inputOtp: print \"OTP Authenticated\" print CdiUtil.bean(SessionIdService).getSessionId() authenticationService.authenticate('username') identity.setWorkingParameter(\"enforce_scope\",\"otp\") return True else: print(\"Wrong otp\") return errorMessage(\"Wrong otp entered\") return False def prepareForStep(self, configurationAttributes, requestParameters, step): print \"OTP test. Prepare for steps %s\" %step if (step ==1): try: userService = CdiUtil.bean(UserService) encryptedInum = ServerUtil.getFirstValue(requestParameters, \"login_hint\") identity = CdiUtil.bean(Identity) print encryptedInum inum = CdiUtil.bean(EncryptionService).decrypt(encryptedInum) foundUser = userService.getUserByInum(inum ) print foundUser username = foundUser.getUserId() print \"username is %s \" % username identity.setWorkingParameter(\"uusername\", username ) return True except: print \"OTP. Exception: '%s'\" % (sys.exc_info()[1]) return False else: return False def getExtraParametersForStep(self, configurationAttributes, step): return Arrays.asList(\"uusername\", \"enforce_scope\") def getCountAuthenticationSteps(self, configurationAttributes): return 1 def getPageForStep(self, configurationAttributes, step): print(\"Get page for step %s\" %step) if( step==1 ) : return \"/auth/otp/otplogin.xhtml\" else: return \"\" def getNextStep(self, configurationAttributes, requestParameters, step): return -1 def getLogoutExternalUrl(self, configurationAttributes, requestParameters): print \"Get external logout URL call\" return None def logout(self, configurationAttributes, requestParameters): print\"logout\" return True", "title": "Stepped-up Authentication"}, {"location": "janssen-server/recipes/stepped-up-authn/#what-is-stepped-up-authentication", "text": "While navigating through an application, a user is challenged to produce an additional authentication when a certain API (of higher criticality) accessed by the client, does not have the needed scope. Consider the following sequence of events : 1. A user is logged in to an app using very basic authentication mechanism. Say login- password. 2. The user navigates through the app. 3. When the user attempts to access a critical resource, he is presented with another authentication step say otp. 4. The user, after successful authentication, has the needed access token to access the critical resource. sequenceDiagram title Stepped-up Authentication actor Person participant Browser participant Website participant Auth Server participant API autonumber Website->>API: request some endpoint API->>API: Enforce<br> presence of <br> 'otp' scope<br> in access_token API->>Website: 3. 401 Unauthorized<br>WWW-Authenticate: Bearer error=\"insufficient_user_authentication\" Website->>Browser: Enforce additional challenge on the user<br> (Enter OTP) Person->>Browser:Enter OTP Browser->>Auth Server: /authorize endpoint Note right of Auth Server: Stepped-up Authentication Auth Server->>Auth Server:Validate OTP (Person authentication script) Note right of Auth Server: Modify scope of AT Auth Server->>Auth Server: Modify scope of AT to include OTP (Update token script) Auth Server->> Website: Return Access Token with scope containing OTP", "title": "What is Stepped Up Authentication ?"}, {"location": "janssen-server/recipes/stepped-up-authn/#implementation-details", "text": "This implementation has been broken down to 5 parts highlighted in different colours. The details contain sample code that can be used to be build the flow using Person Authentication Scripts and Update Token Scripts sequenceDiagram title Implementation Stepped-up authn in Janssen's Authentication server actor Person participant Browser participant Website participant Auth Server participant API autonumber rect rgb(255, 223, 211) Website->>Browser: html login form Person->>Browser: Update PII Browser->>Website: POST Website->>Auth Server: login request /authorize?response_type=code id_token Auth Server->> Auth Server: UpdateTokenScript - place user info in id_token <br>e.g. encrypted inum Auth Server ->>Website: return id_token and code end rect rgb(211,211,211) Website->> Website: Extract the user info from id_token and save in website's session (not to be confused with Auth Server session) end rect rgb(212, 238, 227) Website->>API: request some endpoint API->>API: Enforce<br> presence of <br> 'otp' scope<br> in access_token API->>Website: 401 Unauthorized<br>WWW-Authenticate: <br>Bearer error=\"insufficient_user_authentication\" Website->>Browser: redirect to AS end rect rgb(186,225,255) Browser->>Auth Server: authorize?acr_values=otp<br>&client_id=1234<br>&scope=otp + other scopes<br>&response_type=code<br>&client_id=____<br>&redirect_uri=____<br>&state=_____<br>&nonce=____<br>&prompt=login&<br>login_hint=encrypted_inum Auth Server->>Auth Server: Get encrypted user inum,<br>from login_hint, and decrypt<br>return None, if inum not found<br> Auth Server->>Browser: Display OTP Page Person->>Browser: enter OTP Browser->>Auth Server: POST OTP form Auth Server->>Auth Server: validate OTP Auth Server->>Auth Server: add session variable scope_enforce= otp Auth Server->>Browser: redirect to callback Browser->>Website: callback URI Website->>Auth Server: /token + client creds Auth Server->>Auth Server: Update token script is invoked. <br> read session variable scope-enforce <br> update scope of AT to include otp Auth Server->>Website: access_token, id_token,<br>refresh_token end rect rgb(255,255,186) Website->>API: request some endpoint<br>(with new access_token) API->>API: verify the acess_token. It should contain the necessary scope i.e otp end", "title": "Implementation details :"}, {"location": "janssen-server/recipes/stepped-up-authn/#step-a-ensure-id_token-has-some-info-to-identify-the-user", "text": "When the user logs in for the very first time and performs basic authentication, the Update Token script can be used to place a custom claim containing some user information like User permissions User personal information Internal user identifier. In this example, we store the encrypted inum of the user as a \"custom claim\" in the id_token. A good practice is to not put the primary key / user identifier in plain text UpdateToken script: def modifyIdToken(self, jsonWebResponse, context): print \"Update token script. Modify idToken: %s\" % jsonWebResponse sessionIdService = CdiUtil.bean(SessionIdService) session = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence userService = CdiUtil.bean(UserService) user_name = session.getSessionAttributes().get(\"auth_user\") foundUser = userService.getUserByAttribute(\"uid\", user_name) userInum = foundUser.getAttribute(\"inum\") encryptedInum = CdiUtil.bean(EncryptionService).encrypt(userInum) print encryptedInum #custom claim in id_token jsonWebResponse.getClaims().setClaim(\"someFancyName\", encryptedInum) return True", "title": "Step A: Ensure id_token has some info to identify the user:"}, {"location": "janssen-server/recipes/stepped-up-authn/#step-b-website-rp-extracts-the-user-info-from-id_token", "text": "The Website (RP / client) should extract the user info from id_token and save it in the website's session. The website's session should not be confused with the Auth Server's session. The Auth Server sessions are state-less and any session related information that the website wishes to consume can only be that which can be extracted from an id_token.", "title": "Step B: Website (RP) extracts the user info from id_token:"}, {"location": "janssen-server/recipes/stepped-up-authn/#step-c-critical-resource-accessed-by-user", "text": "Website detects critical resource, examines the Access token presented by the client. Redirects to RP for stepped-up authentication", "title": "Step C: Critical Resource accessed by user."}, {"location": "janssen-server/recipes/stepped-up-authn/#step-d-stepped-up-authentication", "text": "Website calls /authorize endpoint with login_hint=encrypted_inum, which was previously extracted from id_token in Step B Use login_hint , id_token_hint or request -jwe to identify the user in Person Authentication script used to perform the additional authentication step. Stepped-up Authn Person Authentication script: def prepareForStep(self, configurationAttributes, requestParameters, step): print \"OTP test. Prepare for steps %s\" %step if (step ==1): try: userService = CdiUtil.bean(UserService) encryptedInum = ServerUtil.getFirstValue(requestParameters, \"login_hint\") identity = CdiUtil.bean(Identity) print encryptedInum inum = CdiUtil.bean(EncryptionService).decrypt(encryptedInum) foundUser = userService.getUserByInum(inum ) print foundUser username = foundUser.getUserId() print \"username is %s \" % username identity.setWorkingParameter(\"uusername\", username ) return True except: print \"OTP. Exception: '%s'\" % (sys.exc_info()[1]) return False else: return False 3. Validate user otp 4. \"enforce_scope=otp\", add to session def authenticate(self, configurationAttributes, requestParameters, step): print(\"OTP, authentication for step %s\" %step) authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) userService = CdiUtil.bean(UserService) username = identity.getWorkingParameter(\"username\") print username #Here we set hard coded otp otp = '12345' inputOtp = ServerUtil.getFirstValue(requestParameters, \"loginForm:otpCode\") print(\"Client end otp %s \" %inputOtp) print(\"Server end otp %s\" %otp) if otp == inputOtp: print \"OTP Authenticated\" print CdiUtil.bean(SessionIdService).getSessionId() authenticationService.authenticate('username') # adding to session identity.setWorkingParameter(\"enforce_scope\",\"otp\") return True else: print(\"Wrong otp\") return errorMessage(\"Wrong otp entered\") return False 5: Update AT with relevant scope * Check the session variable \"enforce_scope\" and add the \"scope\" to the Access token. * You can also modify Access token header claims and regular claims using the modifyAccessToken in the Update Token Script. Update Token script: def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence enforce_scope = sessionId.getSessionAttributes().get(\"enforce_scope \") if enforce_scope not None: context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"existingScope1\", \"existingScope2\", \"mynewscope\")) context.getHeader().setClaim(\"custom_header_name\", \"custom_header_value\") context.getClaims().setClaim(\"claim_name\", \"claimValue\")", "title": "Step D: Stepped-up authentication"}, {"location": "janssen-server/recipes/stepped-up-authn/#step-e-access-the-critical-resource-with-new-access-token", "text": "The access token contains needed scope because the scopes were updated in Step D, point 5", "title": "Step E: Access the critical resource with new Access token:"}, {"location": "janssen-server/recipes/stepped-up-authn/#update-token-script", "text": "from io.jans.as.server.service import AuthenticationService from io.jans.as.server.service import UserService from io.jans.as.server.service import SessionIdService from io.jans.as.server.util import ServerUtil from io.jans.service.cdi.util import CdiUtil from io.jans.as.service.common import EncryptionService from io.jans.model.custom.script.type.token import UpdateTokenType class UpdateToken(UpdateTokenType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"Update token script. Initializing ...\" print \"Update token script. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Update token script. Destroying ...\" print \"Update token script. Destroyed successfully\" return True def getApiVersion(self): return 11 def modifyIdToken(self, jsonWebResponse, context): print \"Update token script. Modify idToken: %s\" % jsonWebResponse sessionIdService = CdiUtil.bean(SessionIdService) session = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence userService = CdiUtil.bean(UserService) user_name = session.getSessionAttributes().get(\"auth_user\") foundUser = userService.getUserByAttribute(\"uid\", user_name) userInum = foundUser.getAttribute(\"inum\") print userInum encryptedInum = CdiUtil.bean(EncryptionService).encrypt(userInum) print encryptedInum #custom claim in id_token jsonWebResponse.getClaims().setClaim(\"someFancyName\", encryptedInum) #print \"Update token script. After modify idToken: %s\" % jsonWebResponse #jsonWebResponse.getClaims().setClaim(\"someFancyName\", \"madhu\") return True def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence enforce_scope = sessionId.getSessionAttributes().get(\"enforce_scope\") if enforce_scope is not None: context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"openid\", \"profile\", \"otp\")) return True def modifyRefreshToken(self, refreshToken, context): return True def getRefreshTokenLifetimeInSeconds(self, context): return 0 def getIdTokenLifetimeInSeconds(self, context): return 0 def getAccessTokenLifetimeInSeconds(self, context): return 0", "title": "Update token script"}, {"location": "janssen-server/recipes/stepped-up-authn/#otp-script", "text": "from io.jans.as.server.util import ServerUtil from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.as.server.service import UserService from io.jans.as.server.service import SessionIdService from org.jans.as.server.service import CookieService from javax.faces.application import FacesMessage from org.gluu.jsf2.message import FacesMessages from org.gluu.jsf2.service import FacesService from io.jans.util import StringHelper from java.util import Arrays def errorMessage(errorInfo): facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() facesMessages.clear() facesMessages.add(FacesMessage.SEVERITY_ERROR, errorInfo) return False class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"OTP test. Initialization\" self.auth_user = None self.isUserAuthenticated = False self.isValidOtp = False print \"OTP test. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"OTP test. Destroy\" print \"OTP test. Destroyed successfully\" return True def getAuthenticationMethodClaims(self, requestParameters): return None def getApiVersion(self): return 11 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): print(\"OTP test, authentication for step %s\" %step) authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) userService = CdiUtil.bean(UserService) username = identity.getWorkingParameter(\"uusername\") print \"username is %s \" , username if(username is not None): userAuthenticated = authenticationService.authenticate(username) print(\"User present in session\") if(not userAuthenticated): print (\"Not authenticated\") return False #Here we set hard coded otp otp = '12345' inputOtp = ServerUtil.getFirstValue(requestParameters, \"loginForm:otpCode\") print(\"Client end otp %s \" %inputOtp) print(\"Server end otp %s\" %otp) if otp == inputOtp: print \"OTP Authenticated\" print CdiUtil.bean(SessionIdService).getSessionId() authenticationService.authenticate('username') identity.setWorkingParameter(\"enforce_scope\",\"otp\") return True else: print(\"Wrong otp\") return errorMessage(\"Wrong otp entered\") return False def prepareForStep(self, configurationAttributes, requestParameters, step): print \"OTP test. Prepare for steps %s\" %step if (step ==1): try: userService = CdiUtil.bean(UserService) encryptedInum = ServerUtil.getFirstValue(requestParameters, \"login_hint\") identity = CdiUtil.bean(Identity) print encryptedInum inum = CdiUtil.bean(EncryptionService).decrypt(encryptedInum) foundUser = userService.getUserByInum(inum ) print foundUser username = foundUser.getUserId() print \"username is %s \" % username identity.setWorkingParameter(\"uusername\", username ) return True except: print \"OTP. Exception: '%s'\" % (sys.exc_info()[1]) return False else: return False def getExtraParametersForStep(self, configurationAttributes, step): return Arrays.asList(\"uusername\", \"enforce_scope\") def getCountAuthenticationSteps(self, configurationAttributes): return 1 def getPageForStep(self, configurationAttributes, step): print(\"Get page for step %s\" %step) if( step==1 ) : return \"/auth/otp/otplogin.xhtml\" else: return \"\" def getNextStep(self, configurationAttributes, requestParameters, step): return -1 def getLogoutExternalUrl(self, configurationAttributes, requestParameters): print \"Get external logout URL call\" return None def logout(self, configurationAttributes, requestParameters): print\"logout\" return True", "title": "OTP script"}, {"location": "janssen-server/recipes/user-password-validation/", "tags": ["administration", "recipes", "password"], "text": "Password validation # User password validation can be set to check the password strength, like the password must have at least one uppercase, or lowercase, number, and the length of the password. By default, the password attribute validation is not enabled. Enable user password validation through Command Line Tool (CLI) # Obtain the unique ID, that is inum for userPassword attribute. jans cli --operation-id get-attributes --endpoint-args pattern:userPassword Obatin the PatchRequest schema jans cli --schema PatchRequest > /tmp/patch.json Update /tmp/patch.json with user password validation details Enter a valid regex expression to check the strength of the password. Enter Minimum length , the minimum length of a value associated with this attribute. Enter Maximum length , the maximum length of a value associated with this attribute. Following is the example of having userPassword with minimum 8 characters, maximum 20 characters and should be alphanumeric with special characters. [{ \"op\" : \"add\" , \"path\" : \"/attributeValidation\" , \"value\" : { \"minLength\" : 5 , \"maxLength\" :15, \"regexp\" : \"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()\u2013[{}]:;',?/*~ $ ^+=<>]).{8,20} $ \" } }] Execute patch operation for userPassword attribute. jans cli --operation-id patch-attributes-by-inum \\ --url-suffix = \"inum:AAEE\" --data /tmp/patch.json Create a new user using post-user operation. An error notification will be displayed if the password does not match the validation criteria. Enable user password validation through Jans Text UI (TUI) # When using Janssen Text-based UI(TUI) to configure userPassword attribute validation , navigate via Auth Server -> Attributes ->search for userPassword attribute->open the attribute details->enable Enable Custom Validation field-> Enter a value for Regular expression , Minimum Length & Maximum Length fields->Save Create a new user using Users TUI menu. An error notification will be displayed if the password does not match the validation criteria. Enable user password validation through Jans Config API # Obtain the access token curl -k -u \"<put_client_id_here>:<put_config_api_client_secret_here>\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/attributes.write\" Obtain the unique ID, that is inum for userPassword attribute. curl -k -i -H \"Accept: application/json\" -H \"Content-Type: application/json\" \\ -H \"Authorization:Bearer <put_access_token_here>\" -X GET https://<your.jans.server>/jans-config-api/api/v1/attributes?pattern = userPassword Apply Patch for userPassword , use inum as path parameter Enter a valid regex expression to check the strength of the password. Enter Minimum length , the minimum length of a value associated with this attribute. Enter Maximum length , the maximum length of a value associated with this attribute. Following is the example of having userPassword with minimum 8 characters, maximum 20 characters, and should be alphanumeric with special characters. curl -k --location --request PATCH 'https://<your.jans.server>/jans-config-api/api/v1/attributes/<put_userPassword_inum_here>' \\ --header 'Content-Type: application/json-patch+json' --header 'Authorization: Bearer <put_access_token_here>' \\ --data-raw '[{ \"op\": \"add\", \"path\": \"/attributeValidation\", \"value\": { \"minLength\": 8, \"maxLength\":20, \"regexp\": \"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()\u2013[{}]:;' \\' ',?/*~$^+=<>]).{8,20}$\" } }]' Create a new user using /jans-config-api/mgt/configuser endpoint. An error notification will be displayed if the password does not match the validation criteria.", "title": "Password Validation"}, {"location": "janssen-server/recipes/user-password-validation/#password-validation", "text": "User password validation can be set to check the password strength, like the password must have at least one uppercase, or lowercase, number, and the length of the password. By default, the password attribute validation is not enabled.", "title": "Password validation"}, {"location": "janssen-server/recipes/user-password-validation/#enable-user-password-validation-through-command-line-tool-cli", "text": "Obtain the unique ID, that is inum for userPassword attribute. jans cli --operation-id get-attributes --endpoint-args pattern:userPassword Obatin the PatchRequest schema jans cli --schema PatchRequest > /tmp/patch.json Update /tmp/patch.json with user password validation details Enter a valid regex expression to check the strength of the password. Enter Minimum length , the minimum length of a value associated with this attribute. Enter Maximum length , the maximum length of a value associated with this attribute. Following is the example of having userPassword with minimum 8 characters, maximum 20 characters and should be alphanumeric with special characters. [{ \"op\" : \"add\" , \"path\" : \"/attributeValidation\" , \"value\" : { \"minLength\" : 5 , \"maxLength\" :15, \"regexp\" : \"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()\u2013[{}]:;',?/*~ $ ^+=<>]).{8,20} $ \" } }] Execute patch operation for userPassword attribute. jans cli --operation-id patch-attributes-by-inum \\ --url-suffix = \"inum:AAEE\" --data /tmp/patch.json Create a new user using post-user operation. An error notification will be displayed if the password does not match the validation criteria.", "title": "Enable user password validation through Command Line Tool (CLI)"}, {"location": "janssen-server/recipes/user-password-validation/#enable-user-password-validation-through-jans-text-ui-tui", "text": "When using Janssen Text-based UI(TUI) to configure userPassword attribute validation , navigate via Auth Server -> Attributes ->search for userPassword attribute->open the attribute details->enable Enable Custom Validation field-> Enter a value for Regular expression , Minimum Length & Maximum Length fields->Save Create a new user using Users TUI menu. An error notification will be displayed if the password does not match the validation criteria.", "title": "Enable user password validation through Jans Text UI (TUI)"}, {"location": "janssen-server/recipes/user-password-validation/#enable-user-password-validation-through-jans-config-api", "text": "Obtain the access token curl -k -u \"<put_client_id_here>:<put_config_api_client_secret_here>\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/attributes.write\" Obtain the unique ID, that is inum for userPassword attribute. curl -k -i -H \"Accept: application/json\" -H \"Content-Type: application/json\" \\ -H \"Authorization:Bearer <put_access_token_here>\" -X GET https://<your.jans.server>/jans-config-api/api/v1/attributes?pattern = userPassword Apply Patch for userPassword , use inum as path parameter Enter a valid regex expression to check the strength of the password. Enter Minimum length , the minimum length of a value associated with this attribute. Enter Maximum length , the maximum length of a value associated with this attribute. Following is the example of having userPassword with minimum 8 characters, maximum 20 characters, and should be alphanumeric with special characters. curl -k --location --request PATCH 'https://<your.jans.server>/jans-config-api/api/v1/attributes/<put_userPassword_inum_here>' \\ --header 'Content-Type: application/json-patch+json' --header 'Authorization: Bearer <put_access_token_here>' \\ --data-raw '[{ \"op\": \"add\", \"path\": \"/attributeValidation\", \"value\": { \"minLength\": 8, \"maxLength\":20, \"regexp\": \"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()\u2013[{}]:;' \\' ',?/*~$^+=<>]).{8,20}$\" } }]' Create a new user using /jans-config-api/mgt/configuser endpoint. An error notification will be displayed if the password does not match the validation criteria.", "title": "Enable user password validation through Jans Config API"}, {"location": "janssen-server/reference/learning-reference/", "tags": ["administration", "external content", "blogs", "videos", "tutorials"], "text": "Community Content References # This is a list of helpful learning resources outside the official documentation about the Janssen Project. Most of the content is created by the community at large, along with the core team. Though this list is not a complete list of all the content created by the community on various platforms, please help us keep it updated by raising a PR. Articles and Blogs # An intro to Janssen IDP Terraform Provider - Part1 An intro to Janssen IDP Terraform Provider - Part2 Jans-tent to test Single-Sign-On with your Authorization Server Janssen + Mod Auth openidc module to Test OpenID Connect Single Sign-on (SSO) and Single Single Logout (SLO) Enhancing Secure Mobile Authentication with OAuth, Dynamic Client Registration, and DPoP Videos # Password Authentication Using Agama Email Code verification flow Using Agama Time Based OTP authentication Using Agama Connecting To External OpenId Providers Using Agama", "title": "Learning Reference"}, {"location": "janssen-server/reference/learning-reference/#community-content-references", "text": "This is a list of helpful learning resources outside the official documentation about the Janssen Project. Most of the content is created by the community at large, along with the core team. Though this list is not a complete list of all the content created by the community on various platforms, please help us keep it updated by raising a PR.", "title": "Community Content References"}, {"location": "janssen-server/reference/learning-reference/#articles-and-blogs", "text": "An intro to Janssen IDP Terraform Provider - Part1 An intro to Janssen IDP Terraform Provider - Part2 Jans-tent to test Single-Sign-On with your Authorization Server Janssen + Mod Auth openidc module to Test OpenID Connect Single Sign-on (SSO) and Single Single Logout (SLO) Enhancing Secure Mobile Authentication with OAuth, Dynamic Client Registration, and DPoP", "title": "Articles and Blogs"}, {"location": "janssen-server/reference/learning-reference/#videos", "text": "Password Authentication Using Agama Email Code verification flow Using Agama Time Based OTP authentication Using Agama Connecting To External OpenId Providers Using Agama", "title": "Videos"}, {"location": "janssen-server/reference/openapi/", "tags": ["administration", "reference", "REST API", "javadocs"], "text": "API Reference # Janssen Server components publish REST API using OpenAPI specification and Java API using javadoc. REST API # Follow the links below to access respective documentation. Service REST API Jans Auth Server Swagger Jans Config API Swagger Jans Core NA Jans FIDO 2 Swagger Jans SCIM API Swagger Jans KC SAML API Swagger Jans Lock Server Swagger Javadocs # Javadocs for all the modules can be accessed from left side navigation bar under respective module name in Reference Guide > Javadocs / OpenAPI .", "title": "API Reference"}, {"location": "janssen-server/reference/openapi/#api-reference", "text": "Janssen Server components publish REST API using OpenAPI specification and Java API using javadoc.", "title": "API Reference"}, {"location": "janssen-server/reference/openapi/#rest-api", "text": "Follow the links below to access respective documentation. Service REST API Jans Auth Server Swagger Jans Config API Swagger Jans Core NA Jans FIDO 2 Swagger Jans SCIM API Swagger Jans KC SAML API Swagger Jans Lock Server Swagger", "title": "REST API"}, {"location": "janssen-server/reference/openapi/#javadocs", "text": "Javadocs for all the modules can be accessed from left side navigation bar under respective module name in Reference Guide > Javadocs / OpenAPI .", "title": "Javadocs"}, {"location": "janssen-server/reference/database/mysql-config/", "tags": ["administration", "reference", "database", "remote database"], "text": "MySQL ORM persistence layer # The recommended MySQL version is 8.x or newer. Before running installation the administrator can pre-install DB and provide credentials to access it or he can select option to install MySQL on same server during setup. During installation setup generates default /etc/jans/conf/jans-sql.properties and creates jansdb schema with tables and initial data set. Configuration properties # List of specific for MySQL default setting from jans-sql.properties : db.schema.name=jansdb connection.uri=jdbc:mysql://localhost:3306/jansdb?enabledTLSProtocols=TLSv1.2 connection.driver-property.serverTimezone=UTC+0000 # Prefix connection.driver-property.key=value will be coverterd to key=value JDBC driver properties #connection.driver-property.driverProperty=driverPropertyValue #connection.driver-property.useServerPrepStmts=false connection.driver-property.cachePrepStmts=false connection.driver-property.cacheResultSetMetadata=true connection.driver-property.metadataCacheSize=500 #connection.driver-property.prepStmtCacheSize=500 #connection.driver-property.prepStmtCacheSqlLimit=1024 auth.userName=jans auth.userPassword=CC0NHhtXW78= # Password hash method password.encryption.method=SSHA-256 # Connection pool size connection.pool.max-total=40 connection.pool.max-idle=15 connection.pool.min-idle=5 # Max time needed to create connection pool in milliseconds connection.pool.create-max-wait-time-millis=20000 # Max wait 20 seconds connection.pool.max-wait-time-millis=20000 # Allow to evict connection in pool after 30 minutes connection.pool.min-evictable-idle-time-millis=1800000 # Sets whether objects created for the pool will be validated before being returned from it #connection.pool.test-on-create=true # Sets whether objects borrowed from the pool will be validated when they are returned to the pool #connection.pool.test-on-return=true The rest of properties are static for all other supported DB: binaryAttributes=objectGUID certificateAttributes=userCertificate doc_id building rules # In order to support transparency for end applications and allow data migration from one DB to another ORM requires DN attribute in each entry. This attribute it also uses to build doc_id . Here is example of this DN -> doc_id conversion: doc_id is primary key. In order to build unique document identifier ORM uses another unique attribute DN . doc_id is last RDN value. Generic tables structure # Each table in jansdb MySQL schema follow next rules: one table for every objectClass has 2 mandatory column DN and doc_id Index for primary key Data mapping rules # ORM uses VARCHAR / DATETIME(3) / INT / BINARY / SMALLINT / BLOB / JSON data types. SMALLINT represents boolean attribute type. JSON it uses to store multi-valued attribute values. The generic format of such values is: {\"v\": [\"value_1\", \"value_2\", ...]} ORM add v key on top level due to MySQL limitations of indexing JSON array if they are on to level. If it's specified in schema that application can do search in multi-valued attribute setup add next indexes for each column: KEY `jansExtUid_json_1` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v') as char(128) array))), KEY `jansExtUid_json_2` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[0]') as char(128) charset utf8mb4))), KEY `jansExtUid_json_3` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[1]') as char(128) charset utf8mb4))), KEY `jansExtUid_json_4` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[2]') as char(128) charset utf8mb4))), By default it creates indexes for first 3 values. Administrator should add more indexes to confrom maximum count of values. In future versions if top level JSON array indexing will work well we can review format to use simple JSON array. For user password field ORM on persist/update operations automatically create hash. On authentication ORM compares hashes. To store attributes defined in java beans with @JsonObject annotation ORM uses TEXT column type. Java example # This example shows how to use ORM. It opens connection to MySQL DB and add user entry to it: public static void main(String[] args) { // Create Sql entry manager SqlEntryManager couchbaseEntryManager = createSqlEntryManager(); // Create and fill user bean SimpleUser newUser = new SimpleUser(); newUser.setDn(String.format(\"inum=%s,ou=people,o=jans\", System.currentTimeMillis())); newUser.setUserId(\"sample_user_\" + System.currentTimeMillis()); newUser.setUserPassword(\"test\"); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansAddress\", Arrays.asList(\"London\", \"Texas\", \"New York\"))); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); // Call ORM API to store entry couchbaseEntryManager.persist(newUser); couchbaseEntryManager.destroy(); } public static SqlEntryManager createSqlEntryManager() { SqlEntryManagerFactory couchbaseEntryManagerFactory = new SqlEntryManagerFactory(); couchbaseEntryManagerFactory.create(); Properties connectionProperties = getSampleConnectionProperties(); SqlEntryManager couchbaseEntryManager = couchbaseEntryManagerFactory.createEntryManager(connectionProperties); return couchbaseEntryManager; } private static Properties getSampleConnectionProperties() { Properties connectionProperties = new Properties(); connectionProperties.put(\"sql#db.schema.name\", \"jansdb\"); connectionProperties.put(\"sql#connection.uri\", \"jdbc:mysql://localhost:3306/jansdb?profileSQL=true\"); connectionProperties.put(\"sql#connection.driver-property.serverTimezone\", \"GMT+2\"); connectionProperties.put(\"sql#connection.pool.max-total\", \"300\"); connectionProperties.put(\"sql#connection.pool.max-idle\", \"300\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"secret\"); // Password hash method connectionProperties.put(\"sql#password.encryption.method\", \"SSHA-256\"); // Max time needed to create connection pool in milliseconds connectionProperties.put(\"sql#connection.pool.create-max-wait-time-millis\", \"20000\"); // Max wait 20 seconds connectionProperties.put(\"sql#connection.pool.max-wait-time-millis\", \"20000\"); // Allow to evict connection in pool after 30 minutes connectionProperties.put(\"sql#connection.pool.min-evictable-idle-time-millis\", \"1800000\"); connectionProperties.put(\"sql#binaryAttributes\", \"objectGUID\"); connectionProperties.put(\"sql#certificateAttributes\", \"userCertificate\"); return connectionProperties; } More MySQL ORM examples is in this sample module.", "title": "MySQL Configuration"}, {"location": "janssen-server/reference/database/mysql-config/#mysql-orm-persistence-layer", "text": "The recommended MySQL version is 8.x or newer. Before running installation the administrator can pre-install DB and provide credentials to access it or he can select option to install MySQL on same server during setup. During installation setup generates default /etc/jans/conf/jans-sql.properties and creates jansdb schema with tables and initial data set.", "title": "MySQL ORM persistence layer"}, {"location": "janssen-server/reference/database/mysql-config/#configuration-properties", "text": "List of specific for MySQL default setting from jans-sql.properties : db.schema.name=jansdb connection.uri=jdbc:mysql://localhost:3306/jansdb?enabledTLSProtocols=TLSv1.2 connection.driver-property.serverTimezone=UTC+0000 # Prefix connection.driver-property.key=value will be coverterd to key=value JDBC driver properties #connection.driver-property.driverProperty=driverPropertyValue #connection.driver-property.useServerPrepStmts=false connection.driver-property.cachePrepStmts=false connection.driver-property.cacheResultSetMetadata=true connection.driver-property.metadataCacheSize=500 #connection.driver-property.prepStmtCacheSize=500 #connection.driver-property.prepStmtCacheSqlLimit=1024 auth.userName=jans auth.userPassword=CC0NHhtXW78= # Password hash method password.encryption.method=SSHA-256 # Connection pool size connection.pool.max-total=40 connection.pool.max-idle=15 connection.pool.min-idle=5 # Max time needed to create connection pool in milliseconds connection.pool.create-max-wait-time-millis=20000 # Max wait 20 seconds connection.pool.max-wait-time-millis=20000 # Allow to evict connection in pool after 30 minutes connection.pool.min-evictable-idle-time-millis=1800000 # Sets whether objects created for the pool will be validated before being returned from it #connection.pool.test-on-create=true # Sets whether objects borrowed from the pool will be validated when they are returned to the pool #connection.pool.test-on-return=true The rest of properties are static for all other supported DB: binaryAttributes=objectGUID certificateAttributes=userCertificate", "title": "Configuration properties"}, {"location": "janssen-server/reference/database/mysql-config/#doc_id-building-rules", "text": "In order to support transparency for end applications and allow data migration from one DB to another ORM requires DN attribute in each entry. This attribute it also uses to build doc_id . Here is example of this DN -> doc_id conversion: doc_id is primary key. In order to build unique document identifier ORM uses another unique attribute DN . doc_id is last RDN value.", "title": "doc_id building rules"}, {"location": "janssen-server/reference/database/mysql-config/#generic-tables-structure", "text": "Each table in jansdb MySQL schema follow next rules: one table for every objectClass has 2 mandatory column DN and doc_id Index for primary key", "title": "Generic tables structure"}, {"location": "janssen-server/reference/database/mysql-config/#data-mapping-rules", "text": "ORM uses VARCHAR / DATETIME(3) / INT / BINARY / SMALLINT / BLOB / JSON data types. SMALLINT represents boolean attribute type. JSON it uses to store multi-valued attribute values. The generic format of such values is: {\"v\": [\"value_1\", \"value_2\", ...]} ORM add v key on top level due to MySQL limitations of indexing JSON array if they are on to level. If it's specified in schema that application can do search in multi-valued attribute setup add next indexes for each column: KEY `jansExtUid_json_1` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v') as char(128) array))), KEY `jansExtUid_json_2` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[0]') as char(128) charset utf8mb4))), KEY `jansExtUid_json_3` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[1]') as char(128) charset utf8mb4))), KEY `jansExtUid_json_4` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[2]') as char(128) charset utf8mb4))), By default it creates indexes for first 3 values. Administrator should add more indexes to confrom maximum count of values. In future versions if top level JSON array indexing will work well we can review format to use simple JSON array. For user password field ORM on persist/update operations automatically create hash. On authentication ORM compares hashes. To store attributes defined in java beans with @JsonObject annotation ORM uses TEXT column type.", "title": "Data mapping rules"}, {"location": "janssen-server/reference/database/mysql-config/#java-example", "text": "This example shows how to use ORM. It opens connection to MySQL DB and add user entry to it: public static void main(String[] args) { // Create Sql entry manager SqlEntryManager couchbaseEntryManager = createSqlEntryManager(); // Create and fill user bean SimpleUser newUser = new SimpleUser(); newUser.setDn(String.format(\"inum=%s,ou=people,o=jans\", System.currentTimeMillis())); newUser.setUserId(\"sample_user_\" + System.currentTimeMillis()); newUser.setUserPassword(\"test\"); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansAddress\", Arrays.asList(\"London\", \"Texas\", \"New York\"))); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); // Call ORM API to store entry couchbaseEntryManager.persist(newUser); couchbaseEntryManager.destroy(); } public static SqlEntryManager createSqlEntryManager() { SqlEntryManagerFactory couchbaseEntryManagerFactory = new SqlEntryManagerFactory(); couchbaseEntryManagerFactory.create(); Properties connectionProperties = getSampleConnectionProperties(); SqlEntryManager couchbaseEntryManager = couchbaseEntryManagerFactory.createEntryManager(connectionProperties); return couchbaseEntryManager; } private static Properties getSampleConnectionProperties() { Properties connectionProperties = new Properties(); connectionProperties.put(\"sql#db.schema.name\", \"jansdb\"); connectionProperties.put(\"sql#connection.uri\", \"jdbc:mysql://localhost:3306/jansdb?profileSQL=true\"); connectionProperties.put(\"sql#connection.driver-property.serverTimezone\", \"GMT+2\"); connectionProperties.put(\"sql#connection.pool.max-total\", \"300\"); connectionProperties.put(\"sql#connection.pool.max-idle\", \"300\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"secret\"); // Password hash method connectionProperties.put(\"sql#password.encryption.method\", \"SSHA-256\"); // Max time needed to create connection pool in milliseconds connectionProperties.put(\"sql#connection.pool.create-max-wait-time-millis\", \"20000\"); // Max wait 20 seconds connectionProperties.put(\"sql#connection.pool.max-wait-time-millis\", \"20000\"); // Allow to evict connection in pool after 30 minutes connectionProperties.put(\"sql#connection.pool.min-evictable-idle-time-millis\", \"1800000\"); connectionProperties.put(\"sql#binaryAttributes\", \"objectGUID\"); connectionProperties.put(\"sql#certificateAttributes\", \"userCertificate\"); return connectionProperties; } More MySQL ORM examples is in this sample module.", "title": "Java example"}, {"location": "janssen-server/reference/database/mysql-ops/", "tags": ["administration", "reference", "database", "additional claims to database", "jansPerson"], "text": "Below operations require to log into mysql workspace first with command: mysql Change password for user jans : # ALTER USER 'jans'@'localhost' IDENTIFIED BY 'TopSecret'; GRANT ALL PRIVILEGES ON jansdb.* TO 'jans'@'localhost'; Create new user claims to jansPerson : # You can add additional attributes to jansPerson table and use them. Here DB stores all the user attribute information in one entry. Additional attributes will not affect the server functionality. Ensure you restart services after DB schema modification Modify column size of jansPerson : # Say we want to increase the size of mail field to 144. Do the following: * a. Modify column size - ALTER TABLE `jansdb`.`jansPerson` CHANGE COLUMN `mail` `mail` VARCHAR(144) NULL DEFAULT NULL ; * b. Drop indexes and re-create - ALTER TABLE jansdb.jansPerson DROP INDEX `jansPerson_CustomIdx2`; ALTER TABLE jansdb.jansPerson ADD INDEX `jansPerson_CustomIdx2` ((lower(`mail`))); * c. Ensure you restart services after DB schema modification Add user in Jans admin group # Search for inum of JansGrp use jansdb; select * from jansGrp\\G; Add specific user in this group Get DN of user use jansdb; select * from jansPerson where uid='testUser'\\G ; Copy DN of this user. i.e. inum=83d43a5d-3311-4c93-ae26-df80c320557a,ou=people,o=jans Perform operation: use jansdb; update jansGrp set member = '{\"v\": [\"inum=e4fe2c89-f588-41a2-aac5-2f1afa63bed1,ou=people,o=jans\", \"inum=83d43a5d-3311-4c93-ae26-df80c320557a,ou=people,o=jans\"]}'; Update user information # In this example we are doing to update one user's email address. Search for existing email address: use jansdb; select * from jansPerson where uid='testUser'\\G; Modify it: use jansdb; update jansPerson set mail='newEmail@gluu.org' where uid='testUser'; Search user : # use jansdb; select * from jansPerson where uid='admin'\\G; Add custom attribute # There are three steps here: Create attribute in MySQL database: ALTER TABLE jansdb.jansPerson ADD COLUMN cmdAttr VARCHAR(64) NULL; Restart the ConfgiApi service . If you are using kubernetes please restart the deployment . Create attribute using the terraform provider, curl commands, or TUI: Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "MySQL Operation"}, {"location": "janssen-server/reference/database/mysql-ops/#change-password-for-user-jans", "text": "ALTER USER 'jans'@'localhost' IDENTIFIED BY 'TopSecret'; GRANT ALL PRIVILEGES ON jansdb.* TO 'jans'@'localhost';", "title": "Change password for user jans :"}, {"location": "janssen-server/reference/database/mysql-ops/#create-new-user-claims-to-jansperson", "text": "You can add additional attributes to jansPerson table and use them. Here DB stores all the user attribute information in one entry. Additional attributes will not affect the server functionality. Ensure you restart services after DB schema modification", "title": "Create new user claims to jansPerson:"}, {"location": "janssen-server/reference/database/mysql-ops/#modify-column-size-of-jansperson", "text": "Say we want to increase the size of mail field to 144. Do the following: * a. Modify column size - ALTER TABLE `jansdb`.`jansPerson` CHANGE COLUMN `mail` `mail` VARCHAR(144) NULL DEFAULT NULL ; * b. Drop indexes and re-create - ALTER TABLE jansdb.jansPerson DROP INDEX `jansPerson_CustomIdx2`; ALTER TABLE jansdb.jansPerson ADD INDEX `jansPerson_CustomIdx2` ((lower(`mail`))); * c. Ensure you restart services after DB schema modification", "title": "Modify column size of jansPerson :"}, {"location": "janssen-server/reference/database/mysql-ops/#add-user-in-jans-admin-group", "text": "Search for inum of JansGrp use jansdb; select * from jansGrp\\G; Add specific user in this group Get DN of user use jansdb; select * from jansPerson where uid='testUser'\\G ; Copy DN of this user. i.e. inum=83d43a5d-3311-4c93-ae26-df80c320557a,ou=people,o=jans Perform operation: use jansdb; update jansGrp set member = '{\"v\": [\"inum=e4fe2c89-f588-41a2-aac5-2f1afa63bed1,ou=people,o=jans\", \"inum=83d43a5d-3311-4c93-ae26-df80c320557a,ou=people,o=jans\"]}';", "title": "Add user in Jans admin group"}, {"location": "janssen-server/reference/database/mysql-ops/#update-user-information", "text": "In this example we are doing to update one user's email address. Search for existing email address: use jansdb; select * from jansPerson where uid='testUser'\\G; Modify it: use jansdb; update jansPerson set mail='newEmail@gluu.org' where uid='testUser';", "title": "Update user information"}, {"location": "janssen-server/reference/database/mysql-ops/#search-user", "text": "use jansdb; select * from jansPerson where uid='admin'\\G;", "title": "Search user :"}, {"location": "janssen-server/reference/database/mysql-ops/#add-custom-attribute", "text": "There are three steps here: Create attribute in MySQL database: ALTER TABLE jansdb.jansPerson ADD COLUMN cmdAttr VARCHAR(64) NULL; Restart the ConfgiApi service . If you are using kubernetes please restart the deployment . Create attribute using the terraform provider, curl commands, or TUI: Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "Add custom attribute"}, {"location": "janssen-server/reference/database/mysql-schema/", "tags": ["administration", "database", "MySQL", "Indexes"], "text": "MySQL Schema # Tables # Table names adsPrjDeployment agmFlow agmFlowRun jansAppConf jansAttr jansCache jansCibaReq jansClnt jansClntAuthz jansCustomScr jansDeviceRegistration jansDocument jansFido2AuthnEntry jansFido2RegistrationEntry jansGrant jansGrp jansInumMap jansMetric jansOrganization jansPairwiseIdentifier jansPar jansPassResetReq jansPerson jansPushApp jansPushDevice jansRp jansScope jansScr jansSectorIdentifier jansSessId jansSsa jansStatEntry jansToken jansU2fReq jansUmaPCT jansUmaRPT jansUmaResource jansUmaResourcePermission adsPrjDeployment # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansStartDate datetime(3) YES None Start date jansActive smallint YES None jansEndDate datetime(3) YES None End date adsPrjAssets longtext YES None Assets of an ADS project adsPrjDeplDetails text YES None Misc details associated to an ADS project agmFlow # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None agFlowQname varchar(64) YES None Full name of an agama flow agFlowMeta text YES None Metadata of an agama flow jansScr text YES None Attr that contains script (python, java script) jansEnabled smallint YES None Status of the entry, used by many objectclasses jansScrError text YES None Attr that contains first error which application get during it execution agFlowTrans text YES None Transpiled code of an agama flow jansRevision int YES None Revision jansCustomMessage varchar(128) YES None exclude custom welcome message agmFlowRun # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier agFlowSt text YES None Details of a running agama flow instance agFlowEncCont mediumtext YES None Continuation associated to a running agama flow instance jansCustomMessage varchar(128) YES None exclude custom welcome message exp datetime(3) YES None jans Exp jansAppConf # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None ou varchar(64) YES None description varchar(768) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansHostname varchar(64) YES None The hostname of the Jans Server instance jansLastUpd datetime(3) YES None Monitors last time the server was able to connect to the monitoring system. jansManager varchar(64) YES None Used to specify if a person has the manager role jansOrgProfileMgt smallint YES None enable or disable profile management feature in exclude jansScimEnabled smallint YES None exclude SCIM feature - enabled or disabled jansEmail json YES None jansSmtpConf json YES None SMTP configuration jansSslExpiry varchar(64) YES None SAML Trust Relationship configuration jansStatus varchar(16) YES None Status of the entry, used by many objectclasses jansUrl varchar(64) YES None Jans instance URL inum varchar(64) YES None XRI i-number o varchar(64) YES None jansAuthMode varchar(64) YES None jansDbAuth json YES None Custom IDP authentication configuration jansLogViewerConfig varchar(64) YES None Log viewer configuration jansLogConfigLocation varchar(64) YES None Path to external log4j2.xml jansCacheConf text YES None Cache configuration jansDocStoreConf text YES None jansDocStoreConf jansSoftVer varchar(64) YES None userPassword varchar(256) YES None jansConfDyn text YES None jans Dyn Conf jansConfErrors text YES None jans Errors Conf jansConfStatic text YES None jans Static Conf jansConfWebKeys text YES None jans Web Keys Conf jansWebKeysSettings varchar(64) YES None jans Web Keys Conf jansConfApp text YES None jans App Conf jansRevision int YES None Revision jansAttr # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries jansAttrEditTyp json YES None Specify in exclude who can update an attribute, admin or user jansAttrName varchar(64) YES MUL None Specify an identifier for an attribute. May be multi-value where an attribute has two names, like givenName and first-name. jansAttrOrigin varchar(64) YES MUL None Specify the person objectclass associated with the attribute, used for display purposes in exclude. jansAttrSystemEditTyp varchar(64) YES None TODO - still required? jansAttrTyp varchar(64) YES None Data type of attribute. Values can be string, photo, numeric, date jansClaimName varchar(64) YES None Used by jans in conjunction with jansttributeName to map claims to attributes in datastore. jansAttrUsgTyp varchar(64) YES None TODO - Usg? Value can be OpenID jansAttrViewTyp json YES None Specify in exclude who can view an attribute, admin or user jansSAML1URI varchar(64) YES None SAML 1 uri of attribute jansSAML2URI varchar(64) YES None SAML 2 uri of attribute jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number jansMultivaluedAttr smallint YES None jansHideOnDiscovery smallint YES None jansNameIdTyp varchar(64) YES None NameId Typ jansScimCustomAttr smallint YES None jansSourceAttr varchar(64) YES None Source Attr for this Attr seeAlso varchar(64) YES None urn varchar(128) YES None jansRegExp varchar(64) YES None Regular expression used to validate attribute data jansTooltip varchar(64) YES None Custom tooltip to be shown on the UI jansValidation tinytext YES None This data has information about attribute Validation jansCache # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None uuid varchar(64) YES None Unique identifier iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del dat text YES None OX data jansCibaReq # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authReqId varchar(64) YES None Authn request id clnId varchar(64) YES None jans Clnt id usrId varchar(64) YES None jans user id creationDate datetime(3) YES None Creation Date used for password reset requests exp datetime(3) YES None jans Exp jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses jansClnt # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None o varchar(64) YES None jansGrp varchar(64) YES None Group displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries displayNameLocalized json YES None jans Display Name Localized description varchar(768) YES MUL None inum varchar(64) YES MUL None XRI i-number jansAppTyp varchar(64) YES None jans App Typ jansClntIdIssuedAt datetime(3) YES None jans Clnt Issued At jansClntSecret varchar(64) YES None jans Clnt Secret jansClntSecretExpAt datetime(3) YES MUL None Date client expires exp datetime(3) YES None jans Exp del smallint YES MUL None del jansClntURI tinytext YES None jans Clnt URI jansClntURILocalized json YES None jans Clnt URI localized jansContact json YES None jans Contact jansDefAcrValues json YES None jans Def Acr Values jansDefMaxAge int YES None jans Def Max Age jansGrantTyp json YES None jans Grant Typ jansIdTknEncRespAlg varchar(64) YES None jans ID Tkn Enc Resp Alg jansIdTknEncRespEnc varchar(64) YES None jans ID Tkn Enc Resp Enc jansIdTknSignedRespAlg varchar(64) YES None jans ID Tkn Signed Resp Alg jansInitiateLoginURI tinytext YES None jans Initiate Login URI jansJwksURI tinytext YES None jans JWKs URI jansJwks text YES None jans JWKs jansLogoURI tinytext YES None jans Logo URI jansLogoURILocalized json YES None jans Logo URI localized jansPolicyURI tinytext YES None jans Policy URI jansPolicyURILocalized json YES None jans Policy URI localized jansPostLogoutRedirectURI json YES None jans Post Logout Redirect URI jansRedirectURI json YES None jans Redirect URI jansRegistrationAccessTkn varchar(64) YES MUL None jans Registration Access Tkn jansReqObjSigAlg varchar(64) YES None jans Req Obj Sig Alg jansReqObjEncAlg varchar(64) YES None jans Req Obj Enc Alg jansReqObjEncEnc varchar(64) YES None jans Req Obj Enc Enc jansReqURI json YES None jans Req URI jansRespTyp json YES None jans Resp Typ jansScope json YES None jans Attr Scope jansClaim json YES None jans Attr Claim jansSectorIdentifierURI tinytext YES None jans Sector Identifier URI jansSignedRespAlg varchar(64) YES None jans Signed Resp Alg jansSubjectTyp varchar(64) YES None jans Subject Typ jansTknEndpointAuthMethod varchar(64) YES None jans Tkn Endpoint Auth Method jansTknEndpointAuthSigAlg varchar(64) YES None jans Tkn Endpoint Auth Sig Alg jansTosURI tinytext YES None jans TOS URI jansTosURILocalized json YES None jans Tos URI localized jansTrustedClnt smallint YES None jans Trusted Clnt jansUsrInfEncRespAlg varchar(64) YES None jans Usr Inf Enc Resp Alg jansUsrInfEncRespEnc varchar(64) YES None jans Usr Inf Enc Resp Enc jansExtraConf varchar(64) YES None jans additional configuration jansClaimRedirectURI json YES None Claim Redirect URI jansLastAccessTime datetime(3) YES None Last access time jansLastLogonTime datetime(3) YES None Last logon time jansPersistClntAuthzs smallint YES None jans Persist Clnt Authzs jansInclClaimsInIdTkn smallint YES None jans Incl Claims In Id Tkn jansRefreshTknLife int YES None Life of refresh token jansDisabled smallint YES None Status of client jansLogoutURI json YES None jans Policy URI jansLogoutSessRequired smallint YES None jans Policy URI jansdId varchar(64) YES None jansd Id jansAuthorizedOrigins json YES None jans Authorized Origins tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash jansAccessTknAsJwt smallint YES None jansauth - indicator whether to return access token as JWT jansAccessTknSigAlg varchar(64) YES None jansauth - access token signing algorithm jansAccessTknLife int YES None Life of access token jansSoftId varchar(64) YES None Soft Identifier jansSoftVer varchar(64) YES None jansSoftStatement text YES None Soft Statement jansRptAsJwt smallint YES None jansRptAsJwt jansAttrs text YES None Attrs jansBackchannelTknDeliveryMode varchar(64) YES None jans Backchannel Tkn Delivery Mode jansBackchannelClntNotificationEndpoint varchar(64) YES None jans Backchannel Clnt Notification Endpoint jansBackchannelAuthnReqSigAlg varchar(64) YES None jans Backchannel Authn Req Sig Alg jansBackchannelUsrCodeParameter smallint YES None jans Backchannel Usr Code Parameter jansClntAuthz # Field Type Null Key Default Comment doc_id varchar(100) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansClntId json YES None jans Clnt id jansUsrId varchar(64) YES MUL None jans user id exp datetime(3) YES None jans Exp del smallint YES MUL None del jansScope json YES None jans Attr Scope jansCustomScr # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES MUL None XRI i-number displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None jansScr text YES None Attr that contains script (python, java script) jansScrTyp varchar(64) YES MUL None Attr that contains script type (e.g. python, java script) jansProgLng varchar(64) YES None programming language jansModuleProperty json YES None Module property jansConfProperty json YES None Conf property jansLevel int YES None Level jansRevision int YES None Revision jansEnabled smallint YES None Status of the entry, used by many objectclasses jansScrError text YES None Attr that contains first error which application get during it execution jansAlias json YES None jansAlias jansDeviceRegistration # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None jansDeviceKeyHandle varchar(128) YES MUL None jansDeviceKeyHandle jansDeviceHashCode int YES MUL None jansDeviceHashCode jansApp varchar(96) YES MUL None jansApp jansDeviceRegistrationConf text YES None jansDeviceRegistrationConf jansDeviceNotificationConf varchar(64) YES None Extended push notification configuration jansNickName varchar(64) YES None jansNickName jansDeviceData tinytext YES None jansDeviceData jansCounter int YES None jansCounter jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses del smallint YES MUL None del exp datetime(3) YES None jans Exp personInum varchar(64) YES MUL None Inum of a person creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansLastAccessTime datetime(3) YES None Last access time jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None jansDocument # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number ou varchar(64) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None document varchar(64) YES None Save Document in DB creationDate datetime(3) YES None Creation Date used for password reset requests jansModuleProperty json YES None Module property jansLevel int YES None Level jansRevision int YES None Revision jansEnabled smallint YES None Status of the entry, used by many objectclasses jansAlias json YES None jansAlias jansFido2AuthnEntry # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansApp varchar(96) YES MUL None jansApp jansSessStateId varchar(64) YES None jansSessStateId jansCodeChallenge varchar(64) YES MUL None OX PKCE code challenge jansCodeChallengeHash int YES MUL None OX code challenge hash personInum varchar(64) YES MUL None Inum of a person jansAuthData text YES None jansAuthData jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses exp datetime(3) YES None jans Exp del smallint YES MUL None del jansFido2RegistrationEntry # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier creationDate datetime(3) YES MUL None Creation Date used for password reset requests displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansApp varchar(96) YES MUL None jansApp jansSessStateId varchar(64) YES None jansSessStateId jansCodeChallenge varchar(64) YES MUL None OX PKCE code challenge jansCodeChallengeHash int YES MUL None OX code challenge hash jansPublicKeyId varchar(96) YES MUL None jansPublicKeyId jansPublicKeyIdHash int YES MUL None jansPublicKeyIdHash personInum varchar(64) YES MUL None Inum of a person jansRegistrationData text YES None jansRegistrationData jansDeviceData tinytext YES None jansDeviceData jansDeviceNotificationConf varchar(64) YES None Extended push notification configuration jansCounter int YES None jansCounter jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses exp datetime(3) YES None jans Exp del smallint YES MUL None del jansGrant # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None grtId varchar(64) YES None jans grant id iat datetime(3) YES None jans Creation jansGrp # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number member json YES None o varchar(64) YES None owner varchar(64) YES None seeAlso varchar(64) YES None jansMetaCreated varchar(64) YES None jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None jansInumMap # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number jansPrimaryKeyAttrName varchar(64) YES None Primary Key Attribute Name jansPrimaryKeyValue varchar(64) YES None Primary Key Value jansSecondaryKeyAttrName varchar(64) YES None Secondary Key Attribute Name jansSecondaryKeyValue varchar(64) YES None Secondary Key Value jansTertiaryKeyAttrName varchar(64) YES None Tertiary Key Attribute Name jansTertiaryKeyValue varchar(64) YES None Tertiary Key Value jansMetric # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None uniqueIdentifier varchar(64) YES None jansStartDate datetime(3) YES MUL None Start date jansEndDate datetime(3) YES MUL None End date jansAppTyp varchar(64) YES MUL None jans App Typ jansMetricTyp varchar(64) YES MUL None Metric type creationDate datetime(3) YES None Creation Date used for password reset requests del smallint YES MUL None del exp datetime(3) YES None jans Exp jansData text YES None OX data jansHost varchar(64) YES None jans host jansOrganization # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None description varchar(768) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansCustomMessage varchar(128) YES None exclude custom welcome message jansFaviconImage varchar(64) YES None TODO - Stores URL of favicon jansLogoImage varchar(64) YES None Logo used by exclude for default look and feel. jansManager varchar(64) YES None Used to specify if a person has the manager role jansManagerGrp tinytext YES None Used in organizatoin entry to specifies the dn of the group that has admin priviledges in exclude. jansOrgShortName varchar(64) YES None Short description, as few letters as possible, no spaces. jansThemeColor varchar(64) YES None exclude login page configuration inum varchar(64) YES None XRI i-number l varchar(64) YES None mail varchar(96) YES None memberOf json YES None o varchar(64) YES None jansCreationTimestamp datetime(3) YES None Registration time jansRegistrationConf varchar(64) YES None Registration Conf postalCode varchar(16) YES None st varchar(64) YES None street tinytext YES None telephoneNumber varchar(20) YES None title varchar(64) YES None uid varchar(64) YES MUL None jansLogoPath varchar(64) YES None jansLogoPath jansStatus varchar(16) YES None Status of the entry, used by many objectclasses jansFaviconPath varchar(64) YES None jansFaviconPath jansPairwiseIdentifier # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansSectorIdentifier varchar(64) YES None jans Sector Identifier jansClntId json YES None jans Clnt id jansUsrId varchar(64) YES None jans user id jansPar # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES MUL None Identifier jansAttrs text YES None Attrs exp datetime(3) YES None jans Exp del smallint YES MUL None del jansPassResetReq # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansGuid varchar(64) YES None A random string to mark temporary tokens personInum varchar(64) YES None Inum of a person jansPerson # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansAssociatedClnt json YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. c varchar(2) YES None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries givenName varchar(128) YES MUL None jansManagedOrganizations varchar(64) YES None Used to track with which organizations a person is associated jansOptOuts json YES None White pages attributes restricted by person in exclude profile management jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number mail varchar(96) YES MUL None memberOf json YES None o varchar(64) YES None jansPersistentJWT json YES None jans Persistent JWT jansCreationTimestamp datetime(3) YES None Registration time jansExtUid json YES None jansOTPCache json YES None Stores a used OTP to prevent a hacker from using it again. Complementary to jansExtUid attribute jansLastLogonTime datetime(3) YES None Last logon time jansActive smallint YES None jansAddress json YES None jansEmail json YES None jansEntitlements json YES None jansExtId varchar(128) YES None jansImsValue json YES None jansMetaCreated varchar(64) YES None jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None jansNameFormatted tinytext YES None jansPhoneValue json YES None jansPhotos json YES None jansProfileURL varchar(256) YES None jansRole json YES None jansTitle varchar(64) YES None jansUsrTyp varchar(64) YES None jansHonorificPrefix varchar(64) YES None jansHonorificSuffix varchar(64) YES None jans509Certificate json YES None jansPassExpDate datetime(3) YES None Pass Exp date, represented as an ISO 8601 (YYYY-MM-DD) format persistentId varchar(64) YES None PersistentId middleName varchar(64) YES None Middle name(s) nickname varchar(64) YES None Casual name of the End-Usr jansPrefUsrName varchar(64) YES None Shorthand Name profile varchar(64) YES None Profile page URL of the person picture tinytext YES None Profile picture URL of the person website varchar(64) YES None Web page or blog URL of the person emailVerified smallint YES None True if the e-mail address of the person has been verified; otherwise false gender varchar(32) YES None Gender of the person either female or male birthdate datetime(3) YES None Birthday of the person, represented as an ISO 8601:2004 [ISO8601-2004] YYYY-MM-DD format zoneinfo varchar(64) YES None Time zone database representing the End-Usrs time zone. For example, Europe/Paris or America/Los_Angeles locale varchar(64) YES None Locale of the person, represented as a BCP47 [RFC5646] language tag phoneNumberVerified smallint YES None True if the phone number of the person has been verified, otherwise false address tinytext YES None OpenID Connect formatted JSON object representing the address of the person updatedAt datetime(3) YES None Time the information of the person was last updated. Seconds from 1970-01-01T0:0:0Z preferredLanguage varchar(64) YES None preferred written or spoken language for a person role json YES None Role secretAnswer tinytext YES None Secret Answer secretQuestion tinytext YES None Secret Question seeAlso varchar(64) YES None sn varchar(128) YES MUL None cn varchar(128) YES None transientId varchar(64) YES None TransientId uid varchar(64) YES MUL None userPassword varchar(256) YES None st varchar(64) YES None street tinytext YES None l varchar(64) YES None jansCountInvalidLogin varchar(64) YES None Invalid login attempts count jansEnrollmentCode varchar(64) YES None jansEnrollmentCode jansIMAPData varchar(64) YES None This data has information about your imap connection jansPPID json YES None Persistent Pairwise ID for OpenID Connect jansGuid varchar(64) YES None A random string to mark temporary tokens jansPreferredMethod varchar(64) YES None Casa - Preferred method to use for user authentication userCertificate blob YES None jansOTPDevices varchar(512) YES None Casa - Json representation of OTP devices. Complementary to jansExtUid attribute jansMobileDevices varchar(512) YES None Casa - Json representation of mobile devices. Complementary to mobile attribute jansTrustedDevices text YES None Casa - Devices with which strong authentication may be skipped jansStrongAuthPolicy varchar(64) YES None Casa - 2FA Enforcement Policy for User jansUnlinkedExternalUids varchar(64) YES None Casa - List of unlinked social accounts (ie disabled jansExtUids) jansBackchannelDeviceRegistrationTkn varchar(64) YES None jans Backchannel Device Registration Tkn jansBackchannelUsrCode varchar(64) YES None jans Backchannel Usr Code telephoneNumber varchar(20) YES None mobile json YES None carLicense varchar(64) YES None vehicle license or registration plate facsimileTelephoneNumber varchar(20) YES None departmentNumber varchar(64) YES None identifies a department within an organization employeeType varchar(64) YES None type of employment for a person manager tinytext YES None postOfficeBox varchar(64) YES None employeeNumber varchar(64) YES None numerically identifies an employee within an organization preferredDeliveryMethod varchar(50) YES None roomNumber varchar(64) YES None secretary tinytext YES None homePostalAddress tinytext YES None postalCode varchar(16) YES None description varchar(768) YES None title varchar(64) YES None jansAdminUIRole json YES None jansAdminUIRole jansPushApp # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansId varchar(128) YES None Identifier jansName varchar(64) YES None Name jansPushAppConf varchar(64) YES None jansPush application configuration jansPushDevice # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansUsrId varchar(64) YES None jans user id jansId varchar(128) YES None Identifier jansPushApp tinytext YES None jansPush application DN jansPushDeviceConf varchar(64) YES None jansPush device configuration jansTyp varchar(64) YES None jans type jansRp # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier dat text YES None OX data jansScope # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansDefScope smallint YES None Track the default scope for an custom OAuth2 Scope. description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries inum varchar(64) YES None XRI i-number jansScopeTyp varchar(64) YES None OX Attr Scope type creatorId varchar(64) YES None Creator Id creatorTyp varchar(64) YES None Creator type creatorAttrs varchar(64) YES None Creator Attrs creationDate datetime(3) YES None Creation Date used for password reset requests jansClaim json YES None jans Attr Claim jansScrDn json YES None Script object DN jansGrpClaims smallint YES None jans Grp Attr Claims (true or false) jansId varchar(128) YES MUL None Identifier jansIconUrl varchar(64) YES None jans icon url jansUmaPolicyScrDn tinytext YES None OX policy script Dn jansAttrs text YES None Attrs exp datetime(3) YES None jans Exp del smallint YES MUL None del jansScr # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number jansScr text YES None Attr that contains script (python, java script) jansScrTyp varchar(64) YES None Attr that contains script type (e.g. python, java script) jansSectorIdentifier # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier description varchar(768) YES None jansRedirectURI json YES None jans Redirect URI jansClntId json YES None jans Clnt id jansSessId # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier sid varchar(64) YES MUL None Sess Identifier creationDate datetime(3) YES None Creation Date used for password reset requests exp datetime(3) YES None jans Exp del smallint YES MUL None del jansLastAccessTime datetime(3) YES None Last access time jansUsrDN varchar(128) YES MUL None jans Usr DN authnTime datetime(3) YES None jans Authn Time jansState varchar(64) YES None jansState jansSessState text YES None jans Sess State jansPermissionGranted smallint YES None jans Permission Granted jansAsJwt smallint YES None Boolean field to indicate whether object is used as JWT jansJwt text YES None JWT representation of the object or otherwise jwt associated with the object jansPermissionGrantedMap text YES None jans Permission Granted Map jansInvolvedClnts text YES None Involved clients deviceSecret varchar(64) YES MUL None deviceSecret jansSessAttr text YES None jansSessAttr jansSsa # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number o varchar(64) YES None jansAttrs text YES None Attrs description varchar(768) YES None exp datetime(3) YES None jans Exp del smallint YES None del jansState varchar(64) YES None jansState creatorId varchar(64) YES None Creator Id creatorTyp varchar(64) YES None Creator type creationDate datetime(3) YES None Creation Date used for password reset requests jansStatEntry # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES MUL None Identifier dat text YES None OX data jansData text YES None OX data attr text YES None Attrs jansToken # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authnTime datetime(3) YES None jans Authn Time authzCode varchar(64) YES MUL None jans authorization code iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del grtId varchar(64) YES MUL None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknCde varchar(80) YES MUL None jans Tkn Code tknTyp varchar(32) YES None jans Tkn Typ usrId varchar(64) YES None jans user id jansUsrDN varchar(128) YES None jans Usr DN clnId varchar(64) YES None jans Clnt id acr varchar(48) YES None uuid varchar(64) YES None Unique identifier chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims ssnId varchar(64) YES MUL None jans Sess DN attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash dpop varchar(64) YES None DPoP Proof jansU2fReq # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansReqId varchar(64) YES None jansReqId jansReq text YES None jansReq jansSessStateId varchar(64) YES None jansSessStateId del smallint YES MUL None del exp datetime(3) YES None jans Exp personInum varchar(64) YES None Inum of a person creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansUmaPCT # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None clnId varchar(64) YES None jans Clnt id iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del tknCde varchar(80) YES MUL None jans Tkn Code ssnId varchar(64) YES None jans Sess DN jansClaimValues varchar(64) YES None Claim Values dpop varchar(64) YES None DPoP Proof authnTime datetime(3) YES None jans Authn Time authzCode varchar(64) YES None jans authorization code grtId varchar(64) YES None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknTyp varchar(32) YES None jans Tkn Typ usrId varchar(64) YES None jans user id jansUsrDN varchar(128) YES None jans Usr DN acr varchar(48) YES None uuid varchar(64) YES None Unique identifier chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash jansUmaRPT # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authnTime datetime(3) YES None jans Authn Time clnId varchar(64) YES None jans Clnt id iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES None del tknCde varchar(80) YES None jans Tkn Code usrId varchar(64) YES None jans user id ssnId varchar(64) YES None jans Sess DN jansUmaPermission json YES None jans uma permission uuid varchar(64) YES None Unique identifier dpop varchar(64) YES None DPoP Proof authzCode varchar(64) YES None jans authorization code grtId varchar(64) YES None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknTyp varchar(32) YES None jans Tkn Typ jansUsrDN varchar(128) YES None jans Usr DN acr varchar(48) YES None chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash jansUmaResource # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries inum varchar(64) YES None XRI i-number owner varchar(64) YES None jansAssociatedClnt json YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. jansUmaScope varchar(768) YES MUL None URI reference of scope descriptor jansFaviconImage varchar(64) YES None TODO - Stores URL of favicon jansGrp varchar(64) YES None Group jansId varchar(128) YES MUL None Identifier jansResource tinytext YES None Host path jansRevision int YES None Revision jansTyp varchar(64) YES None jans type jansScopeExpression text YES None Scope expression iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del description varchar(768) YES None jansUmaResourcePermission # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None exp datetime(3) YES None jans Exp del smallint YES None del jansUmaScope varchar(768) YES None URI reference of scope descriptor jansConfCode varchar(64) YES None jans configuration code jansResourceSetId varchar(64) YES None jans resource set id jansAttrs text YES None Attrs jansTicket varchar(64) YES MUL None jans ticket jansStatus varchar(16) YES None Status of the entry, used by many objectclasses", "title": "MySQL Schema"}, {"location": "janssen-server/reference/database/mysql-schema/#mysql-schema", "text": "", "title": "MySQL Schema"}, {"location": "janssen-server/reference/database/mysql-schema/#tables", "text": "Table names adsPrjDeployment agmFlow agmFlowRun jansAppConf jansAttr jansCache jansCibaReq jansClnt jansClntAuthz jansCustomScr jansDeviceRegistration jansDocument jansFido2AuthnEntry jansFido2RegistrationEntry jansGrant jansGrp jansInumMap jansMetric jansOrganization jansPairwiseIdentifier jansPar jansPassResetReq jansPerson jansPushApp jansPushDevice jansRp jansScope jansScr jansSectorIdentifier jansSessId jansSsa jansStatEntry jansToken jansU2fReq jansUmaPCT jansUmaRPT jansUmaResource jansUmaResourcePermission", "title": "Tables"}, {"location": "janssen-server/reference/database/mysql-schema/#adsprjdeployment", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansStartDate datetime(3) YES None Start date jansActive smallint YES None jansEndDate datetime(3) YES None End date adsPrjAssets longtext YES None Assets of an ADS project adsPrjDeplDetails text YES None Misc details associated to an ADS project", "title": "adsPrjDeployment"}, {"location": "janssen-server/reference/database/mysql-schema/#agmflow", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None agFlowQname varchar(64) YES None Full name of an agama flow agFlowMeta text YES None Metadata of an agama flow jansScr text YES None Attr that contains script (python, java script) jansEnabled smallint YES None Status of the entry, used by many objectclasses jansScrError text YES None Attr that contains first error which application get during it execution agFlowTrans text YES None Transpiled code of an agama flow jansRevision int YES None Revision jansCustomMessage varchar(128) YES None exclude custom welcome message", "title": "agmFlow"}, {"location": "janssen-server/reference/database/mysql-schema/#agmflowrun", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier agFlowSt text YES None Details of a running agama flow instance agFlowEncCont mediumtext YES None Continuation associated to a running agama flow instance jansCustomMessage varchar(128) YES None exclude custom welcome message exp datetime(3) YES None jans Exp", "title": "agmFlowRun"}, {"location": "janssen-server/reference/database/mysql-schema/#jansappconf", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None ou varchar(64) YES None description varchar(768) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansHostname varchar(64) YES None The hostname of the Jans Server instance jansLastUpd datetime(3) YES None Monitors last time the server was able to connect to the monitoring system. jansManager varchar(64) YES None Used to specify if a person has the manager role jansOrgProfileMgt smallint YES None enable or disable profile management feature in exclude jansScimEnabled smallint YES None exclude SCIM feature - enabled or disabled jansEmail json YES None jansSmtpConf json YES None SMTP configuration jansSslExpiry varchar(64) YES None SAML Trust Relationship configuration jansStatus varchar(16) YES None Status of the entry, used by many objectclasses jansUrl varchar(64) YES None Jans instance URL inum varchar(64) YES None XRI i-number o varchar(64) YES None jansAuthMode varchar(64) YES None jansDbAuth json YES None Custom IDP authentication configuration jansLogViewerConfig varchar(64) YES None Log viewer configuration jansLogConfigLocation varchar(64) YES None Path to external log4j2.xml jansCacheConf text YES None Cache configuration jansDocStoreConf text YES None jansDocStoreConf jansSoftVer varchar(64) YES None userPassword varchar(256) YES None jansConfDyn text YES None jans Dyn Conf jansConfErrors text YES None jans Errors Conf jansConfStatic text YES None jans Static Conf jansConfWebKeys text YES None jans Web Keys Conf jansWebKeysSettings varchar(64) YES None jans Web Keys Conf jansConfApp text YES None jans App Conf jansRevision int YES None Revision", "title": "jansAppConf"}, {"location": "janssen-server/reference/database/mysql-schema/#jansattr", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries jansAttrEditTyp json YES None Specify in exclude who can update an attribute, admin or user jansAttrName varchar(64) YES MUL None Specify an identifier for an attribute. May be multi-value where an attribute has two names, like givenName and first-name. jansAttrOrigin varchar(64) YES MUL None Specify the person objectclass associated with the attribute, used for display purposes in exclude. jansAttrSystemEditTyp varchar(64) YES None TODO - still required? jansAttrTyp varchar(64) YES None Data type of attribute. Values can be string, photo, numeric, date jansClaimName varchar(64) YES None Used by jans in conjunction with jansttributeName to map claims to attributes in datastore. jansAttrUsgTyp varchar(64) YES None TODO - Usg? Value can be OpenID jansAttrViewTyp json YES None Specify in exclude who can view an attribute, admin or user jansSAML1URI varchar(64) YES None SAML 1 uri of attribute jansSAML2URI varchar(64) YES None SAML 2 uri of attribute jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number jansMultivaluedAttr smallint YES None jansHideOnDiscovery smallint YES None jansNameIdTyp varchar(64) YES None NameId Typ jansScimCustomAttr smallint YES None jansSourceAttr varchar(64) YES None Source Attr for this Attr seeAlso varchar(64) YES None urn varchar(128) YES None jansRegExp varchar(64) YES None Regular expression used to validate attribute data jansTooltip varchar(64) YES None Custom tooltip to be shown on the UI jansValidation tinytext YES None This data has information about attribute Validation", "title": "jansAttr"}, {"location": "janssen-server/reference/database/mysql-schema/#janscache", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None uuid varchar(64) YES None Unique identifier iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del dat text YES None OX data", "title": "jansCache"}, {"location": "janssen-server/reference/database/mysql-schema/#janscibareq", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authReqId varchar(64) YES None Authn request id clnId varchar(64) YES None jans Clnt id usrId varchar(64) YES None jans user id creationDate datetime(3) YES None Creation Date used for password reset requests exp datetime(3) YES None jans Exp jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses", "title": "jansCibaReq"}, {"location": "janssen-server/reference/database/mysql-schema/#jansclnt", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None o varchar(64) YES None jansGrp varchar(64) YES None Group displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries displayNameLocalized json YES None jans Display Name Localized description varchar(768) YES MUL None inum varchar(64) YES MUL None XRI i-number jansAppTyp varchar(64) YES None jans App Typ jansClntIdIssuedAt datetime(3) YES None jans Clnt Issued At jansClntSecret varchar(64) YES None jans Clnt Secret jansClntSecretExpAt datetime(3) YES MUL None Date client expires exp datetime(3) YES None jans Exp del smallint YES MUL None del jansClntURI tinytext YES None jans Clnt URI jansClntURILocalized json YES None jans Clnt URI localized jansContact json YES None jans Contact jansDefAcrValues json YES None jans Def Acr Values jansDefMaxAge int YES None jans Def Max Age jansGrantTyp json YES None jans Grant Typ jansIdTknEncRespAlg varchar(64) YES None jans ID Tkn Enc Resp Alg jansIdTknEncRespEnc varchar(64) YES None jans ID Tkn Enc Resp Enc jansIdTknSignedRespAlg varchar(64) YES None jans ID Tkn Signed Resp Alg jansInitiateLoginURI tinytext YES None jans Initiate Login URI jansJwksURI tinytext YES None jans JWKs URI jansJwks text YES None jans JWKs jansLogoURI tinytext YES None jans Logo URI jansLogoURILocalized json YES None jans Logo URI localized jansPolicyURI tinytext YES None jans Policy URI jansPolicyURILocalized json YES None jans Policy URI localized jansPostLogoutRedirectURI json YES None jans Post Logout Redirect URI jansRedirectURI json YES None jans Redirect URI jansRegistrationAccessTkn varchar(64) YES MUL None jans Registration Access Tkn jansReqObjSigAlg varchar(64) YES None jans Req Obj Sig Alg jansReqObjEncAlg varchar(64) YES None jans Req Obj Enc Alg jansReqObjEncEnc varchar(64) YES None jans Req Obj Enc Enc jansReqURI json YES None jans Req URI jansRespTyp json YES None jans Resp Typ jansScope json YES None jans Attr Scope jansClaim json YES None jans Attr Claim jansSectorIdentifierURI tinytext YES None jans Sector Identifier URI jansSignedRespAlg varchar(64) YES None jans Signed Resp Alg jansSubjectTyp varchar(64) YES None jans Subject Typ jansTknEndpointAuthMethod varchar(64) YES None jans Tkn Endpoint Auth Method jansTknEndpointAuthSigAlg varchar(64) YES None jans Tkn Endpoint Auth Sig Alg jansTosURI tinytext YES None jans TOS URI jansTosURILocalized json YES None jans Tos URI localized jansTrustedClnt smallint YES None jans Trusted Clnt jansUsrInfEncRespAlg varchar(64) YES None jans Usr Inf Enc Resp Alg jansUsrInfEncRespEnc varchar(64) YES None jans Usr Inf Enc Resp Enc jansExtraConf varchar(64) YES None jans additional configuration jansClaimRedirectURI json YES None Claim Redirect URI jansLastAccessTime datetime(3) YES None Last access time jansLastLogonTime datetime(3) YES None Last logon time jansPersistClntAuthzs smallint YES None jans Persist Clnt Authzs jansInclClaimsInIdTkn smallint YES None jans Incl Claims In Id Tkn jansRefreshTknLife int YES None Life of refresh token jansDisabled smallint YES None Status of client jansLogoutURI json YES None jans Policy URI jansLogoutSessRequired smallint YES None jans Policy URI jansdId varchar(64) YES None jansd Id jansAuthorizedOrigins json YES None jans Authorized Origins tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash jansAccessTknAsJwt smallint YES None jansauth - indicator whether to return access token as JWT jansAccessTknSigAlg varchar(64) YES None jansauth - access token signing algorithm jansAccessTknLife int YES None Life of access token jansSoftId varchar(64) YES None Soft Identifier jansSoftVer varchar(64) YES None jansSoftStatement text YES None Soft Statement jansRptAsJwt smallint YES None jansRptAsJwt jansAttrs text YES None Attrs jansBackchannelTknDeliveryMode varchar(64) YES None jans Backchannel Tkn Delivery Mode jansBackchannelClntNotificationEndpoint varchar(64) YES None jans Backchannel Clnt Notification Endpoint jansBackchannelAuthnReqSigAlg varchar(64) YES None jans Backchannel Authn Req Sig Alg jansBackchannelUsrCodeParameter smallint YES None jans Backchannel Usr Code Parameter", "title": "jansClnt"}, {"location": "janssen-server/reference/database/mysql-schema/#jansclntauthz", "text": "Field Type Null Key Default Comment doc_id varchar(100) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansClntId json YES None jans Clnt id jansUsrId varchar(64) YES MUL None jans user id exp datetime(3) YES None jans Exp del smallint YES MUL None del jansScope json YES None jans Attr Scope", "title": "jansClntAuthz"}, {"location": "janssen-server/reference/database/mysql-schema/#janscustomscr", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES MUL None XRI i-number displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None jansScr text YES None Attr that contains script (python, java script) jansScrTyp varchar(64) YES MUL None Attr that contains script type (e.g. python, java script) jansProgLng varchar(64) YES None programming language jansModuleProperty json YES None Module property jansConfProperty json YES None Conf property jansLevel int YES None Level jansRevision int YES None Revision jansEnabled smallint YES None Status of the entry, used by many objectclasses jansScrError text YES None Attr that contains first error which application get during it execution jansAlias json YES None jansAlias", "title": "jansCustomScr"}, {"location": "janssen-server/reference/database/mysql-schema/#jansdeviceregistration", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None jansDeviceKeyHandle varchar(128) YES MUL None jansDeviceKeyHandle jansDeviceHashCode int YES MUL None jansDeviceHashCode jansApp varchar(96) YES MUL None jansApp jansDeviceRegistrationConf text YES None jansDeviceRegistrationConf jansDeviceNotificationConf varchar(64) YES None Extended push notification configuration jansNickName varchar(64) YES None jansNickName jansDeviceData tinytext YES None jansDeviceData jansCounter int YES None jansCounter jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses del smallint YES MUL None del exp datetime(3) YES None jans Exp personInum varchar(64) YES MUL None Inum of a person creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansLastAccessTime datetime(3) YES None Last access time jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None", "title": "jansDeviceRegistration"}, {"location": "janssen-server/reference/database/mysql-schema/#jansdocument", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number ou varchar(64) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None document varchar(64) YES None Save Document in DB creationDate datetime(3) YES None Creation Date used for password reset requests jansModuleProperty json YES None Module property jansLevel int YES None Level jansRevision int YES None Revision jansEnabled smallint YES None Status of the entry, used by many objectclasses jansAlias json YES None jansAlias", "title": "jansDocument"}, {"location": "janssen-server/reference/database/mysql-schema/#jansfido2authnentry", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansApp varchar(96) YES MUL None jansApp jansSessStateId varchar(64) YES None jansSessStateId jansCodeChallenge varchar(64) YES MUL None OX PKCE code challenge jansCodeChallengeHash int YES MUL None OX code challenge hash personInum varchar(64) YES MUL None Inum of a person jansAuthData text YES None jansAuthData jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses exp datetime(3) YES None jans Exp del smallint YES MUL None del", "title": "jansFido2AuthnEntry"}, {"location": "janssen-server/reference/database/mysql-schema/#jansfido2registrationentry", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier creationDate datetime(3) YES MUL None Creation Date used for password reset requests displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansApp varchar(96) YES MUL None jansApp jansSessStateId varchar(64) YES None jansSessStateId jansCodeChallenge varchar(64) YES MUL None OX PKCE code challenge jansCodeChallengeHash int YES MUL None OX code challenge hash jansPublicKeyId varchar(96) YES MUL None jansPublicKeyId jansPublicKeyIdHash int YES MUL None jansPublicKeyIdHash personInum varchar(64) YES MUL None Inum of a person jansRegistrationData text YES None jansRegistrationData jansDeviceData tinytext YES None jansDeviceData jansDeviceNotificationConf varchar(64) YES None Extended push notification configuration jansCounter int YES None jansCounter jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses exp datetime(3) YES None jans Exp del smallint YES MUL None del", "title": "jansFido2RegistrationEntry"}, {"location": "janssen-server/reference/database/mysql-schema/#jansgrant", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None grtId varchar(64) YES None jans grant id iat datetime(3) YES None jans Creation", "title": "jansGrant"}, {"location": "janssen-server/reference/database/mysql-schema/#jansgrp", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number member json YES None o varchar(64) YES None owner varchar(64) YES None seeAlso varchar(64) YES None jansMetaCreated varchar(64) YES None jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None", "title": "jansGrp"}, {"location": "janssen-server/reference/database/mysql-schema/#jansinummap", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number jansPrimaryKeyAttrName varchar(64) YES None Primary Key Attribute Name jansPrimaryKeyValue varchar(64) YES None Primary Key Value jansSecondaryKeyAttrName varchar(64) YES None Secondary Key Attribute Name jansSecondaryKeyValue varchar(64) YES None Secondary Key Value jansTertiaryKeyAttrName varchar(64) YES None Tertiary Key Attribute Name jansTertiaryKeyValue varchar(64) YES None Tertiary Key Value", "title": "jansInumMap"}, {"location": "janssen-server/reference/database/mysql-schema/#jansmetric", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None uniqueIdentifier varchar(64) YES None jansStartDate datetime(3) YES MUL None Start date jansEndDate datetime(3) YES MUL None End date jansAppTyp varchar(64) YES MUL None jans App Typ jansMetricTyp varchar(64) YES MUL None Metric type creationDate datetime(3) YES None Creation Date used for password reset requests del smallint YES MUL None del exp datetime(3) YES None jans Exp jansData text YES None OX data jansHost varchar(64) YES None jans host", "title": "jansMetric"}, {"location": "janssen-server/reference/database/mysql-schema/#jansorganization", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None description varchar(768) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansCustomMessage varchar(128) YES None exclude custom welcome message jansFaviconImage varchar(64) YES None TODO - Stores URL of favicon jansLogoImage varchar(64) YES None Logo used by exclude for default look and feel. jansManager varchar(64) YES None Used to specify if a person has the manager role jansManagerGrp tinytext YES None Used in organizatoin entry to specifies the dn of the group that has admin priviledges in exclude. jansOrgShortName varchar(64) YES None Short description, as few letters as possible, no spaces. jansThemeColor varchar(64) YES None exclude login page configuration inum varchar(64) YES None XRI i-number l varchar(64) YES None mail varchar(96) YES None memberOf json YES None o varchar(64) YES None jansCreationTimestamp datetime(3) YES None Registration time jansRegistrationConf varchar(64) YES None Registration Conf postalCode varchar(16) YES None st varchar(64) YES None street tinytext YES None telephoneNumber varchar(20) YES None title varchar(64) YES None uid varchar(64) YES MUL None jansLogoPath varchar(64) YES None jansLogoPath jansStatus varchar(16) YES None Status of the entry, used by many objectclasses jansFaviconPath varchar(64) YES None jansFaviconPath", "title": "jansOrganization"}, {"location": "janssen-server/reference/database/mysql-schema/#janspairwiseidentifier", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansSectorIdentifier varchar(64) YES None jans Sector Identifier jansClntId json YES None jans Clnt id jansUsrId varchar(64) YES None jans user id", "title": "jansPairwiseIdentifier"}, {"location": "janssen-server/reference/database/mysql-schema/#janspar", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES MUL None Identifier jansAttrs text YES None Attrs exp datetime(3) YES None jans Exp del smallint YES MUL None del", "title": "jansPar"}, {"location": "janssen-server/reference/database/mysql-schema/#janspassresetreq", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansGuid varchar(64) YES None A random string to mark temporary tokens personInum varchar(64) YES None Inum of a person", "title": "jansPassResetReq"}, {"location": "janssen-server/reference/database/mysql-schema/#jansperson", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansAssociatedClnt json YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. c varchar(2) YES None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries givenName varchar(128) YES MUL None jansManagedOrganizations varchar(64) YES None Used to track with which organizations a person is associated jansOptOuts json YES None White pages attributes restricted by person in exclude profile management jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number mail varchar(96) YES MUL None memberOf json YES None o varchar(64) YES None jansPersistentJWT json YES None jans Persistent JWT jansCreationTimestamp datetime(3) YES None Registration time jansExtUid json YES None jansOTPCache json YES None Stores a used OTP to prevent a hacker from using it again. Complementary to jansExtUid attribute jansLastLogonTime datetime(3) YES None Last logon time jansActive smallint YES None jansAddress json YES None jansEmail json YES None jansEntitlements json YES None jansExtId varchar(128) YES None jansImsValue json YES None jansMetaCreated varchar(64) YES None jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None jansNameFormatted tinytext YES None jansPhoneValue json YES None jansPhotos json YES None jansProfileURL varchar(256) YES None jansRole json YES None jansTitle varchar(64) YES None jansUsrTyp varchar(64) YES None jansHonorificPrefix varchar(64) YES None jansHonorificSuffix varchar(64) YES None jans509Certificate json YES None jansPassExpDate datetime(3) YES None Pass Exp date, represented as an ISO 8601 (YYYY-MM-DD) format persistentId varchar(64) YES None PersistentId middleName varchar(64) YES None Middle name(s) nickname varchar(64) YES None Casual name of the End-Usr jansPrefUsrName varchar(64) YES None Shorthand Name profile varchar(64) YES None Profile page URL of the person picture tinytext YES None Profile picture URL of the person website varchar(64) YES None Web page or blog URL of the person emailVerified smallint YES None True if the e-mail address of the person has been verified; otherwise false gender varchar(32) YES None Gender of the person either female or male birthdate datetime(3) YES None Birthday of the person, represented as an ISO 8601:2004 [ISO8601-2004] YYYY-MM-DD format zoneinfo varchar(64) YES None Time zone database representing the End-Usrs time zone. For example, Europe/Paris or America/Los_Angeles locale varchar(64) YES None Locale of the person, represented as a BCP47 [RFC5646] language tag phoneNumberVerified smallint YES None True if the phone number of the person has been verified, otherwise false address tinytext YES None OpenID Connect formatted JSON object representing the address of the person updatedAt datetime(3) YES None Time the information of the person was last updated. Seconds from 1970-01-01T0:0:0Z preferredLanguage varchar(64) YES None preferred written or spoken language for a person role json YES None Role secretAnswer tinytext YES None Secret Answer secretQuestion tinytext YES None Secret Question seeAlso varchar(64) YES None sn varchar(128) YES MUL None cn varchar(128) YES None transientId varchar(64) YES None TransientId uid varchar(64) YES MUL None userPassword varchar(256) YES None st varchar(64) YES None street tinytext YES None l varchar(64) YES None jansCountInvalidLogin varchar(64) YES None Invalid login attempts count jansEnrollmentCode varchar(64) YES None jansEnrollmentCode jansIMAPData varchar(64) YES None This data has information about your imap connection jansPPID json YES None Persistent Pairwise ID for OpenID Connect jansGuid varchar(64) YES None A random string to mark temporary tokens jansPreferredMethod varchar(64) YES None Casa - Preferred method to use for user authentication userCertificate blob YES None jansOTPDevices varchar(512) YES None Casa - Json representation of OTP devices. Complementary to jansExtUid attribute jansMobileDevices varchar(512) YES None Casa - Json representation of mobile devices. Complementary to mobile attribute jansTrustedDevices text YES None Casa - Devices with which strong authentication may be skipped jansStrongAuthPolicy varchar(64) YES None Casa - 2FA Enforcement Policy for User jansUnlinkedExternalUids varchar(64) YES None Casa - List of unlinked social accounts (ie disabled jansExtUids) jansBackchannelDeviceRegistrationTkn varchar(64) YES None jans Backchannel Device Registration Tkn jansBackchannelUsrCode varchar(64) YES None jans Backchannel Usr Code telephoneNumber varchar(20) YES None mobile json YES None carLicense varchar(64) YES None vehicle license or registration plate facsimileTelephoneNumber varchar(20) YES None departmentNumber varchar(64) YES None identifies a department within an organization employeeType varchar(64) YES None type of employment for a person manager tinytext YES None postOfficeBox varchar(64) YES None employeeNumber varchar(64) YES None numerically identifies an employee within an organization preferredDeliveryMethod varchar(50) YES None roomNumber varchar(64) YES None secretary tinytext YES None homePostalAddress tinytext YES None postalCode varchar(16) YES None description varchar(768) YES None title varchar(64) YES None jansAdminUIRole json YES None jansAdminUIRole", "title": "jansPerson"}, {"location": "janssen-server/reference/database/mysql-schema/#janspushapp", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansId varchar(128) YES None Identifier jansName varchar(64) YES None Name jansPushAppConf varchar(64) YES None jansPush application configuration", "title": "jansPushApp"}, {"location": "janssen-server/reference/database/mysql-schema/#janspushdevice", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansUsrId varchar(64) YES None jans user id jansId varchar(128) YES None Identifier jansPushApp tinytext YES None jansPush application DN jansPushDeviceConf varchar(64) YES None jansPush device configuration jansTyp varchar(64) YES None jans type", "title": "jansPushDevice"}, {"location": "janssen-server/reference/database/mysql-schema/#jansrp", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier dat text YES None OX data", "title": "jansRp"}, {"location": "janssen-server/reference/database/mysql-schema/#jansscope", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansDefScope smallint YES None Track the default scope for an custom OAuth2 Scope. description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries inum varchar(64) YES None XRI i-number jansScopeTyp varchar(64) YES None OX Attr Scope type creatorId varchar(64) YES None Creator Id creatorTyp varchar(64) YES None Creator type creatorAttrs varchar(64) YES None Creator Attrs creationDate datetime(3) YES None Creation Date used for password reset requests jansClaim json YES None jans Attr Claim jansScrDn json YES None Script object DN jansGrpClaims smallint YES None jans Grp Attr Claims (true or false) jansId varchar(128) YES MUL None Identifier jansIconUrl varchar(64) YES None jans icon url jansUmaPolicyScrDn tinytext YES None OX policy script Dn jansAttrs text YES None Attrs exp datetime(3) YES None jans Exp del smallint YES MUL None del", "title": "jansScope"}, {"location": "janssen-server/reference/database/mysql-schema/#jansscr", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number jansScr text YES None Attr that contains script (python, java script) jansScrTyp varchar(64) YES None Attr that contains script type (e.g. python, java script)", "title": "jansScr"}, {"location": "janssen-server/reference/database/mysql-schema/#janssectoridentifier", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier description varchar(768) YES None jansRedirectURI json YES None jans Redirect URI jansClntId json YES None jans Clnt id", "title": "jansSectorIdentifier"}, {"location": "janssen-server/reference/database/mysql-schema/#janssessid", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier sid varchar(64) YES MUL None Sess Identifier creationDate datetime(3) YES None Creation Date used for password reset requests exp datetime(3) YES None jans Exp del smallint YES MUL None del jansLastAccessTime datetime(3) YES None Last access time jansUsrDN varchar(128) YES MUL None jans Usr DN authnTime datetime(3) YES None jans Authn Time jansState varchar(64) YES None jansState jansSessState text YES None jans Sess State jansPermissionGranted smallint YES None jans Permission Granted jansAsJwt smallint YES None Boolean field to indicate whether object is used as JWT jansJwt text YES None JWT representation of the object or otherwise jwt associated with the object jansPermissionGrantedMap text YES None jans Permission Granted Map jansInvolvedClnts text YES None Involved clients deviceSecret varchar(64) YES MUL None deviceSecret jansSessAttr text YES None jansSessAttr", "title": "jansSessId"}, {"location": "janssen-server/reference/database/mysql-schema/#jansssa", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number o varchar(64) YES None jansAttrs text YES None Attrs description varchar(768) YES None exp datetime(3) YES None jans Exp del smallint YES None del jansState varchar(64) YES None jansState creatorId varchar(64) YES None Creator Id creatorTyp varchar(64) YES None Creator type creationDate datetime(3) YES None Creation Date used for password reset requests", "title": "jansSsa"}, {"location": "janssen-server/reference/database/mysql-schema/#jansstatentry", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES MUL None Identifier dat text YES None OX data jansData text YES None OX data attr text YES None Attrs", "title": "jansStatEntry"}, {"location": "janssen-server/reference/database/mysql-schema/#janstoken", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authnTime datetime(3) YES None jans Authn Time authzCode varchar(64) YES MUL None jans authorization code iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del grtId varchar(64) YES MUL None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknCde varchar(80) YES MUL None jans Tkn Code tknTyp varchar(32) YES None jans Tkn Typ usrId varchar(64) YES None jans user id jansUsrDN varchar(128) YES None jans Usr DN clnId varchar(64) YES None jans Clnt id acr varchar(48) YES None uuid varchar(64) YES None Unique identifier chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims ssnId varchar(64) YES MUL None jans Sess DN attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash dpop varchar(64) YES None DPoP Proof", "title": "jansToken"}, {"location": "janssen-server/reference/database/mysql-schema/#jansu2freq", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansReqId varchar(64) YES None jansReqId jansReq text YES None jansReq jansSessStateId varchar(64) YES None jansSessStateId del smallint YES MUL None del exp datetime(3) YES None jans Exp personInum varchar(64) YES None Inum of a person creationDate datetime(3) YES MUL None Creation Date used for password reset requests", "title": "jansU2fReq"}, {"location": "janssen-server/reference/database/mysql-schema/#jansumapct", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None clnId varchar(64) YES None jans Clnt id iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del tknCde varchar(80) YES MUL None jans Tkn Code ssnId varchar(64) YES None jans Sess DN jansClaimValues varchar(64) YES None Claim Values dpop varchar(64) YES None DPoP Proof authnTime datetime(3) YES None jans Authn Time authzCode varchar(64) YES None jans authorization code grtId varchar(64) YES None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknTyp varchar(32) YES None jans Tkn Typ usrId varchar(64) YES None jans user id jansUsrDN varchar(128) YES None jans Usr DN acr varchar(48) YES None uuid varchar(64) YES None Unique identifier chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash", "title": "jansUmaPCT"}, {"location": "janssen-server/reference/database/mysql-schema/#jansumarpt", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authnTime datetime(3) YES None jans Authn Time clnId varchar(64) YES None jans Clnt id iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES None del tknCde varchar(80) YES None jans Tkn Code usrId varchar(64) YES None jans user id ssnId varchar(64) YES None jans Sess DN jansUmaPermission json YES None jans uma permission uuid varchar(64) YES None Unique identifier dpop varchar(64) YES None DPoP Proof authzCode varchar(64) YES None jans authorization code grtId varchar(64) YES None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknTyp varchar(32) YES None jans Tkn Typ jansUsrDN varchar(128) YES None jans Usr DN acr varchar(48) YES None chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash", "title": "jansUmaRPT"}, {"location": "janssen-server/reference/database/mysql-schema/#jansumaresource", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries inum varchar(64) YES None XRI i-number owner varchar(64) YES None jansAssociatedClnt json YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. jansUmaScope varchar(768) YES MUL None URI reference of scope descriptor jansFaviconImage varchar(64) YES None TODO - Stores URL of favicon jansGrp varchar(64) YES None Group jansId varchar(128) YES MUL None Identifier jansResource tinytext YES None Host path jansRevision int YES None Revision jansTyp varchar(64) YES None jans type jansScopeExpression text YES None Scope expression iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del description varchar(768) YES None", "title": "jansUmaResource"}, {"location": "janssen-server/reference/database/mysql-schema/#jansumaresourcepermission", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None exp datetime(3) YES None jans Exp del smallint YES None del jansUmaScope varchar(768) YES None URI reference of scope descriptor jansConfCode varchar(64) YES None jans configuration code jansResourceSetId varchar(64) YES None jans resource set id jansAttrs text YES None Attrs jansTicket varchar(64) YES MUL None jans ticket jansStatus varchar(16) YES None Status of the entry, used by many objectclasses", "title": "jansUmaResourcePermission"}, {"location": "janssen-server/reference/database/pgsql-config/", "tags": ["administration", "reference", "database", "remote database"], "text": "PostgreSQL ORM persistence layer # The recommended PostgreSQL versions are 14.x, 15.x or newer. Before running installation the administrator can pre-install DB and provide credentials to access it or he can select option to install PostgreSQL on same server during setup. During installation setup generates default /etc/jans/conf/jans-sql.properties and creates jansdb schema with tables and initial data set. Configuration properties # List of specific for PostgreSQL default setting from jans-sql.properties : db.schema.name=public connection.uri=jdbc:postgresql://localhost:5432/jansdb # Prefix connection.driver-property.key=value will be coverterd to key=value JDBC driver properties #connection.driver-property.driverProperty=driverPropertyValue auth.userName=jans auth.userPassword=CC0NHhtXW78= # Password hash method password.encryption.method=SSHA-256 # Connection pool size connection.pool.max-total=40 connection.pool.max-idle=15 connection.pool.min-idle=5 # Max time needed to create connection pool in milliseconds connection.pool.create-max-wait-time-millis=20000 # Max wait 20 seconds connection.pool.max-wait-time-millis=20000 # Allow to evict connection in pool after 30 minutes connection.pool.min-evictable-idle-time-millis=1800000 # Sets whether objects created for the pool will be validated before being returned from it #connection.pool.test-on-create=true # Sets whether objects borrowed from the pool will be validated when they are returned to the pool #connection.pool.test-on-return=true The rest of properties are static for all other supported DB: binaryAttributes=objectGUID certificateAttributes=userCertificate doc_id building rules # In order to support transparency for end applications and allow data migration from one DB to another ORM requires DN attribute in each entry. This attribute it also uses to build doc_id . Here is example of this DN -> doc_id conversion: doc_id is primary key. In order to build unique document identifier ORM uses another unique attribute DN . doc_id is last RDN value. Generic tables structure # Each table in jansdb PostgreSQL database follow next rules: one table for every objectClass has 2 mandatory column DN and doc_id Index for primary key Data mapping rules # ORM uses CHARACTER VARYING / TIMESTAMP / INT64 / BYTEA / BOOLEAN / TEXT / JSONB data types. JSONB it uses to store multi-valued attribute values. The generic format of such values is: [\"value_1\", \"value_2\", ...] If in schema specified in schema that application can do search in multi-valued attribute setup add next indexes for each column: CREATE INDEX IF NOT EXISTS \"jansPerson_jsonb_path_query_array_idx\" ON public.\"jansPerson\" USING gin (jsonb_path_query_array(\"jansExtUid\", '$[*]'::jsonpath)) TABLESPACE pg_default; For user password field ORM on persist/update operations automatically create hash. On authentication ORM compares hashes. To store attributes defined in java beans with @JsonObject annotation ORM uses TEXT column type. Java example # This example shows how to use ORM. It opens connection to PostgreSQL DB and add user entry to it: public static void main(String[] args) { // Create Sql entry manager SqlEntryManager couchbaseEntryManager = createSqlEntryManager(); // Create and fill user bean SimpleUser newUser = new SimpleUser(); newUser.setDn(String.format(\"inum=%s,ou=people,o=jans\", System.currentTimeMillis())); newUser.setUserId(\"sample_user_\" + System.currentTimeMillis()); newUser.setUserPassword(\"test\"); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansAddress\", Arrays.asList(\"London\", \"Texas\", \"New York\"))); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); // Call ORM API to store entry couchbaseEntryManager.persist(newUser); couchbaseEntryManager.destroy(); } public static SqlEntryManager createSqlEntryManager() { SqlEntryManagerFactory couchbaseEntryManagerFactory = new SqlEntryManagerFactory(); couchbaseEntryManagerFactory.create(); Properties connectionProperties = getSampleConnectionProperties(); SqlEntryManager couchbaseEntryManager = couchbaseEntryManagerFactory.createEntryManager(connectionProperties); return couchbaseEntryManager; } private static Properties getSampleConnectionProperties() { Properties connectionProperties = new Properties(); connectionProperties.put(\"sql#db.schema.name\", \"public\"); connectionProperties.put(\"sql#connection.uri\", \"jdbc:postgresql://localhost:5432/jansdb\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"secret\"); connectionProperties.put(\"sql#connection.pool.max-total\", \"300\"); connectionProperties.put(\"sql#connection.pool.max-idle\", \"300\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"Secret1!\"); // Password hash method connectionProperties.put(\"sql#password.encryption.method\", \"SSHA-256\"); // Max time needed to create connection pool in milliseconds connectionProperties.put(\"sql#connection.pool.create-max-wait-time-millis\", \"20000\"); // Max wait 20 seconds connectionProperties.put(\"sql#connection.pool.max-wait-time-millis\", \"20000\"); // Allow to evict connection in pool after 30 minutes connectionProperties.put(\"sql#connection.pool.min-evictable-idle-time-millis\", \"1800000\"); connectionProperties.put(\"sql#binaryAttributes\", \"objectGUID\"); connectionProperties.put(\"sql#certificateAttributes\", \"userCertificate\"); return connectionProperties; } More MySQL ORM examples is in this sample module.", "title": "PostgreSQL Configuration"}, {"location": "janssen-server/reference/database/pgsql-config/#postgresql-orm-persistence-layer", "text": "The recommended PostgreSQL versions are 14.x, 15.x or newer. Before running installation the administrator can pre-install DB and provide credentials to access it or he can select option to install PostgreSQL on same server during setup. During installation setup generates default /etc/jans/conf/jans-sql.properties and creates jansdb schema with tables and initial data set.", "title": "PostgreSQL ORM persistence layer"}, {"location": "janssen-server/reference/database/pgsql-config/#configuration-properties", "text": "List of specific for PostgreSQL default setting from jans-sql.properties : db.schema.name=public connection.uri=jdbc:postgresql://localhost:5432/jansdb # Prefix connection.driver-property.key=value will be coverterd to key=value JDBC driver properties #connection.driver-property.driverProperty=driverPropertyValue auth.userName=jans auth.userPassword=CC0NHhtXW78= # Password hash method password.encryption.method=SSHA-256 # Connection pool size connection.pool.max-total=40 connection.pool.max-idle=15 connection.pool.min-idle=5 # Max time needed to create connection pool in milliseconds connection.pool.create-max-wait-time-millis=20000 # Max wait 20 seconds connection.pool.max-wait-time-millis=20000 # Allow to evict connection in pool after 30 minutes connection.pool.min-evictable-idle-time-millis=1800000 # Sets whether objects created for the pool will be validated before being returned from it #connection.pool.test-on-create=true # Sets whether objects borrowed from the pool will be validated when they are returned to the pool #connection.pool.test-on-return=true The rest of properties are static for all other supported DB: binaryAttributes=objectGUID certificateAttributes=userCertificate", "title": "Configuration properties"}, {"location": "janssen-server/reference/database/pgsql-config/#doc_id-building-rules", "text": "In order to support transparency for end applications and allow data migration from one DB to another ORM requires DN attribute in each entry. This attribute it also uses to build doc_id . Here is example of this DN -> doc_id conversion: doc_id is primary key. In order to build unique document identifier ORM uses another unique attribute DN . doc_id is last RDN value.", "title": "doc_id building rules"}, {"location": "janssen-server/reference/database/pgsql-config/#generic-tables-structure", "text": "Each table in jansdb PostgreSQL database follow next rules: one table for every objectClass has 2 mandatory column DN and doc_id Index for primary key", "title": "Generic tables structure"}, {"location": "janssen-server/reference/database/pgsql-config/#data-mapping-rules", "text": "ORM uses CHARACTER VARYING / TIMESTAMP / INT64 / BYTEA / BOOLEAN / TEXT / JSONB data types. JSONB it uses to store multi-valued attribute values. The generic format of such values is: [\"value_1\", \"value_2\", ...] If in schema specified in schema that application can do search in multi-valued attribute setup add next indexes for each column: CREATE INDEX IF NOT EXISTS \"jansPerson_jsonb_path_query_array_idx\" ON public.\"jansPerson\" USING gin (jsonb_path_query_array(\"jansExtUid\", '$[*]'::jsonpath)) TABLESPACE pg_default; For user password field ORM on persist/update operations automatically create hash. On authentication ORM compares hashes. To store attributes defined in java beans with @JsonObject annotation ORM uses TEXT column type.", "title": "Data mapping rules"}, {"location": "janssen-server/reference/database/pgsql-config/#java-example", "text": "This example shows how to use ORM. It opens connection to PostgreSQL DB and add user entry to it: public static void main(String[] args) { // Create Sql entry manager SqlEntryManager couchbaseEntryManager = createSqlEntryManager(); // Create and fill user bean SimpleUser newUser = new SimpleUser(); newUser.setDn(String.format(\"inum=%s,ou=people,o=jans\", System.currentTimeMillis())); newUser.setUserId(\"sample_user_\" + System.currentTimeMillis()); newUser.setUserPassword(\"test\"); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansAddress\", Arrays.asList(\"London\", \"Texas\", \"New York\"))); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); // Call ORM API to store entry couchbaseEntryManager.persist(newUser); couchbaseEntryManager.destroy(); } public static SqlEntryManager createSqlEntryManager() { SqlEntryManagerFactory couchbaseEntryManagerFactory = new SqlEntryManagerFactory(); couchbaseEntryManagerFactory.create(); Properties connectionProperties = getSampleConnectionProperties(); SqlEntryManager couchbaseEntryManager = couchbaseEntryManagerFactory.createEntryManager(connectionProperties); return couchbaseEntryManager; } private static Properties getSampleConnectionProperties() { Properties connectionProperties = new Properties(); connectionProperties.put(\"sql#db.schema.name\", \"public\"); connectionProperties.put(\"sql#connection.uri\", \"jdbc:postgresql://localhost:5432/jansdb\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"secret\"); connectionProperties.put(\"sql#connection.pool.max-total\", \"300\"); connectionProperties.put(\"sql#connection.pool.max-idle\", \"300\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"Secret1!\"); // Password hash method connectionProperties.put(\"sql#password.encryption.method\", \"SSHA-256\"); // Max time needed to create connection pool in milliseconds connectionProperties.put(\"sql#connection.pool.create-max-wait-time-millis\", \"20000\"); // Max wait 20 seconds connectionProperties.put(\"sql#connection.pool.max-wait-time-millis\", \"20000\"); // Allow to evict connection in pool after 30 minutes connectionProperties.put(\"sql#connection.pool.min-evictable-idle-time-millis\", \"1800000\"); connectionProperties.put(\"sql#binaryAttributes\", \"objectGUID\"); connectionProperties.put(\"sql#certificateAttributes\", \"userCertificate\"); return connectionProperties; } More MySQL ORM examples is in this sample module.", "title": "Java example"}, {"location": "janssen-server/reference/database/pgsql-ops/", "tags": ["administration", "reference", "database"], "text": "PostgreSQL Operations # PostgreSQL is a versatile and reliable database management system that empowers developers and organizations to build robust and efficient applications. Establish Connection to Jans PostgreSQL Server # Connect to PostgreSql workspace: sudo -u postgres psql Show all Database list : \\list or \\l You will see jansdb in the list of database. Let's make a connection with jansdb : \\c jansdb Search user # Change database: \\c jansdb Search for user testUser : SELECT * FROM \"jansPerson\" WHERE uid = 'testuser'; If you want pretty output, enable display mode with \\x Re-run search query. Change password for user jans # Changing user 'jans' password to \"secret\": ALTER USER jans WITH PASSWORD 'secret'; Add user in Jans Group # Get DN of target user. i.e. we are searching for DN of user 'testUser' with: SELECT * FROM \"jansPerson\" WHERE uid = 'testuser'; Get DN of Jans Admin Group. i.e. SELECT * FROM \"jansGrp\"; Add ( actually append ) new user in member of this group: UPDATE \"jansGrp\" SET member = '[\"inum=d33a2ce9-e9de-4f74-8a7d-2519f73635b7,ou=people,o=jans\", \"inum=618d7792-caca-4915-8b92-9955bf94affb,ou=people,o=jans\"]'; List users with specific filter # To search for users with a filter using PostgreSQL's command-line tool psql, you can use the SELECT statement with the WHERE clause to apply filters to the query. Here's the query to find specific user: SELECT * FROM \"jansPerson\" WHERE uid= '<uid>'; Modify column size of Jans postgresql # The psql command-line tool, you can use the \\d+ command to display detailed information about a table, including its columns. Lets see the details of jansPerson table: \\d+ \"jansPerson\"; To modify the size of a column in a PostgreSQL table, you will need to use the ALTER TABLE statement along with the ALTER COLUMN clause. Here's how you can modify the size of a column: ALTER TABLE \"jansPerson\" ALTER COLUMN mail TYPE VARCHAR(100); Add custom attribute # To add a custom attribute to an existing PostgreSQL table, you can use the ALTER TABLE statement with the ADD COLUMN clause. Here's how you can add a custom attribute in jansPerson table: ALTER TABLE \"jansPerson\" ADD COLUMN membership_level VARCHAR(50); You can also specify additional constraints, defaults, or other attributes for the new column as needed. Here's an example with a default value: ALTER TABLE \"jansPerson\" ADD COLUMN membership_level VARCHAR DEFAULT 'Basic'; Output column data into txt # If you want to output the data from a PostgreSQL table's column into a text file, you can use the COPY command. This command allows you to copy the contents of a table or query result into an external file. Here's how you can do it: COPY (SELECT * FROM \"jansPerson\") TO '/tmp/output.txt'; After executing the command, the data from the specified column will be copied into the specified text file. Back-up and re-store # PostgreSQL is a popular open-source relational database management system used for web applications, business intelligence, and other data-intensive applications. A critical aspect of managing a PostgreSQL database is ensuring data protection by having a backup and restore strategy in place. Back-up # To dump the PostgreSQL database, you can use the pg_dump command-line utility. To back-up your database pg_dump -h localhost -U \"<user>\" \"<dbName>\" -Fc > /tmp/back-up.sql Re-store # To restore the backup file you need to use pg_restore . pg_restore -h localhost -U \"<user>\" -d <db_name> <back-up.sql> Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "PostgreSQL Operation"}, {"location": "janssen-server/reference/database/pgsql-ops/#postgresql-operations", "text": "PostgreSQL is a versatile and reliable database management system that empowers developers and organizations to build robust and efficient applications.", "title": "PostgreSQL Operations"}, {"location": "janssen-server/reference/database/pgsql-ops/#establish-connection-to-jans-postgresql-server", "text": "Connect to PostgreSql workspace: sudo -u postgres psql Show all Database list : \\list or \\l You will see jansdb in the list of database. Let's make a connection with jansdb : \\c jansdb", "title": "Establish Connection to Jans PostgreSQL Server"}, {"location": "janssen-server/reference/database/pgsql-ops/#search-user", "text": "Change database: \\c jansdb Search for user testUser : SELECT * FROM \"jansPerson\" WHERE uid = 'testuser'; If you want pretty output, enable display mode with \\x Re-run search query.", "title": "Search user"}, {"location": "janssen-server/reference/database/pgsql-ops/#change-password-for-user-jans", "text": "Changing user 'jans' password to \"secret\": ALTER USER jans WITH PASSWORD 'secret';", "title": "Change password for user jans"}, {"location": "janssen-server/reference/database/pgsql-ops/#add-user-in-jans-group", "text": "Get DN of target user. i.e. we are searching for DN of user 'testUser' with: SELECT * FROM \"jansPerson\" WHERE uid = 'testuser'; Get DN of Jans Admin Group. i.e. SELECT * FROM \"jansGrp\"; Add ( actually append ) new user in member of this group: UPDATE \"jansGrp\" SET member = '[\"inum=d33a2ce9-e9de-4f74-8a7d-2519f73635b7,ou=people,o=jans\", \"inum=618d7792-caca-4915-8b92-9955bf94affb,ou=people,o=jans\"]';", "title": "Add user in Jans Group"}, {"location": "janssen-server/reference/database/pgsql-ops/#list-users-with-specific-filter", "text": "To search for users with a filter using PostgreSQL's command-line tool psql, you can use the SELECT statement with the WHERE clause to apply filters to the query. Here's the query to find specific user: SELECT * FROM \"jansPerson\" WHERE uid= '<uid>';", "title": "List users with specific filter"}, {"location": "janssen-server/reference/database/pgsql-ops/#modify-column-size-of-jans-postgresql", "text": "The psql command-line tool, you can use the \\d+ command to display detailed information about a table, including its columns. Lets see the details of jansPerson table: \\d+ \"jansPerson\"; To modify the size of a column in a PostgreSQL table, you will need to use the ALTER TABLE statement along with the ALTER COLUMN clause. Here's how you can modify the size of a column: ALTER TABLE \"jansPerson\" ALTER COLUMN mail TYPE VARCHAR(100);", "title": "Modify column size of Jans postgresql"}, {"location": "janssen-server/reference/database/pgsql-ops/#add-custom-attribute", "text": "To add a custom attribute to an existing PostgreSQL table, you can use the ALTER TABLE statement with the ADD COLUMN clause. Here's how you can add a custom attribute in jansPerson table: ALTER TABLE \"jansPerson\" ADD COLUMN membership_level VARCHAR(50); You can also specify additional constraints, defaults, or other attributes for the new column as needed. Here's an example with a default value: ALTER TABLE \"jansPerson\" ADD COLUMN membership_level VARCHAR DEFAULT 'Basic';", "title": "Add custom attribute"}, {"location": "janssen-server/reference/database/pgsql-ops/#output-column-data-into-txt", "text": "If you want to output the data from a PostgreSQL table's column into a text file, you can use the COPY command. This command allows you to copy the contents of a table or query result into an external file. Here's how you can do it: COPY (SELECT * FROM \"jansPerson\") TO '/tmp/output.txt'; After executing the command, the data from the specified column will be copied into the specified text file.", "title": "Output column data into txt"}, {"location": "janssen-server/reference/database/pgsql-ops/#back-up-and-re-store", "text": "PostgreSQL is a popular open-source relational database management system used for web applications, business intelligence, and other data-intensive applications. A critical aspect of managing a PostgreSQL database is ensuring data protection by having a backup and restore strategy in place.", "title": "Back-up and re-store"}, {"location": "janssen-server/reference/database/pgsql-ops/#back-up", "text": "To dump the PostgreSQL database, you can use the pg_dump command-line utility. To back-up your database pg_dump -h localhost -U \"<user>\" \"<dbName>\" -Fc > /tmp/back-up.sql", "title": "Back-up"}, {"location": "janssen-server/reference/database/pgsql-ops/#re-store", "text": "To restore the backup file you need to use pg_restore . pg_restore -h localhost -U \"<user>\" -d <db_name> <back-up.sql>", "title": "Re-store"}, {"location": "janssen-server/reference/database/pgsql-ops/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/", "tags": ["administration", "database", "PostgreSQL", "Indexes"], "text": "PostgreSQL Indexes # jansPairwiseIdentifier # tablename indexname indexdef jansPairwiseIdentifier jansPairwiseIdentifier_pkey CREATE UNIQUE INDEX \"jansPairwiseIdentifier_pkey\" ON public.\"jansPairwiseIdentifier\" USING btree (doc_id) jansPerson # tablename indexname indexdef jansPerson jansPerson_pkey CREATE UNIQUE INDEX \"jansPerson_pkey\" ON public.\"jansPerson\" USING btree (doc_id) jansPerson jansPerson_givenName_idx CREATE INDEX \"jansPerson_givenName_idx\" ON public.\"jansPerson\" USING btree (\"givenName\") jansPerson jansPerson_mail_idx CREATE INDEX \"jansPerson_mail_idx\" ON public.\"jansPerson\" USING btree (mail) jansPerson jansPerson_sn_idx CREATE INDEX \"jansPerson_sn_idx\" ON public.\"jansPerson\" USING btree (sn) jansPerson jansPerson_lower_idx CREATE INDEX \"jansPerson_lower_idx\" ON public.\"jansPerson\" USING btree (lower((uid)::text)) jansPerson jansPerson_displayName_idx CREATE INDEX \"jansPerson_displayName_idx\" ON public.\"jansPerson\" USING btree (\"displayName\") jansPerson jansPerson_inum_idx CREATE INDEX \"jansPerson_inum_idx\" ON public.\"jansPerson\" USING btree (inum) jansPerson jansPerson_jsonb_path_query_array_idx CREATE INDEX \"jansPerson_jsonb_path_query_array_idx\" ON public.\"jansPerson\" USING gin (jsonb_path_query_array(\"jansExtUid\", '$[*]'::jsonpath)) jansPerson jansPerson_uid_idx CREATE INDEX \"jansPerson_uid_idx\" ON public.\"jansPerson\" USING btree (uid) jansPerson jansPerson_lower_idx1 CREATE INDEX \"jansPerson_lower_idx1\" ON public.\"jansPerson\" USING btree (lower((mail)::text)) jansOrganization # tablename indexname indexdef jansOrganization jansOrganization_pkey CREATE UNIQUE INDEX \"jansOrganization_pkey\" ON public.\"jansOrganization\" USING btree (doc_id) jansOrganization jansOrganization_uid_idx CREATE INDEX \"jansOrganization_uid_idx\" ON public.\"jansOrganization\" USING btree (uid) jansSsa # tablename indexname indexdef jansSsa jansSsa_pkey CREATE UNIQUE INDEX \"jansSsa_pkey\" ON public.\"jansSsa\" USING btree (doc_id) jansAppConf # tablename indexname indexdef jansAppConf jansAppConf_pkey CREATE UNIQUE INDEX \"jansAppConf_pkey\" ON public.\"jansAppConf\" USING btree (doc_id) jansClnt # tablename indexname indexdef jansClnt jansClnt_pkey CREATE UNIQUE INDEX \"jansClnt_pkey\" ON public.\"jansClnt\" USING btree (doc_id) jansClnt jansClnt_description_idx CREATE INDEX \"jansClnt_description_idx\" ON public.\"jansClnt\" USING btree (description) jansClnt jansClnt_jansClntSecretExpAt_idx CREATE INDEX \"jansClnt_jansClntSecretExpAt_idx\" ON public.\"jansClnt\" USING btree (\"jansClntSecretExpAt\") jansClnt jansClnt_del_exp_idx CREATE INDEX \"jansClnt_del_exp_idx\" ON public.\"jansClnt\" USING btree (del, exp) jansClnt jansClnt_displayName_idx CREATE INDEX \"jansClnt_displayName_idx\" ON public.\"jansClnt\" USING btree (\"displayName\") jansClnt jansClnt_inum_idx CREATE INDEX \"jansClnt_inum_idx\" ON public.\"jansClnt\" USING btree (inum) jansClnt jansClnt_jansRegistrationAccessTkn_idx CREATE INDEX \"jansClnt_jansRegistrationAccessTkn_idx\" ON public.\"jansClnt\" USING btree (\"jansRegistrationAccessTkn\") jansScope # tablename indexname indexdef jansScope jansScope_pkey CREATE UNIQUE INDEX \"jansScope_pkey\" ON public.\"jansScope\" USING btree (doc_id) jansScope jansScope_displayName_idx CREATE INDEX \"jansScope_displayName_idx\" ON public.\"jansScope\" USING btree (\"displayName\") jansScope jansScope_del_exp_idx CREATE INDEX \"jansScope_del_exp_idx\" ON public.\"jansScope\" USING btree (del, exp) jansScope jansScope_description_idx CREATE INDEX \"jansScope_description_idx\" ON public.\"jansScope\" USING btree (description) jansScope jansScope_jansId_idx CREATE INDEX \"jansScope_jansId_idx\" ON public.\"jansScope\" USING btree (\"jansId\") jansUmaResource # tablename indexname indexdef jansUmaResource jansUmaResource_pkey CREATE UNIQUE INDEX \"jansUmaResource_pkey\" ON public.\"jansUmaResource\" USING btree (doc_id) jansUmaResource jansUmaResource_jansUmaScope_idx CREATE INDEX \"jansUmaResource_jansUmaScope_idx\" ON public.\"jansUmaResource\" USING btree (\"jansUmaScope\") jansUmaResource jansUmaResource_del_exp_idx CREATE INDEX \"jansUmaResource_del_exp_idx\" ON public.\"jansUmaResource\" USING btree (del, exp) jansUmaResource jansUmaResource_displayName_idx CREATE INDEX \"jansUmaResource_displayName_idx\" ON public.\"jansUmaResource\" USING btree (\"displayName\") jansUmaResource jansUmaResource_jansId_idx CREATE INDEX \"jansUmaResource_jansId_idx\" ON public.\"jansUmaResource\" USING btree (\"jansId\") jansUmaResourcePermission # tablename indexname indexdef jansUmaResourcePermission jansUmaResourcePermission_pkey CREATE UNIQUE INDEX \"jansUmaResourcePermission_pkey\" ON public.\"jansUmaResourcePermission\" USING btree (doc_id) jansUmaResourcePermission jansUmaResourcePermission_jansTicket_idx CREATE INDEX \"jansUmaResourcePermission_jansTicket_idx\" ON public.\"jansUmaResourcePermission\" USING btree (\"jansTicket\") jansGrant # tablename indexname indexdef jansGrant jansGrant_pkey CREATE UNIQUE INDEX \"jansGrant_pkey\" ON public.\"jansGrant\" USING btree (doc_id) jansToken # tablename indexname indexdef jansToken jansToken_pkey CREATE UNIQUE INDEX \"jansToken_pkey\" ON public.\"jansToken\" USING btree (doc_id) jansToken jansToken_authzCode_idx CREATE INDEX \"jansToken_authzCode_idx\" ON public.\"jansToken\" USING btree (\"authzCode\") jansToken jansToken_grtId_idx CREATE INDEX \"jansToken_grtId_idx\" ON public.\"jansToken\" USING btree (\"grtId\") jansToken jansToken_ssnId_idx CREATE INDEX \"jansToken_ssnId_idx\" ON public.\"jansToken\" USING btree (\"ssnId\") jansToken jansToken_tknCde_idx CREATE INDEX \"jansToken_tknCde_idx\" ON public.\"jansToken\" USING btree (\"tknCde\") jansToken jansToken_del_exp_idx CREATE INDEX \"jansToken_del_exp_idx\" ON public.\"jansToken\" USING btree (del, exp) jansGrp # tablename indexname indexdef jansGrp jansGrp_pkey CREATE UNIQUE INDEX \"jansGrp_pkey\" ON public.\"jansGrp\" USING btree (doc_id) jansGrp jansGrp_description_idx CREATE INDEX \"jansGrp_description_idx\" ON public.\"jansGrp\" USING btree (description) jansGrp jansGrp_inum_idx CREATE INDEX \"jansGrp_inum_idx\" ON public.\"jansGrp\" USING btree (inum) jansGrp jansGrp_displayName_idx CREATE INDEX \"jansGrp_displayName_idx\" ON public.\"jansGrp\" USING btree (\"displayName\") jansAttr # tablename indexname indexdef jansAttr jansAttr_pkey CREATE UNIQUE INDEX \"jansAttr_pkey\" ON public.\"jansAttr\" USING btree (doc_id) jansAttr jansAttr_description_idx CREATE INDEX \"jansAttr_description_idx\" ON public.\"jansAttr\" USING btree (description) jansAttr jansAttr_jansAttrName_idx CREATE INDEX \"jansAttr_jansAttrName_idx\" ON public.\"jansAttr\" USING btree (\"jansAttrName\") jansAttr jansAttr_inum_idx CREATE INDEX \"jansAttr_inum_idx\" ON public.\"jansAttr\" USING btree (inum) jansAttr jansAttr_displayName_idx CREATE INDEX \"jansAttr_displayName_idx\" ON public.\"jansAttr\" USING btree (\"displayName\") jansAttr jansAttr_jansAttrOrigin_idx CREATE INDEX \"jansAttr_jansAttrOrigin_idx\" ON public.\"jansAttr\" USING btree (\"jansAttrOrigin\") jansPassResetReq # tablename indexname indexdef jansPassResetReq jansPassResetReq_pkey CREATE UNIQUE INDEX \"jansPassResetReq_pkey\" ON public.\"jansPassResetReq\" USING btree (doc_id) jansPassResetReq jansPassResetReq_creationDate_idx CREATE INDEX \"jansPassResetReq_creationDate_idx\" ON public.\"jansPassResetReq\" USING btree (\"creationDate\") jansSessId # tablename indexname indexdef jansSessId jansSessId_pkey CREATE UNIQUE INDEX \"jansSessId_pkey\" ON public.\"jansSessId\" USING btree (doc_id) jansSessId jansSessId_sid_idx CREATE INDEX \"jansSessId_sid_idx\" ON public.\"jansSessId\" USING btree (sid) jansSessId jansSessId_deviceSecret_idx CREATE INDEX \"jansSessId_deviceSecret_idx\" ON public.\"jansSessId\" USING btree (\"deviceSecret\") jansSessId jansSessId_jansUsrDN_idx CREATE INDEX \"jansSessId_jansUsrDN_idx\" ON public.\"jansSessId\" USING btree (\"jansUsrDN\") jansSessId jansSessId_del_exp_idx CREATE INDEX \"jansSessId_del_exp_idx\" ON public.\"jansSessId\" USING btree (del, exp) jansUmaRPT # tablename indexname indexdef jansUmaRPT jansUmaRPT_pkey CREATE UNIQUE INDEX \"jansUmaRPT_pkey\" ON public.\"jansUmaRPT\" USING btree (doc_id) jansPushApp # tablename indexname indexdef jansPushApp jansPushApp_pkey CREATE UNIQUE INDEX \"jansPushApp_pkey\" ON public.\"jansPushApp\" USING btree (doc_id) jansScr # tablename indexname indexdef jansScr jansScr_pkey CREATE UNIQUE INDEX \"jansScr_pkey\" ON public.\"jansScr\" USING btree (doc_id) jansCustomScr # tablename indexname indexdef jansCustomScr jansCustomScr_pkey CREATE UNIQUE INDEX \"jansCustomScr_pkey\" ON public.\"jansCustomScr\" USING btree (doc_id) jansCustomScr jansCustomScr_inum_idx CREATE INDEX \"jansCustomScr_inum_idx\" ON public.\"jansCustomScr\" USING btree (inum) jansCustomScr jansCustomScr_jansScrTyp_idx CREATE INDEX \"jansCustomScr_jansScrTyp_idx\" ON public.\"jansCustomScr\" USING btree (\"jansScrTyp\") jansDeviceRegistration # tablename indexname indexdef jansDeviceRegistration jansDeviceRegistration_pkey CREATE UNIQUE INDEX \"jansDeviceRegistration_pkey\" ON public.\"jansDeviceRegistration\" USING btree (doc_id) jansDeviceRegistration jansDeviceRegistration_jansDeviceKeyHandle_idx CREATE INDEX \"jansDeviceRegistration_jansDeviceKeyHandle_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansDeviceKeyHandle\") jansDeviceRegistration jansDeviceRegistration_jansApp_idx CREATE INDEX \"jansDeviceRegistration_jansApp_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansApp\") jansDeviceRegistration jansDeviceRegistration_personInum_idx CREATE INDEX \"jansDeviceRegistration_personInum_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"personInum\") jansDeviceRegistration jansDeviceRegistration_del_exp_idx CREATE INDEX \"jansDeviceRegistration_del_exp_idx\" ON public.\"jansDeviceRegistration\" USING btree (del, exp) jansDeviceRegistration jansDeviceRegistration_jansDeviceHashCode_idx CREATE INDEX \"jansDeviceRegistration_jansDeviceHashCode_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansDeviceHashCode\") jansDeviceRegistration jansDeviceRegistration_jansStatus_idx CREATE INDEX \"jansDeviceRegistration_jansStatus_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansStatus\") jansDeviceRegistration jansDeviceRegistration_creationDate_idx CREATE INDEX \"jansDeviceRegistration_creationDate_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"creationDate\") jansU2fReq # tablename indexname indexdef jansU2fReq jansU2fReq_pkey CREATE UNIQUE INDEX \"jansU2fReq_pkey\" ON public.\"jansU2fReq\" USING btree (doc_id) jansU2fReq jansU2fReq_del_exp_idx CREATE INDEX \"jansU2fReq_del_exp_idx\" ON public.\"jansU2fReq\" USING btree (del, exp) jansU2fReq jansU2fReq_creationDate_idx CREATE INDEX \"jansU2fReq_creationDate_idx\" ON public.\"jansU2fReq\" USING btree (\"creationDate\") jansMetric # tablename indexname indexdef jansMetric jansMetric_pkey CREATE UNIQUE INDEX \"jansMetric_pkey\" ON public.\"jansMetric\" USING btree (doc_id) jansMetric jansMetric_jansEndDate_idx CREATE INDEX \"jansMetric_jansEndDate_idx\" ON public.\"jansMetric\" USING btree (\"jansEndDate\") jansMetric jansMetric_jansMetricTyp_idx CREATE INDEX \"jansMetric_jansMetricTyp_idx\" ON public.\"jansMetric\" USING btree (\"jansMetricTyp\") jansMetric jansMetric_jansStartDate_idx CREATE INDEX \"jansMetric_jansStartDate_idx\" ON public.\"jansMetric\" USING btree (\"jansStartDate\") jansMetric jansMetric_jansAppTyp_idx CREATE INDEX \"jansMetric_jansAppTyp_idx\" ON public.\"jansMetric\" USING btree (\"jansAppTyp\") jansMetric jansMetric_del_exp_idx CREATE INDEX \"jansMetric_del_exp_idx\" ON public.\"jansMetric\" USING btree (del, exp) jansUmaPCT # tablename indexname indexdef jansUmaPCT jansUmaPCT_pkey CREATE UNIQUE INDEX \"jansUmaPCT_pkey\" ON public.\"jansUmaPCT\" USING btree (doc_id) jansUmaPCT jansUmaPCT_tknCde_idx CREATE INDEX \"jansUmaPCT_tknCde_idx\" ON public.\"jansUmaPCT\" USING btree (\"tknCde\") jansUmaPCT jansUmaPCT_del_exp_idx CREATE INDEX \"jansUmaPCT_del_exp_idx\" ON public.\"jansUmaPCT\" USING btree (del, exp) jansCache # tablename indexname indexdef jansCache jansCache_pkey CREATE UNIQUE INDEX \"jansCache_pkey\" ON public.\"jansCache\" USING btree (doc_id) jansCache jansCache_del_exp_idx CREATE INDEX \"jansCache_del_exp_idx\" ON public.\"jansCache\" USING btree (del, exp) jansFido2RegistrationEntry # tablename indexname indexdef jansFido2RegistrationEntry jansFido2RegistrationEntry_pkey CREATE UNIQUE INDEX \"jansFido2RegistrationEntry_pkey\" ON public.\"jansFido2RegistrationEntry\" USING btree (doc_id) jansFido2RegistrationEntry jansFido2RegistrationEntry_jansApp_idx CREATE INDEX \"jansFido2RegistrationEntry_jansApp_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansApp\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansCodeChallengeHash_idx CREATE INDEX \"jansFido2RegistrationEntry_jansCodeChallengeHash_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansCodeChallengeHash\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansPublicKeyIdHash_idx CREATE INDEX \"jansFido2RegistrationEntry_jansPublicKeyIdHash_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansPublicKeyIdHash\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansStatus_idx CREATE INDEX \"jansFido2RegistrationEntry_jansStatus_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansStatus\") jansFido2RegistrationEntry jansFido2RegistrationEntry_creationDate_idx CREATE INDEX \"jansFido2RegistrationEntry_creationDate_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"creationDate\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansCodeChallenge_idx CREATE INDEX \"jansFido2RegistrationEntry_jansCodeChallenge_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansCodeChallenge\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansPublicKeyId_idx CREATE INDEX \"jansFido2RegistrationEntry_jansPublicKeyId_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansPublicKeyId\") jansFido2RegistrationEntry jansFido2RegistrationEntry_personInum_idx CREATE INDEX \"jansFido2RegistrationEntry_personInum_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"personInum\") jansFido2RegistrationEntry jansFido2RegistrationEntry_del_exp_idx CREATE INDEX \"jansFido2RegistrationEntry_del_exp_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (del, exp) jansPushDevice # tablename indexname indexdef jansPushDevice jansPushDevice_pkey CREATE UNIQUE INDEX \"jansPushDevice_pkey\" ON public.\"jansPushDevice\" USING btree (doc_id) jansClntAuthz # tablename indexname indexdef jansClntAuthz jansClntAuthz_pkey CREATE UNIQUE INDEX \"jansClntAuthz_pkey\" ON public.\"jansClntAuthz\" USING btree (doc_id) jansClntAuthz jansClntAuthz_jsonb_path_query_array_idx CREATE INDEX \"jansClntAuthz_jsonb_path_query_array_idx\" ON public.\"jansClntAuthz\" USING gin (jsonb_path_query_array(\"jansClntId\", '$[*]'::jsonpath)) jansClntAuthz jansClntAuthz_del_exp_idx CREATE INDEX \"jansClntAuthz_del_exp_idx\" ON public.\"jansClntAuthz\" USING btree (del, exp) jansClntAuthz jansClntAuthz_jansUsrId_idx CREATE INDEX \"jansClntAuthz_jansUsrId_idx\" ON public.\"jansClntAuthz\" USING btree (\"jansUsrId\") jansSectorIdentifier # tablename indexname indexdef jansSectorIdentifier jansSectorIdentifier_pkey CREATE UNIQUE INDEX \"jansSectorIdentifier_pkey\" ON public.\"jansSectorIdentifier\" USING btree (doc_id) jansFido2AuthnEntry # tablename indexname indexdef jansFido2AuthnEntry jansFido2AuthnEntry_pkey CREATE UNIQUE INDEX \"jansFido2AuthnEntry_pkey\" ON public.\"jansFido2AuthnEntry\" USING btree (doc_id) jansFido2AuthnEntry jansFido2AuthnEntry_jansApp_idx CREATE INDEX \"jansFido2AuthnEntry_jansApp_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansApp\") jansFido2AuthnEntry jansFido2AuthnEntry_jansCodeChallengeHash_idx CREATE INDEX \"jansFido2AuthnEntry_jansCodeChallengeHash_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansCodeChallengeHash\") jansFido2AuthnEntry jansFido2AuthnEntry_jansStatus_idx CREATE INDEX \"jansFido2AuthnEntry_jansStatus_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansStatus\") jansFido2AuthnEntry jansFido2AuthnEntry_creationDate_idx CREATE INDEX \"jansFido2AuthnEntry_creationDate_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"creationDate\") jansFido2AuthnEntry jansFido2AuthnEntry_jansCodeChallenge_idx CREATE INDEX \"jansFido2AuthnEntry_jansCodeChallenge_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansCodeChallenge\") jansFido2AuthnEntry jansFido2AuthnEntry_personInum_idx CREATE INDEX \"jansFido2AuthnEntry_personInum_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"personInum\") jansFido2AuthnEntry jansFido2AuthnEntry_del_exp_idx CREATE INDEX \"jansFido2AuthnEntry_del_exp_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (del, exp) jansRp # tablename indexname indexdef jansRp jansRp_pkey CREATE UNIQUE INDEX \"jansRp_pkey\" ON public.\"jansRp\" USING btree (doc_id) jansCibaReq # tablename indexname indexdef jansCibaReq jansCibaReq_pkey CREATE UNIQUE INDEX \"jansCibaReq_pkey\" ON public.\"jansCibaReq\" USING btree (doc_id) jansCibaReq jansCibaReq_jansStatus_exp_idx CREATE INDEX \"jansCibaReq_jansStatus_exp_idx\" ON public.\"jansCibaReq\" USING btree (\"jansStatus\", exp) jansStatEntry # tablename indexname indexdef jansStatEntry jansStatEntry_pkey CREATE UNIQUE INDEX \"jansStatEntry_pkey\" ON public.\"jansStatEntry\" USING btree (doc_id) jansStatEntry jansStatEntry_jansId_idx CREATE INDEX \"jansStatEntry_jansId_idx\" ON public.\"jansStatEntry\" USING btree (\"jansId\") jansPar # tablename indexname indexdef jansPar jansPar_pkey CREATE UNIQUE INDEX \"jansPar_pkey\" ON public.\"jansPar\" USING btree (doc_id) jansPar jansPar_jansId_idx CREATE INDEX \"jansPar_jansId_idx\" ON public.\"jansPar\" USING btree (\"jansId\") jansPar jansPar_del_exp_idx CREATE INDEX \"jansPar_del_exp_idx\" ON public.\"jansPar\" USING btree (del, exp) jansInumMap # tablename indexname indexdef jansInumMap jansInumMap_pkey CREATE UNIQUE INDEX \"jansInumMap_pkey\" ON public.\"jansInumMap\" USING btree (doc_id) jansInumMap jansInumMap_jansStatus_idx CREATE INDEX \"jansInumMap_jansStatus_idx\" ON public.\"jansInumMap\" USING btree (\"jansStatus\") jansInumMap jansInumMap_inum_idx CREATE INDEX \"jansInumMap_inum_idx\" ON public.\"jansInumMap\" USING btree (inum) agmFlowRun # tablename indexname indexdef agmFlowRun agmFlowRun_pkey CREATE UNIQUE INDEX \"agmFlowRun_pkey\" ON public.\"agmFlowRun\" USING btree (doc_id) agmFlow # tablename indexname indexdef agmFlow agmFlow_pkey CREATE UNIQUE INDEX \"agmFlow_pkey\" ON public.\"agmFlow\" USING btree (doc_id) adsPrjDeployment # tablename indexname indexdef adsPrjDeployment adsPrjDeployment_pkey CREATE UNIQUE INDEX \"adsPrjDeployment_pkey\" ON public.\"adsPrjDeployment\" USING btree (doc_id) jansDocument # tablename indexname indexdef jansDocument jansDocument_pkey CREATE UNIQUE INDEX \"jansDocument_pkey\" ON public.\"jansDocument\" USING btree (doc_id)", "title": "PostgreSQL Indexes"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#postgresql-indexes", "text": "", "title": "PostgreSQL Indexes"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janspairwiseidentifier", "text": "tablename indexname indexdef jansPairwiseIdentifier jansPairwiseIdentifier_pkey CREATE UNIQUE INDEX \"jansPairwiseIdentifier_pkey\" ON public.\"jansPairwiseIdentifier\" USING btree (doc_id)", "title": "jansPairwiseIdentifier"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansperson", "text": "tablename indexname indexdef jansPerson jansPerson_pkey CREATE UNIQUE INDEX \"jansPerson_pkey\" ON public.\"jansPerson\" USING btree (doc_id) jansPerson jansPerson_givenName_idx CREATE INDEX \"jansPerson_givenName_idx\" ON public.\"jansPerson\" USING btree (\"givenName\") jansPerson jansPerson_mail_idx CREATE INDEX \"jansPerson_mail_idx\" ON public.\"jansPerson\" USING btree (mail) jansPerson jansPerson_sn_idx CREATE INDEX \"jansPerson_sn_idx\" ON public.\"jansPerson\" USING btree (sn) jansPerson jansPerson_lower_idx CREATE INDEX \"jansPerson_lower_idx\" ON public.\"jansPerson\" USING btree (lower((uid)::text)) jansPerson jansPerson_displayName_idx CREATE INDEX \"jansPerson_displayName_idx\" ON public.\"jansPerson\" USING btree (\"displayName\") jansPerson jansPerson_inum_idx CREATE INDEX \"jansPerson_inum_idx\" ON public.\"jansPerson\" USING btree (inum) jansPerson jansPerson_jsonb_path_query_array_idx CREATE INDEX \"jansPerson_jsonb_path_query_array_idx\" ON public.\"jansPerson\" USING gin (jsonb_path_query_array(\"jansExtUid\", '$[*]'::jsonpath)) jansPerson jansPerson_uid_idx CREATE INDEX \"jansPerson_uid_idx\" ON public.\"jansPerson\" USING btree (uid) jansPerson jansPerson_lower_idx1 CREATE INDEX \"jansPerson_lower_idx1\" ON public.\"jansPerson\" USING btree (lower((mail)::text))", "title": "jansPerson"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansorganization", "text": "tablename indexname indexdef jansOrganization jansOrganization_pkey CREATE UNIQUE INDEX \"jansOrganization_pkey\" ON public.\"jansOrganization\" USING btree (doc_id) jansOrganization jansOrganization_uid_idx CREATE INDEX \"jansOrganization_uid_idx\" ON public.\"jansOrganization\" USING btree (uid)", "title": "jansOrganization"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansssa", "text": "tablename indexname indexdef jansSsa jansSsa_pkey CREATE UNIQUE INDEX \"jansSsa_pkey\" ON public.\"jansSsa\" USING btree (doc_id)", "title": "jansSsa"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansappconf", "text": "tablename indexname indexdef jansAppConf jansAppConf_pkey CREATE UNIQUE INDEX \"jansAppConf_pkey\" ON public.\"jansAppConf\" USING btree (doc_id)", "title": "jansAppConf"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansclnt", "text": "tablename indexname indexdef jansClnt jansClnt_pkey CREATE UNIQUE INDEX \"jansClnt_pkey\" ON public.\"jansClnt\" USING btree (doc_id) jansClnt jansClnt_description_idx CREATE INDEX \"jansClnt_description_idx\" ON public.\"jansClnt\" USING btree (description) jansClnt jansClnt_jansClntSecretExpAt_idx CREATE INDEX \"jansClnt_jansClntSecretExpAt_idx\" ON public.\"jansClnt\" USING btree (\"jansClntSecretExpAt\") jansClnt jansClnt_del_exp_idx CREATE INDEX \"jansClnt_del_exp_idx\" ON public.\"jansClnt\" USING btree (del, exp) jansClnt jansClnt_displayName_idx CREATE INDEX \"jansClnt_displayName_idx\" ON public.\"jansClnt\" USING btree (\"displayName\") jansClnt jansClnt_inum_idx CREATE INDEX \"jansClnt_inum_idx\" ON public.\"jansClnt\" USING btree (inum) jansClnt jansClnt_jansRegistrationAccessTkn_idx CREATE INDEX \"jansClnt_jansRegistrationAccessTkn_idx\" ON public.\"jansClnt\" USING btree (\"jansRegistrationAccessTkn\")", "title": "jansClnt"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansscope", "text": "tablename indexname indexdef jansScope jansScope_pkey CREATE UNIQUE INDEX \"jansScope_pkey\" ON public.\"jansScope\" USING btree (doc_id) jansScope jansScope_displayName_idx CREATE INDEX \"jansScope_displayName_idx\" ON public.\"jansScope\" USING btree (\"displayName\") jansScope jansScope_del_exp_idx CREATE INDEX \"jansScope_del_exp_idx\" ON public.\"jansScope\" USING btree (del, exp) jansScope jansScope_description_idx CREATE INDEX \"jansScope_description_idx\" ON public.\"jansScope\" USING btree (description) jansScope jansScope_jansId_idx CREATE INDEX \"jansScope_jansId_idx\" ON public.\"jansScope\" USING btree (\"jansId\")", "title": "jansScope"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansumaresource", "text": "tablename indexname indexdef jansUmaResource jansUmaResource_pkey CREATE UNIQUE INDEX \"jansUmaResource_pkey\" ON public.\"jansUmaResource\" USING btree (doc_id) jansUmaResource jansUmaResource_jansUmaScope_idx CREATE INDEX \"jansUmaResource_jansUmaScope_idx\" ON public.\"jansUmaResource\" USING btree (\"jansUmaScope\") jansUmaResource jansUmaResource_del_exp_idx CREATE INDEX \"jansUmaResource_del_exp_idx\" ON public.\"jansUmaResource\" USING btree (del, exp) jansUmaResource jansUmaResource_displayName_idx CREATE INDEX \"jansUmaResource_displayName_idx\" ON public.\"jansUmaResource\" USING btree (\"displayName\") jansUmaResource jansUmaResource_jansId_idx CREATE INDEX \"jansUmaResource_jansId_idx\" ON public.\"jansUmaResource\" USING btree (\"jansId\")", "title": "jansUmaResource"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansumaresourcepermission", "text": "tablename indexname indexdef jansUmaResourcePermission jansUmaResourcePermission_pkey CREATE UNIQUE INDEX \"jansUmaResourcePermission_pkey\" ON public.\"jansUmaResourcePermission\" USING btree (doc_id) jansUmaResourcePermission jansUmaResourcePermission_jansTicket_idx CREATE INDEX \"jansUmaResourcePermission_jansTicket_idx\" ON public.\"jansUmaResourcePermission\" USING btree (\"jansTicket\")", "title": "jansUmaResourcePermission"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansgrant", "text": "tablename indexname indexdef jansGrant jansGrant_pkey CREATE UNIQUE INDEX \"jansGrant_pkey\" ON public.\"jansGrant\" USING btree (doc_id)", "title": "jansGrant"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janstoken", "text": "tablename indexname indexdef jansToken jansToken_pkey CREATE UNIQUE INDEX \"jansToken_pkey\" ON public.\"jansToken\" USING btree (doc_id) jansToken jansToken_authzCode_idx CREATE INDEX \"jansToken_authzCode_idx\" ON public.\"jansToken\" USING btree (\"authzCode\") jansToken jansToken_grtId_idx CREATE INDEX \"jansToken_grtId_idx\" ON public.\"jansToken\" USING btree (\"grtId\") jansToken jansToken_ssnId_idx CREATE INDEX \"jansToken_ssnId_idx\" ON public.\"jansToken\" USING btree (\"ssnId\") jansToken jansToken_tknCde_idx CREATE INDEX \"jansToken_tknCde_idx\" ON public.\"jansToken\" USING btree (\"tknCde\") jansToken jansToken_del_exp_idx CREATE INDEX \"jansToken_del_exp_idx\" ON public.\"jansToken\" USING btree (del, exp)", "title": "jansToken"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansgrp", "text": "tablename indexname indexdef jansGrp jansGrp_pkey CREATE UNIQUE INDEX \"jansGrp_pkey\" ON public.\"jansGrp\" USING btree (doc_id) jansGrp jansGrp_description_idx CREATE INDEX \"jansGrp_description_idx\" ON public.\"jansGrp\" USING btree (description) jansGrp jansGrp_inum_idx CREATE INDEX \"jansGrp_inum_idx\" ON public.\"jansGrp\" USING btree (inum) jansGrp jansGrp_displayName_idx CREATE INDEX \"jansGrp_displayName_idx\" ON public.\"jansGrp\" USING btree (\"displayName\")", "title": "jansGrp"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansattr", "text": "tablename indexname indexdef jansAttr jansAttr_pkey CREATE UNIQUE INDEX \"jansAttr_pkey\" ON public.\"jansAttr\" USING btree (doc_id) jansAttr jansAttr_description_idx CREATE INDEX \"jansAttr_description_idx\" ON public.\"jansAttr\" USING btree (description) jansAttr jansAttr_jansAttrName_idx CREATE INDEX \"jansAttr_jansAttrName_idx\" ON public.\"jansAttr\" USING btree (\"jansAttrName\") jansAttr jansAttr_inum_idx CREATE INDEX \"jansAttr_inum_idx\" ON public.\"jansAttr\" USING btree (inum) jansAttr jansAttr_displayName_idx CREATE INDEX \"jansAttr_displayName_idx\" ON public.\"jansAttr\" USING btree (\"displayName\") jansAttr jansAttr_jansAttrOrigin_idx CREATE INDEX \"jansAttr_jansAttrOrigin_idx\" ON public.\"jansAttr\" USING btree (\"jansAttrOrigin\")", "title": "jansAttr"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janspassresetreq", "text": "tablename indexname indexdef jansPassResetReq jansPassResetReq_pkey CREATE UNIQUE INDEX \"jansPassResetReq_pkey\" ON public.\"jansPassResetReq\" USING btree (doc_id) jansPassResetReq jansPassResetReq_creationDate_idx CREATE INDEX \"jansPassResetReq_creationDate_idx\" ON public.\"jansPassResetReq\" USING btree (\"creationDate\")", "title": "jansPassResetReq"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janssessid", "text": "tablename indexname indexdef jansSessId jansSessId_pkey CREATE UNIQUE INDEX \"jansSessId_pkey\" ON public.\"jansSessId\" USING btree (doc_id) jansSessId jansSessId_sid_idx CREATE INDEX \"jansSessId_sid_idx\" ON public.\"jansSessId\" USING btree (sid) jansSessId jansSessId_deviceSecret_idx CREATE INDEX \"jansSessId_deviceSecret_idx\" ON public.\"jansSessId\" USING btree (\"deviceSecret\") jansSessId jansSessId_jansUsrDN_idx CREATE INDEX \"jansSessId_jansUsrDN_idx\" ON public.\"jansSessId\" USING btree (\"jansUsrDN\") jansSessId jansSessId_del_exp_idx CREATE INDEX \"jansSessId_del_exp_idx\" ON public.\"jansSessId\" USING btree (del, exp)", "title": "jansSessId"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansumarpt", "text": "tablename indexname indexdef jansUmaRPT jansUmaRPT_pkey CREATE UNIQUE INDEX \"jansUmaRPT_pkey\" ON public.\"jansUmaRPT\" USING btree (doc_id)", "title": "jansUmaRPT"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janspushapp", "text": "tablename indexname indexdef jansPushApp jansPushApp_pkey CREATE UNIQUE INDEX \"jansPushApp_pkey\" ON public.\"jansPushApp\" USING btree (doc_id)", "title": "jansPushApp"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansscr", "text": "tablename indexname indexdef jansScr jansScr_pkey CREATE UNIQUE INDEX \"jansScr_pkey\" ON public.\"jansScr\" USING btree (doc_id)", "title": "jansScr"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janscustomscr", "text": "tablename indexname indexdef jansCustomScr jansCustomScr_pkey CREATE UNIQUE INDEX \"jansCustomScr_pkey\" ON public.\"jansCustomScr\" USING btree (doc_id) jansCustomScr jansCustomScr_inum_idx CREATE INDEX \"jansCustomScr_inum_idx\" ON public.\"jansCustomScr\" USING btree (inum) jansCustomScr jansCustomScr_jansScrTyp_idx CREATE INDEX \"jansCustomScr_jansScrTyp_idx\" ON public.\"jansCustomScr\" USING btree (\"jansScrTyp\")", "title": "jansCustomScr"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansdeviceregistration", "text": "tablename indexname indexdef jansDeviceRegistration jansDeviceRegistration_pkey CREATE UNIQUE INDEX \"jansDeviceRegistration_pkey\" ON public.\"jansDeviceRegistration\" USING btree (doc_id) jansDeviceRegistration jansDeviceRegistration_jansDeviceKeyHandle_idx CREATE INDEX \"jansDeviceRegistration_jansDeviceKeyHandle_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansDeviceKeyHandle\") jansDeviceRegistration jansDeviceRegistration_jansApp_idx CREATE INDEX \"jansDeviceRegistration_jansApp_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansApp\") jansDeviceRegistration jansDeviceRegistration_personInum_idx CREATE INDEX \"jansDeviceRegistration_personInum_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"personInum\") jansDeviceRegistration jansDeviceRegistration_del_exp_idx CREATE INDEX \"jansDeviceRegistration_del_exp_idx\" ON public.\"jansDeviceRegistration\" USING btree (del, exp) jansDeviceRegistration jansDeviceRegistration_jansDeviceHashCode_idx CREATE INDEX \"jansDeviceRegistration_jansDeviceHashCode_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansDeviceHashCode\") jansDeviceRegistration jansDeviceRegistration_jansStatus_idx CREATE INDEX \"jansDeviceRegistration_jansStatus_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansStatus\") jansDeviceRegistration jansDeviceRegistration_creationDate_idx CREATE INDEX \"jansDeviceRegistration_creationDate_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"creationDate\")", "title": "jansDeviceRegistration"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansu2freq", "text": "tablename indexname indexdef jansU2fReq jansU2fReq_pkey CREATE UNIQUE INDEX \"jansU2fReq_pkey\" ON public.\"jansU2fReq\" USING btree (doc_id) jansU2fReq jansU2fReq_del_exp_idx CREATE INDEX \"jansU2fReq_del_exp_idx\" ON public.\"jansU2fReq\" USING btree (del, exp) jansU2fReq jansU2fReq_creationDate_idx CREATE INDEX \"jansU2fReq_creationDate_idx\" ON public.\"jansU2fReq\" USING btree (\"creationDate\")", "title": "jansU2fReq"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansmetric", "text": "tablename indexname indexdef jansMetric jansMetric_pkey CREATE UNIQUE INDEX \"jansMetric_pkey\" ON public.\"jansMetric\" USING btree (doc_id) jansMetric jansMetric_jansEndDate_idx CREATE INDEX \"jansMetric_jansEndDate_idx\" ON public.\"jansMetric\" USING btree (\"jansEndDate\") jansMetric jansMetric_jansMetricTyp_idx CREATE INDEX \"jansMetric_jansMetricTyp_idx\" ON public.\"jansMetric\" USING btree (\"jansMetricTyp\") jansMetric jansMetric_jansStartDate_idx CREATE INDEX \"jansMetric_jansStartDate_idx\" ON public.\"jansMetric\" USING btree (\"jansStartDate\") jansMetric jansMetric_jansAppTyp_idx CREATE INDEX \"jansMetric_jansAppTyp_idx\" ON public.\"jansMetric\" USING btree (\"jansAppTyp\") jansMetric jansMetric_del_exp_idx CREATE INDEX \"jansMetric_del_exp_idx\" ON public.\"jansMetric\" USING btree (del, exp)", "title": "jansMetric"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansumapct", "text": "tablename indexname indexdef jansUmaPCT jansUmaPCT_pkey CREATE UNIQUE INDEX \"jansUmaPCT_pkey\" ON public.\"jansUmaPCT\" USING btree (doc_id) jansUmaPCT jansUmaPCT_tknCde_idx CREATE INDEX \"jansUmaPCT_tknCde_idx\" ON public.\"jansUmaPCT\" USING btree (\"tknCde\") jansUmaPCT jansUmaPCT_del_exp_idx CREATE INDEX \"jansUmaPCT_del_exp_idx\" ON public.\"jansUmaPCT\" USING btree (del, exp)", "title": "jansUmaPCT"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janscache", "text": "tablename indexname indexdef jansCache jansCache_pkey CREATE UNIQUE INDEX \"jansCache_pkey\" ON public.\"jansCache\" USING btree (doc_id) jansCache jansCache_del_exp_idx CREATE INDEX \"jansCache_del_exp_idx\" ON public.\"jansCache\" USING btree (del, exp)", "title": "jansCache"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansfido2registrationentry", "text": "tablename indexname indexdef jansFido2RegistrationEntry jansFido2RegistrationEntry_pkey CREATE UNIQUE INDEX \"jansFido2RegistrationEntry_pkey\" ON public.\"jansFido2RegistrationEntry\" USING btree (doc_id) jansFido2RegistrationEntry jansFido2RegistrationEntry_jansApp_idx CREATE INDEX \"jansFido2RegistrationEntry_jansApp_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansApp\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansCodeChallengeHash_idx CREATE INDEX \"jansFido2RegistrationEntry_jansCodeChallengeHash_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansCodeChallengeHash\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansPublicKeyIdHash_idx CREATE INDEX \"jansFido2RegistrationEntry_jansPublicKeyIdHash_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansPublicKeyIdHash\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansStatus_idx CREATE INDEX \"jansFido2RegistrationEntry_jansStatus_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansStatus\") jansFido2RegistrationEntry jansFido2RegistrationEntry_creationDate_idx CREATE INDEX \"jansFido2RegistrationEntry_creationDate_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"creationDate\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansCodeChallenge_idx CREATE INDEX \"jansFido2RegistrationEntry_jansCodeChallenge_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansCodeChallenge\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansPublicKeyId_idx CREATE INDEX \"jansFido2RegistrationEntry_jansPublicKeyId_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansPublicKeyId\") jansFido2RegistrationEntry jansFido2RegistrationEntry_personInum_idx CREATE INDEX \"jansFido2RegistrationEntry_personInum_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"personInum\") jansFido2RegistrationEntry jansFido2RegistrationEntry_del_exp_idx CREATE INDEX \"jansFido2RegistrationEntry_del_exp_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (del, exp)", "title": "jansFido2RegistrationEntry"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janspushdevice", "text": "tablename indexname indexdef jansPushDevice jansPushDevice_pkey CREATE UNIQUE INDEX \"jansPushDevice_pkey\" ON public.\"jansPushDevice\" USING btree (doc_id)", "title": "jansPushDevice"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansclntauthz", "text": "tablename indexname indexdef jansClntAuthz jansClntAuthz_pkey CREATE UNIQUE INDEX \"jansClntAuthz_pkey\" ON public.\"jansClntAuthz\" USING btree (doc_id) jansClntAuthz jansClntAuthz_jsonb_path_query_array_idx CREATE INDEX \"jansClntAuthz_jsonb_path_query_array_idx\" ON public.\"jansClntAuthz\" USING gin (jsonb_path_query_array(\"jansClntId\", '$[*]'::jsonpath)) jansClntAuthz jansClntAuthz_del_exp_idx CREATE INDEX \"jansClntAuthz_del_exp_idx\" ON public.\"jansClntAuthz\" USING btree (del, exp) jansClntAuthz jansClntAuthz_jansUsrId_idx CREATE INDEX \"jansClntAuthz_jansUsrId_idx\" ON public.\"jansClntAuthz\" USING btree (\"jansUsrId\")", "title": "jansClntAuthz"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janssectoridentifier", "text": "tablename indexname indexdef jansSectorIdentifier jansSectorIdentifier_pkey CREATE UNIQUE INDEX \"jansSectorIdentifier_pkey\" ON public.\"jansSectorIdentifier\" USING btree (doc_id)", "title": "jansSectorIdentifier"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansfido2authnentry", "text": "tablename indexname indexdef jansFido2AuthnEntry jansFido2AuthnEntry_pkey CREATE UNIQUE INDEX \"jansFido2AuthnEntry_pkey\" ON public.\"jansFido2AuthnEntry\" USING btree (doc_id) jansFido2AuthnEntry jansFido2AuthnEntry_jansApp_idx CREATE INDEX \"jansFido2AuthnEntry_jansApp_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansApp\") jansFido2AuthnEntry jansFido2AuthnEntry_jansCodeChallengeHash_idx CREATE INDEX \"jansFido2AuthnEntry_jansCodeChallengeHash_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansCodeChallengeHash\") jansFido2AuthnEntry jansFido2AuthnEntry_jansStatus_idx CREATE INDEX \"jansFido2AuthnEntry_jansStatus_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansStatus\") jansFido2AuthnEntry jansFido2AuthnEntry_creationDate_idx CREATE INDEX \"jansFido2AuthnEntry_creationDate_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"creationDate\") jansFido2AuthnEntry jansFido2AuthnEntry_jansCodeChallenge_idx CREATE INDEX \"jansFido2AuthnEntry_jansCodeChallenge_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansCodeChallenge\") jansFido2AuthnEntry jansFido2AuthnEntry_personInum_idx CREATE INDEX \"jansFido2AuthnEntry_personInum_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"personInum\") jansFido2AuthnEntry jansFido2AuthnEntry_del_exp_idx CREATE INDEX \"jansFido2AuthnEntry_del_exp_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (del, exp)", "title": "jansFido2AuthnEntry"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansrp", "text": "tablename indexname indexdef jansRp jansRp_pkey CREATE UNIQUE INDEX \"jansRp_pkey\" ON public.\"jansRp\" USING btree (doc_id)", "title": "jansRp"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janscibareq", "text": "tablename indexname indexdef jansCibaReq jansCibaReq_pkey CREATE UNIQUE INDEX \"jansCibaReq_pkey\" ON public.\"jansCibaReq\" USING btree (doc_id) jansCibaReq jansCibaReq_jansStatus_exp_idx CREATE INDEX \"jansCibaReq_jansStatus_exp_idx\" ON public.\"jansCibaReq\" USING btree (\"jansStatus\", exp)", "title": "jansCibaReq"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansstatentry", "text": "tablename indexname indexdef jansStatEntry jansStatEntry_pkey CREATE UNIQUE INDEX \"jansStatEntry_pkey\" ON public.\"jansStatEntry\" USING btree (doc_id) jansStatEntry jansStatEntry_jansId_idx CREATE INDEX \"jansStatEntry_jansId_idx\" ON public.\"jansStatEntry\" USING btree (\"jansId\")", "title": "jansStatEntry"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janspar", "text": "tablename indexname indexdef jansPar jansPar_pkey CREATE UNIQUE INDEX \"jansPar_pkey\" ON public.\"jansPar\" USING btree (doc_id) jansPar jansPar_jansId_idx CREATE INDEX \"jansPar_jansId_idx\" ON public.\"jansPar\" USING btree (\"jansId\") jansPar jansPar_del_exp_idx CREATE INDEX \"jansPar_del_exp_idx\" ON public.\"jansPar\" USING btree (del, exp)", "title": "jansPar"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansinummap", "text": "tablename indexname indexdef jansInumMap jansInumMap_pkey CREATE UNIQUE INDEX \"jansInumMap_pkey\" ON public.\"jansInumMap\" USING btree (doc_id) jansInumMap jansInumMap_jansStatus_idx CREATE INDEX \"jansInumMap_jansStatus_idx\" ON public.\"jansInumMap\" USING btree (\"jansStatus\") jansInumMap jansInumMap_inum_idx CREATE INDEX \"jansInumMap_inum_idx\" ON public.\"jansInumMap\" USING btree (inum)", "title": "jansInumMap"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#agmflowrun", "text": "tablename indexname indexdef agmFlowRun agmFlowRun_pkey CREATE UNIQUE INDEX \"agmFlowRun_pkey\" ON public.\"agmFlowRun\" USING btree (doc_id)", "title": "agmFlowRun"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#agmflow", "text": "tablename indexname indexdef agmFlow agmFlow_pkey CREATE UNIQUE INDEX \"agmFlow_pkey\" ON public.\"agmFlow\" USING btree (doc_id)", "title": "agmFlow"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#adsprjdeployment", "text": "tablename indexname indexdef adsPrjDeployment adsPrjDeployment_pkey CREATE UNIQUE INDEX \"adsPrjDeployment_pkey\" ON public.\"adsPrjDeployment\" USING btree (doc_id)", "title": "adsPrjDeployment"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansdocument", "text": "tablename indexname indexdef jansDocument jansDocument_pkey CREATE UNIQUE INDEX \"jansDocument_pkey\" ON public.\"jansDocument\" USING btree (doc_id)", "title": "jansDocument"}, {"location": "janssen-server/reference/database/pgsql-schema/", "tags": ["administration", "database", "PostgreSQL", "Indexes"], "text": "PostgreSQL Schema # Tables # Table names jansPairwiseIdentifier jansPerson jansOrganization jansSsa jansAppConf jansClnt jansScope jansUmaResource jansUmaResourcePermission jansGrant jansToken jansGrp jansAttr jansPassResetReq jansSessId jansUmaRPT jansPushApp jansScr jansCustomScr jansDeviceRegistration jansU2fReq jansMetric jansUmaPCT jansCache jansFido2RegistrationEntry jansPushDevice jansClntAuthz jansSectorIdentifier jansFido2AuthnEntry jansRp jansCibaReq jansStatEntry jansPar jansInumMap agmFlowRun agmFlow adsPrjDeployment jansDocument jansPairwiseIdentifier # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansSectorIdentifier character varying 64 YES None jans Sector Identifier jansClntId jsonb None YES None jans Clnt id jansUsrId character varying 64 YES None jans user id jansPerson # Field Type Character Maximum Length Null Default Comment jansAssociatedClnt jsonb None YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansManagedOrganizations character varying 64 YES None Used to track with which organizations a person is associated jansOptOuts jsonb None YES None White pages attributes restricted by person in exclude profile management jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansPersistentJWT jsonb None YES None jans Persistent JWT jansCreationTimestamp timestamp without time zone None YES None Registration time jansOTPCache jsonb None YES None Stores a used OTP to prevent a hacker from using it again. Complementary to jansExtUid attribute jansLastLogonTime timestamp without time zone None YES None Last logon time jansPassExpDate timestamp without time zone None YES None Pass Exp date, represented as an ISO 8601 (YYYY-MM-DD) format persistentId character varying 64 YES None PersistentId middleName character varying 64 YES None Middle name(s) nickname character varying 64 YES None Casual name of the End-Usr jansPrefUsrName character varying 64 YES None Shorthand Name profile character varying 64 YES None Profile page URL of the person picture text None YES None Profile picture URL of the person website character varying 64 YES None Web page or blog URL of the person emailVerified boolean None YES None True if the e-mail address of the person has been verified; otherwise false gender character varying 32 YES None Gender of the person either female or male birthdate timestamp without time zone None YES None Birthday of the person, represented as an ISO 8601:2004 [ISO8601-2004] YYYY-MM-DD format zoneinfo character varying 64 YES None Time zone database representing the End-Usrs time zone. For example, Europe/Paris or America/Los_Angeles locale character varying 64 YES None Locale of the person, represented as a BCP47 [RFC5646] language tag phoneNumberVerified boolean None YES None True if the phone number of the person has been verified, otherwise false address text None YES None OpenID Connect formatted JSON object representing the address of the person updatedAt timestamp without time zone None YES None Time the information of the person was last updated. Seconds from 1970-01-01T0:0:0Z preferredLanguage character varying 64 YES None preferred written or spoken language for a person role jsonb None YES None Role secretAnswer text None YES None Secret Answer secretQuestion text None YES None Secret Question transientId character varying 64 YES None TransientId jansCountInvalidLogin character varying 64 YES None Invalid login attempts count jansEnrollmentCode character varying 64 YES None jansEnrollmentCode jansIMAPData character varying 64 YES None This data has information about your imap connection jansPPID jsonb None YES None Persistent Pairwise ID for OpenID Connect jansGuid character varying 64 YES None A random string to mark temporary tokens jansPreferredMethod character varying 64 YES None Casa - Preferred method to use for user authentication jansOTPDevices character varying 512 YES None Casa - Json representation of OTP devices. Complementary to jansExtUid attribute jansMobileDevices character varying 512 YES None Casa - Json representation of mobile devices. Complementary to mobile attribute jansTrustedDevices text None YES None Casa - Devices with which strong authentication may be skipped jansStrongAuthPolicy character varying 64 YES None Casa - 2FA Enforcement Policy for User jansUnlinkedExternalUids character varying 64 YES None Casa - List of unlinked social accounts (ie disabled jansExtUids) jansBackchannelDeviceRegistrationTkn character varying 64 YES None jans Backchannel Device Registration Tkn jansBackchannelUsrCode character varying 64 YES None jans Backchannel Usr Code carLicense character varying 64 YES None vehicle license or registration plate departmentNumber character varying 64 YES None identifies a department within an organization employeeType character varying 64 YES None type of employment for a person employeeNumber character varying 64 YES None numerically identifies an employee within an organization jansAdminUIRole jsonb None YES None jansAdminUIRole jansOrganization # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansCustomMessage character varying 128 YES None exclude custom welcome message jansFaviconImage character varying 64 YES None TODO - Stores URL of favicon jansLogoImage character varying 64 YES None Logo used by exclude for default look and feel. jansManager character varying 64 YES None Used to specify if a person has the manager role jansManagerGrp text None YES None Used in organizatoin entry to specifies the dn of the group that has admin priviledges in exclude. jansOrgShortName character varying 64 YES None Short description, as few letters as possible, no spaces. jansThemeColor character varying 64 YES None exclude login page configuration inum character varying 64 YES None XRI i-number jansCreationTimestamp timestamp without time zone None YES None Registration time jansRegistrationConf character varying 64 YES None Registration Conf jansLogoPath character varying 64 YES None jansLogoPath jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansFaviconPath character varying 64 YES None jansFaviconPath jansSsa # Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansState character varying 64 YES None jansState creatorId character varying 64 YES None Creator Id creatorTyp character varying 64 YES None Creator type creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansAppConf # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansHostname character varying 64 YES None The hostname of the Jans Server instance jansLastUpd timestamp without time zone None YES None Monitors last time the server was able to connect to the monitoring system. jansManager character varying 64 YES None Used to specify if a person has the manager role jansOrgProfileMgt boolean None YES None enable or disable profile management feature in exclude jansScimEnabled boolean None YES None exclude SCIM feature - enabled or disabled jansSmtpConf jsonb None YES None SMTP configuration jansSslExpiry character varying 64 YES None SAML Trust Relationship configuration jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansUrl character varying 64 YES None Jans instance URL inum character varying 64 YES None XRI i-number jansDbAuth jsonb None YES None Custom IDP authentication configuration jansLogViewerConfig character varying 64 YES None Log viewer configuration jansLogConfigLocation character varying 64 YES None Path to external log4j2.xml jansCacheConf text None YES None Cache configuration jansDocStoreConf text None YES None jansDocStoreConf jansConfDyn text None YES None jans Dyn Conf jansConfErrors text None YES None jans Errors Conf jansConfStatic text None YES None jans Static Conf jansConfWebKeys text None YES None jans Web Keys Conf jansWebKeysSettings character varying 64 YES None jans Web Keys Conf jansConfApp text None YES None jans App Conf jansRevision integer None YES None Revision jansClnt # Field Type Character Maximum Length Null Default Comment jansGrp character varying 64 YES None Group displayName character varying 128 YES None preferred name of a person to be used when displaying entries displayNameLocalized jsonb None YES None jans Display Name Localized inum character varying 64 YES None XRI i-number jansAppTyp character varying 64 YES None jans App Typ jansClntIdIssuedAt timestamp without time zone None YES None jans Clnt Issued At jansClntSecret character varying 64 YES None jans Clnt Secret jansClntSecretExpAt timestamp without time zone None YES None Date client expires exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansClntURI text None YES None jans Clnt URI jansClntURILocalized jsonb None YES None jans Clnt URI localized jansContact jsonb None YES None jans Contact jansDefAcrValues jsonb None YES None jans Def Acr Values jansDefMaxAge integer None YES None jans Def Max Age jansGrantTyp jsonb None YES None jans Grant Typ jansIdTknEncRespAlg character varying 64 YES None jans ID Tkn Enc Resp Alg jansIdTknEncRespEnc character varying 64 YES None jans ID Tkn Enc Resp Enc jansIdTknSignedRespAlg character varying 64 YES None jans ID Tkn Signed Resp Alg jansInitiateLoginURI text None YES None jans Initiate Login URI jansJwksURI text None YES None jans JWKs URI jansJwks text None YES None jans JWKs jansLogoURI text None YES None jans Logo URI jansLogoURILocalized jsonb None YES None jans Logo URI localized jansPolicyURI text None YES None jans Policy URI jansPolicyURILocalized jsonb None YES None jans Policy URI localized jansPostLogoutRedirectURI jsonb None YES None jans Post Logout Redirect URI jansRedirectURI jsonb None YES None jans Redirect URI jansRegistrationAccessTkn character varying 64 YES None jans Registration Access Tkn jansReqObjSigAlg character varying 64 YES None jans Req Obj Sig Alg jansReqObjEncAlg character varying 64 YES None jans Req Obj Enc Alg jansReqObjEncEnc character varying 64 YES None jans Req Obj Enc Enc jansReqURI jsonb None YES None jans Req URI jansRespTyp jsonb None YES None jans Resp Typ jansScope jsonb None YES None jans Attr Scope jansClaim jsonb None YES None jans Attr Claim jansSectorIdentifierURI text None YES None jans Sector Identifier URI jansSignedRespAlg character varying 64 YES None jans Signed Resp Alg jansSubjectTyp character varying 64 YES None jans Subject Typ jansTknEndpointAuthMethod character varying 64 YES None jans Tkn Endpoint Auth Method jansTknEndpointAuthSigAlg character varying 64 YES None jans Tkn Endpoint Auth Sig Alg jansTosURI text None YES None jans TOS URI jansTosURILocalized jsonb None YES None jans Tos URI localized jansTrustedClnt boolean None YES None jans Trusted Clnt jansUsrInfEncRespAlg character varying 64 YES None jans Usr Inf Enc Resp Alg jansUsrInfEncRespEnc character varying 64 YES None jans Usr Inf Enc Resp Enc jansExtraConf character varying 64 YES None jans additional configuration jansClaimRedirectURI jsonb None YES None Claim Redirect URI jansLastAccessTime timestamp without time zone None YES None Last access time jansLastLogonTime timestamp without time zone None YES None Last logon time jansPersistClntAuthzs boolean None YES None jans Persist Clnt Authzs jansInclClaimsInIdTkn boolean None YES None jans Incl Claims In Id Tkn jansRefreshTknLife integer None YES None Life of refresh token jansDisabled boolean None YES None Status of client jansLogoutURI jsonb None YES None jans Policy URI jansLogoutSessRequired boolean None YES None jans Policy URI jansdId character varying 64 YES None jansd Id jansAuthorizedOrigins jsonb None YES None jans Authorized Origins tknBndCnf text None YES None jansauth - Tkn Binding Id Hash jansAccessTknAsJwt boolean None YES None jansauth - indicator whether to return access token as JWT jansAccessTknSigAlg character varying 64 YES None jansauth - access token signing algorithm jansAccessTknLife integer None YES None Life of access token jansSoftId character varying 64 YES None Soft Identifier jansSoftStatement text None YES None Soft Statement jansRptAsJwt boolean None YES None jansRptAsJwt jansAttrs text None YES None Attrs jansBackchannelTknDeliveryMode character varying 64 YES None jans Backchannel Tkn Delivery Mode jansBackchannelClntNotificationEndpoint character varying 64 YES None jans Backchannel Clnt Notification Endpoint jansBackchannelAuthnReqSigAlg character varying 64 YES None jans Backchannel Authn Req Sig Alg jansBackchannelUsrCodeParameter boolean None YES None jans Backchannel Usr Code Parameter jansScope # Field Type Character Maximum Length Null Default Comment jansDefScope boolean None YES None Track the default scope for an custom OAuth2 Scope. displayName character varying 128 YES None preferred name of a person to be used when displaying entries inum character varying 64 YES None XRI i-number jansScopeTyp character varying 64 YES None OX Attr Scope type creatorId character varying 64 YES None Creator Id creatorTyp character varying 64 YES None Creator type creatorAttrs character varying 64 YES None Creator Attrs creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansClaim jsonb None YES None jans Attr Claim jansScrDn jsonb None YES None Script object DN jansGrpClaims boolean None YES None jans Grp Attr Claims (true or false) jansId character varying 128 YES None Identifier jansIconUrl character varying 64 YES None jans icon url jansUmaPolicyScrDn text None YES None OX policy script Dn jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansUmaResource # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries inum character varying 64 YES None XRI i-number jansAssociatedClnt jsonb None YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. jansUmaScope character varying 768 YES None URI reference of scope descriptor jansFaviconImage character varying 64 YES None TODO - Stores URL of favicon jansGrp character varying 64 YES None Group jansId character varying 128 YES None Identifier jansResource text None YES None Host path jansRevision integer None YES None Revision jansTyp character varying 64 YES None jans type jansScopeExpression text None YES None Scope expression iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansUmaResourcePermission # Field Type Character Maximum Length Null Default Comment exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansUmaScope character varying 768 YES None URI reference of scope descriptor jansConfCode character varying 64 YES None jans configuration code jansResourceSetId character varying 64 YES None jans resource set id jansAttrs text None YES None Attrs jansTicket character varying 64 YES None jans ticket jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansGrant # Field Type Character Maximum Length Null Default Comment grtId character varying 64 YES None jans grant id iat timestamp without time zone None YES None jans Creation jansToken # Field Type Character Maximum Length Null Default Comment authnTime timestamp without time zone None YES None jans Authn Time authzCode character varying 64 YES None jans authorization code iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknCde character varying 80 YES None jans Tkn Code tknTyp character varying 32 YES None jans Tkn Typ usrId character varying 64 YES None jans user id jansUsrDN character varying 128 YES None jans Usr DN clnId character varying 64 YES None jans Clnt id uuid character varying 64 YES None Unique identifier chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims ssnId character varying 64 YES None jans Sess DN attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash dpop character varying 64 YES None DPoP Proof jansGrp # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansAttr # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansAttrEditTyp jsonb None YES None Specify in exclude who can update an attribute, admin or user jansAttrName character varying 64 YES None Specify an identifier for an attribute. May be multi-value where an attribute has two names, like givenName and first-name. jansAttrOrigin character varying 64 YES None Specify the person objectclass associated with the attribute, used for display purposes in exclude. jansAttrSystemEditTyp character varying 64 YES None TODO - still required? jansAttrTyp character varying 64 YES None Data type of attribute. Values can be string, photo, numeric, date jansClaimName character varying 64 YES None Used by jans in conjunction with jansttributeName to map claims to attributes in LDAP. jansAttrUsgTyp character varying 64 YES None TODO - Usg? Value can be OpenID jansAttrViewTyp jsonb None YES None Specify in exclude who can view an attribute, admin or user jansSAML1URI character varying 64 YES None SAML 1 uri of attribute jansSAML2URI character varying 64 YES None SAML 2 uri of attribute jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansNameIdTyp character varying 64 YES None NameId Typ jansSourceAttr character varying 64 YES None Source Attr for this Attr jansRegExp character varying 64 YES None Regular expression used to validate attribute data jansTooltip character varying 64 YES None Custom tooltip to be shown on the UI jansValidation text None YES None This data has information about attribute Validation jansPassResetReq # Field Type Character Maximum Length Null Default Comment creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansGuid character varying 64 YES None A random string to mark temporary tokens personInum character varying 64 YES None Inum of a person jansSessId # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier sid character varying 64 YES None Sess Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansLastAccessTime timestamp without time zone None YES None Last access time jansUsrDN character varying 128 YES None jans Usr DN authnTime timestamp without time zone None YES None jans Authn Time jansState character varying 64 YES None jansState jansSessState text None YES None jans Sess State jansPermissionGranted boolean None YES None jans Permission Granted jansAsJwt boolean None YES None Boolean field to indicate whether object is used as JWT jansJwt text None YES None JWT representation of the object or otherwise jwt associated with the object jansPermissionGrantedMap text None YES None jans Permission Granted Map jansInvolvedClnts text None YES None Involved clients deviceSecret character varying 64 YES None deviceSecret jansSessAttr text None YES None jansSessAttr jansUmaRPT # Field Type Character Maximum Length Null Default Comment authnTime timestamp without time zone None YES None jans Authn Time clnId character varying 64 YES None jans Clnt id iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del tknCde character varying 80 YES None jans Tkn Code usrId character varying 64 YES None jans user id ssnId character varying 64 YES None jans Sess DN jansUmaPermission jsonb None YES None jans uma permission uuid character varying 64 YES None Unique identifier dpop character varying 64 YES None DPoP Proof authzCode character varying 64 YES None jans authorization code grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknTyp character varying 32 YES None jans Tkn Typ jansUsrDN character varying 128 YES None jans Usr DN chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash jansPushApp # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansId character varying 128 YES None Identifier jansName character varying 64 YES None Name jansPushAppConf character varying 64 YES None jansPush application configuration jansScr # Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number jansScr text None YES None Attr that contains script (python, java script) jansScrTyp character varying 64 YES None Attr that contains script type (e.g. python, java script) jansCustomScr # Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansScr text None YES None Attr that contains script (python, java script) jansScrTyp character varying 64 YES None Attr that contains script type (e.g. python, java script) jansProgLng character varying 64 YES None programming language jansModuleProperty jsonb None YES None Module property jansConfProperty jsonb None YES None Conf property jansLevel integer None YES None Level jansRevision integer None YES None Revision jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansScrError text None YES None Attr that contains first error which application get during it execution jansAlias jsonb None YES None jansAlias jansDeviceRegistration # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansDeviceKeyHandle character varying 128 YES None jansDeviceKeyHandle jansDeviceHashCode integer None YES None jansDeviceHashCode jansApp character varying 96 YES None jansApp jansDeviceRegistrationConf text None YES None jansDeviceRegistrationConf jansDeviceNotificationConf character varying 64 YES None Extended push notification configuration jansNickName character varying 64 YES None jansNickName jansDeviceData text None YES None jansDeviceData jansCounter integer None YES None jansCounter jansStatus character varying 16 YES None Status of the entry, used by many objectclasses del boolean None YES None del exp timestamp without time zone None YES None jans Exp personInum character varying 64 YES None Inum of a person creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansLastAccessTime timestamp without time zone None YES None Last access time jansU2fReq # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansReqId character varying 64 YES None jansReqId jansReq text None YES None jansReq jansSessStateId character varying 64 YES None jansSessStateId del boolean None YES None del exp timestamp without time zone None YES None jans Exp personInum character varying 64 YES None Inum of a person creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansMetric # Field Type Character Maximum Length Null Default Comment jansStartDate timestamp without time zone None YES None Start date jansEndDate timestamp without time zone None YES None End date jansAppTyp character varying 64 YES None jans App Typ jansMetricTyp character varying 64 YES None Metric type creationDate timestamp without time zone None YES None Creation Date used for password reset requests del boolean None YES None del exp timestamp without time zone None YES None jans Exp jansData text None YES None OX data jansHost character varying 64 YES None jans host jansUmaPCT # Field Type Character Maximum Length Null Default Comment clnId character varying 64 YES None jans Clnt id iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del tknCde character varying 80 YES None jans Tkn Code ssnId character varying 64 YES None jans Sess DN jansClaimValues character varying 64 YES None Claim Values dpop character varying 64 YES None DPoP Proof authnTime timestamp without time zone None YES None jans Authn Time authzCode character varying 64 YES None jans authorization code grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknTyp character varying 32 YES None jans Tkn Typ usrId character varying 64 YES None jans user id jansUsrDN character varying 128 YES None jans Usr DN uuid character varying 64 YES None Unique identifier chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash jansCache # Field Type Character Maximum Length Null Default Comment uuid character varying 64 YES None Unique identifier iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del dat text None YES None OX data jansFido2RegistrationEntry # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansApp character varying 96 YES None jansApp jansSessStateId character varying 64 YES None jansSessStateId jansCodeChallenge character varying 64 YES None OX PKCE code challenge jansCodeChallengeHash integer None YES None OX code challenge hash jansPublicKeyId character varying 96 YES None jansPublicKeyId jansPublicKeyIdHash integer None YES None jansPublicKeyIdHash personInum character varying 64 YES None Inum of a person jansRegistrationData text None YES None jansRegistrationData jansDeviceData text None YES None jansDeviceData jansDeviceNotificationConf character varying 64 YES None Extended push notification configuration jansCounter integer None YES None jansCounter jansStatus character varying 16 YES None Status of the entry, used by many objectclasses exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansPushDevice # Field Type Character Maximum Length Null Default Comment jansUsrId character varying 64 YES None jans user id jansId character varying 128 YES None Identifier jansPushApp text None YES None jansPush application DN jansPushDeviceConf character varying 64 YES None jansPush device configuration jansTyp character varying 64 YES None jans type jansClntAuthz # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansClntId jsonb None YES None jans Clnt id jansUsrId character varying 64 YES None jans user id exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansScope jsonb None YES None jans Attr Scope jansSectorIdentifier # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansRedirectURI jsonb None YES None jans Redirect URI jansClntId jsonb None YES None jans Clnt id jansFido2AuthnEntry # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansApp character varying 96 YES None jansApp jansSessStateId character varying 64 YES None jansSessStateId jansCodeChallenge character varying 64 YES None OX PKCE code challenge jansCodeChallengeHash integer None YES None OX code challenge hash personInum character varying 64 YES None Inum of a person jansAuthData text None YES None jansAuthData jansStatus character varying 16 YES None Status of the entry, used by many objectclasses exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansRp # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier dat text None YES None OX data jansCibaReq # Field Type Character Maximum Length Null Default Comment authReqId character varying 64 YES None Authn request id clnId character varying 64 YES None jans Clnt id usrId character varying 64 YES None jans user id creationDate timestamp without time zone None YES None Creation Date used for password reset requests exp timestamp without time zone None YES None jans Exp jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansStatEntry # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier dat text None YES None OX data jansData text None YES None OX data attr text None YES None Attrs jansPar # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansInumMap # Field Type Character Maximum Length Null Default Comment jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansPrimaryKeyAttrName character varying 64 YES None Primary Key Attribute Name jansPrimaryKeyValue character varying 64 YES None Primary Key Value jansSecondaryKeyAttrName character varying 64 YES None Secondary Key Attribute Name jansSecondaryKeyValue character varying 64 YES None Secondary Key Value jansTertiaryKeyAttrName character varying 64 YES None Tertiary Key Attribute Name jansTertiaryKeyValue character varying 64 YES None Tertiary Key Value agmFlowRun # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier agFlowSt text None YES None Details of a running agama flow instance agFlowEncCont text None YES None Continuation associated to a running agama flow instance jansCustomMessage character varying 128 YES None exclude custom welcome message exp timestamp without time zone None YES None jans Exp agmFlow # Field Type Character Maximum Length Null Default Comment agFlowQname character varying 64 YES None Full name of an agama flow agFlowMeta text None YES None Metadata of an agama flow jansScr text None YES None Attr that contains script (python, java script) jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansScrError text None YES None Attr that contains first error which application get during it execution agFlowTrans text None YES None Transpiled code of an agama flow jansRevision integer None YES None Revision jansCustomMessage character varying 128 YES None exclude custom welcome message adsPrjDeployment # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansStartDate timestamp without time zone None YES None Start date jansEndDate timestamp without time zone None YES None End date adsPrjAssets text None YES None Assets of an ADS project adsPrjDeplDetails text None YES None Misc details associated to an ADS project jansDocument # Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number displayName character varying 128 YES None preferred name of a person to be used when displaying entries document character varying 64 YES None Save Document in DB creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansModuleProperty jsonb None YES None Module property jansLevel integer None YES None Level jansRevision integer None YES None Revision jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansAlias jsonb None YES None jansAlias", "title": "PostgreSQL Schema"}, {"location": "janssen-server/reference/database/pgsql-schema/#postgresql-schema", "text": "", "title": "PostgreSQL Schema"}, {"location": "janssen-server/reference/database/pgsql-schema/#tables", "text": "Table names jansPairwiseIdentifier jansPerson jansOrganization jansSsa jansAppConf jansClnt jansScope jansUmaResource jansUmaResourcePermission jansGrant jansToken jansGrp jansAttr jansPassResetReq jansSessId jansUmaRPT jansPushApp jansScr jansCustomScr jansDeviceRegistration jansU2fReq jansMetric jansUmaPCT jansCache jansFido2RegistrationEntry jansPushDevice jansClntAuthz jansSectorIdentifier jansFido2AuthnEntry jansRp jansCibaReq jansStatEntry jansPar jansInumMap agmFlowRun agmFlow adsPrjDeployment jansDocument", "title": "Tables"}, {"location": "janssen-server/reference/database/pgsql-schema/#janspairwiseidentifier", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansSectorIdentifier character varying 64 YES None jans Sector Identifier jansClntId jsonb None YES None jans Clnt id jansUsrId character varying 64 YES None jans user id", "title": "jansPairwiseIdentifier"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansperson", "text": "Field Type Character Maximum Length Null Default Comment jansAssociatedClnt jsonb None YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansManagedOrganizations character varying 64 YES None Used to track with which organizations a person is associated jansOptOuts jsonb None YES None White pages attributes restricted by person in exclude profile management jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansPersistentJWT jsonb None YES None jans Persistent JWT jansCreationTimestamp timestamp without time zone None YES None Registration time jansOTPCache jsonb None YES None Stores a used OTP to prevent a hacker from using it again. Complementary to jansExtUid attribute jansLastLogonTime timestamp without time zone None YES None Last logon time jansPassExpDate timestamp without time zone None YES None Pass Exp date, represented as an ISO 8601 (YYYY-MM-DD) format persistentId character varying 64 YES None PersistentId middleName character varying 64 YES None Middle name(s) nickname character varying 64 YES None Casual name of the End-Usr jansPrefUsrName character varying 64 YES None Shorthand Name profile character varying 64 YES None Profile page URL of the person picture text None YES None Profile picture URL of the person website character varying 64 YES None Web page or blog URL of the person emailVerified boolean None YES None True if the e-mail address of the person has been verified; otherwise false gender character varying 32 YES None Gender of the person either female or male birthdate timestamp without time zone None YES None Birthday of the person, represented as an ISO 8601:2004 [ISO8601-2004] YYYY-MM-DD format zoneinfo character varying 64 YES None Time zone database representing the End-Usrs time zone. For example, Europe/Paris or America/Los_Angeles locale character varying 64 YES None Locale of the person, represented as a BCP47 [RFC5646] language tag phoneNumberVerified boolean None YES None True if the phone number of the person has been verified, otherwise false address text None YES None OpenID Connect formatted JSON object representing the address of the person updatedAt timestamp without time zone None YES None Time the information of the person was last updated. Seconds from 1970-01-01T0:0:0Z preferredLanguage character varying 64 YES None preferred written or spoken language for a person role jsonb None YES None Role secretAnswer text None YES None Secret Answer secretQuestion text None YES None Secret Question transientId character varying 64 YES None TransientId jansCountInvalidLogin character varying 64 YES None Invalid login attempts count jansEnrollmentCode character varying 64 YES None jansEnrollmentCode jansIMAPData character varying 64 YES None This data has information about your imap connection jansPPID jsonb None YES None Persistent Pairwise ID for OpenID Connect jansGuid character varying 64 YES None A random string to mark temporary tokens jansPreferredMethod character varying 64 YES None Casa - Preferred method to use for user authentication jansOTPDevices character varying 512 YES None Casa - Json representation of OTP devices. Complementary to jansExtUid attribute jansMobileDevices character varying 512 YES None Casa - Json representation of mobile devices. Complementary to mobile attribute jansTrustedDevices text None YES None Casa - Devices with which strong authentication may be skipped jansStrongAuthPolicy character varying 64 YES None Casa - 2FA Enforcement Policy for User jansUnlinkedExternalUids character varying 64 YES None Casa - List of unlinked social accounts (ie disabled jansExtUids) jansBackchannelDeviceRegistrationTkn character varying 64 YES None jans Backchannel Device Registration Tkn jansBackchannelUsrCode character varying 64 YES None jans Backchannel Usr Code carLicense character varying 64 YES None vehicle license or registration plate departmentNumber character varying 64 YES None identifies a department within an organization employeeType character varying 64 YES None type of employment for a person employeeNumber character varying 64 YES None numerically identifies an employee within an organization jansAdminUIRole jsonb None YES None jansAdminUIRole", "title": "jansPerson"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansorganization", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansCustomMessage character varying 128 YES None exclude custom welcome message jansFaviconImage character varying 64 YES None TODO - Stores URL of favicon jansLogoImage character varying 64 YES None Logo used by exclude for default look and feel. jansManager character varying 64 YES None Used to specify if a person has the manager role jansManagerGrp text None YES None Used in organizatoin entry to specifies the dn of the group that has admin priviledges in exclude. jansOrgShortName character varying 64 YES None Short description, as few letters as possible, no spaces. jansThemeColor character varying 64 YES None exclude login page configuration inum character varying 64 YES None XRI i-number jansCreationTimestamp timestamp without time zone None YES None Registration time jansRegistrationConf character varying 64 YES None Registration Conf jansLogoPath character varying 64 YES None jansLogoPath jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansFaviconPath character varying 64 YES None jansFaviconPath", "title": "jansOrganization"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansssa", "text": "Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansState character varying 64 YES None jansState creatorId character varying 64 YES None Creator Id creatorTyp character varying 64 YES None Creator type creationDate timestamp without time zone None YES None Creation Date used for password reset requests", "title": "jansSsa"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansappconf", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansHostname character varying 64 YES None The hostname of the Jans Server instance jansLastUpd timestamp without time zone None YES None Monitors last time the server was able to connect to the monitoring system. jansManager character varying 64 YES None Used to specify if a person has the manager role jansOrgProfileMgt boolean None YES None enable or disable profile management feature in exclude jansScimEnabled boolean None YES None exclude SCIM feature - enabled or disabled jansSmtpConf jsonb None YES None SMTP configuration jansSslExpiry character varying 64 YES None SAML Trust Relationship configuration jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansUrl character varying 64 YES None Jans instance URL inum character varying 64 YES None XRI i-number jansDbAuth jsonb None YES None Custom IDP authentication configuration jansLogViewerConfig character varying 64 YES None Log viewer configuration jansLogConfigLocation character varying 64 YES None Path to external log4j2.xml jansCacheConf text None YES None Cache configuration jansDocStoreConf text None YES None jansDocStoreConf jansConfDyn text None YES None jans Dyn Conf jansConfErrors text None YES None jans Errors Conf jansConfStatic text None YES None jans Static Conf jansConfWebKeys text None YES None jans Web Keys Conf jansWebKeysSettings character varying 64 YES None jans Web Keys Conf jansConfApp text None YES None jans App Conf jansRevision integer None YES None Revision", "title": "jansAppConf"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansclnt", "text": "Field Type Character Maximum Length Null Default Comment jansGrp character varying 64 YES None Group displayName character varying 128 YES None preferred name of a person to be used when displaying entries displayNameLocalized jsonb None YES None jans Display Name Localized inum character varying 64 YES None XRI i-number jansAppTyp character varying 64 YES None jans App Typ jansClntIdIssuedAt timestamp without time zone None YES None jans Clnt Issued At jansClntSecret character varying 64 YES None jans Clnt Secret jansClntSecretExpAt timestamp without time zone None YES None Date client expires exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansClntURI text None YES None jans Clnt URI jansClntURILocalized jsonb None YES None jans Clnt URI localized jansContact jsonb None YES None jans Contact jansDefAcrValues jsonb None YES None jans Def Acr Values jansDefMaxAge integer None YES None jans Def Max Age jansGrantTyp jsonb None YES None jans Grant Typ jansIdTknEncRespAlg character varying 64 YES None jans ID Tkn Enc Resp Alg jansIdTknEncRespEnc character varying 64 YES None jans ID Tkn Enc Resp Enc jansIdTknSignedRespAlg character varying 64 YES None jans ID Tkn Signed Resp Alg jansInitiateLoginURI text None YES None jans Initiate Login URI jansJwksURI text None YES None jans JWKs URI jansJwks text None YES None jans JWKs jansLogoURI text None YES None jans Logo URI jansLogoURILocalized jsonb None YES None jans Logo URI localized jansPolicyURI text None YES None jans Policy URI jansPolicyURILocalized jsonb None YES None jans Policy URI localized jansPostLogoutRedirectURI jsonb None YES None jans Post Logout Redirect URI jansRedirectURI jsonb None YES None jans Redirect URI jansRegistrationAccessTkn character varying 64 YES None jans Registration Access Tkn jansReqObjSigAlg character varying 64 YES None jans Req Obj Sig Alg jansReqObjEncAlg character varying 64 YES None jans Req Obj Enc Alg jansReqObjEncEnc character varying 64 YES None jans Req Obj Enc Enc jansReqURI jsonb None YES None jans Req URI jansRespTyp jsonb None YES None jans Resp Typ jansScope jsonb None YES None jans Attr Scope jansClaim jsonb None YES None jans Attr Claim jansSectorIdentifierURI text None YES None jans Sector Identifier URI jansSignedRespAlg character varying 64 YES None jans Signed Resp Alg jansSubjectTyp character varying 64 YES None jans Subject Typ jansTknEndpointAuthMethod character varying 64 YES None jans Tkn Endpoint Auth Method jansTknEndpointAuthSigAlg character varying 64 YES None jans Tkn Endpoint Auth Sig Alg jansTosURI text None YES None jans TOS URI jansTosURILocalized jsonb None YES None jans Tos URI localized jansTrustedClnt boolean None YES None jans Trusted Clnt jansUsrInfEncRespAlg character varying 64 YES None jans Usr Inf Enc Resp Alg jansUsrInfEncRespEnc character varying 64 YES None jans Usr Inf Enc Resp Enc jansExtraConf character varying 64 YES None jans additional configuration jansClaimRedirectURI jsonb None YES None Claim Redirect URI jansLastAccessTime timestamp without time zone None YES None Last access time jansLastLogonTime timestamp without time zone None YES None Last logon time jansPersistClntAuthzs boolean None YES None jans Persist Clnt Authzs jansInclClaimsInIdTkn boolean None YES None jans Incl Claims In Id Tkn jansRefreshTknLife integer None YES None Life of refresh token jansDisabled boolean None YES None Status of client jansLogoutURI jsonb None YES None jans Policy URI jansLogoutSessRequired boolean None YES None jans Policy URI jansdId character varying 64 YES None jansd Id jansAuthorizedOrigins jsonb None YES None jans Authorized Origins tknBndCnf text None YES None jansauth - Tkn Binding Id Hash jansAccessTknAsJwt boolean None YES None jansauth - indicator whether to return access token as JWT jansAccessTknSigAlg character varying 64 YES None jansauth - access token signing algorithm jansAccessTknLife integer None YES None Life of access token jansSoftId character varying 64 YES None Soft Identifier jansSoftStatement text None YES None Soft Statement jansRptAsJwt boolean None YES None jansRptAsJwt jansAttrs text None YES None Attrs jansBackchannelTknDeliveryMode character varying 64 YES None jans Backchannel Tkn Delivery Mode jansBackchannelClntNotificationEndpoint character varying 64 YES None jans Backchannel Clnt Notification Endpoint jansBackchannelAuthnReqSigAlg character varying 64 YES None jans Backchannel Authn Req Sig Alg jansBackchannelUsrCodeParameter boolean None YES None jans Backchannel Usr Code Parameter", "title": "jansClnt"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansscope", "text": "Field Type Character Maximum Length Null Default Comment jansDefScope boolean None YES None Track the default scope for an custom OAuth2 Scope. displayName character varying 128 YES None preferred name of a person to be used when displaying entries inum character varying 64 YES None XRI i-number jansScopeTyp character varying 64 YES None OX Attr Scope type creatorId character varying 64 YES None Creator Id creatorTyp character varying 64 YES None Creator type creatorAttrs character varying 64 YES None Creator Attrs creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansClaim jsonb None YES None jans Attr Claim jansScrDn jsonb None YES None Script object DN jansGrpClaims boolean None YES None jans Grp Attr Claims (true or false) jansId character varying 128 YES None Identifier jansIconUrl character varying 64 YES None jans icon url jansUmaPolicyScrDn text None YES None OX policy script Dn jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del", "title": "jansScope"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansumaresource", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries inum character varying 64 YES None XRI i-number jansAssociatedClnt jsonb None YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. jansUmaScope character varying 768 YES None URI reference of scope descriptor jansFaviconImage character varying 64 YES None TODO - Stores URL of favicon jansGrp character varying 64 YES None Group jansId character varying 128 YES None Identifier jansResource text None YES None Host path jansRevision integer None YES None Revision jansTyp character varying 64 YES None jans type jansScopeExpression text None YES None Scope expression iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del", "title": "jansUmaResource"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansumaresourcepermission", "text": "Field Type Character Maximum Length Null Default Comment exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansUmaScope character varying 768 YES None URI reference of scope descriptor jansConfCode character varying 64 YES None jans configuration code jansResourceSetId character varying 64 YES None jans resource set id jansAttrs text None YES None Attrs jansTicket character varying 64 YES None jans ticket jansStatus character varying 16 YES None Status of the entry, used by many objectclasses", "title": "jansUmaResourcePermission"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansgrant", "text": "Field Type Character Maximum Length Null Default Comment grtId character varying 64 YES None jans grant id iat timestamp without time zone None YES None jans Creation", "title": "jansGrant"}, {"location": "janssen-server/reference/database/pgsql-schema/#janstoken", "text": "Field Type Character Maximum Length Null Default Comment authnTime timestamp without time zone None YES None jans Authn Time authzCode character varying 64 YES None jans authorization code iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknCde character varying 80 YES None jans Tkn Code tknTyp character varying 32 YES None jans Tkn Typ usrId character varying 64 YES None jans user id jansUsrDN character varying 128 YES None jans Usr DN clnId character varying 64 YES None jans Clnt id uuid character varying 64 YES None Unique identifier chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims ssnId character varying 64 YES None jans Sess DN attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash dpop character varying 64 YES None DPoP Proof", "title": "jansToken"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansgrp", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number", "title": "jansGrp"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansattr", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansAttrEditTyp jsonb None YES None Specify in exclude who can update an attribute, admin or user jansAttrName character varying 64 YES None Specify an identifier for an attribute. May be multi-value where an attribute has two names, like givenName and first-name. jansAttrOrigin character varying 64 YES None Specify the person objectclass associated with the attribute, used for display purposes in exclude. jansAttrSystemEditTyp character varying 64 YES None TODO - still required? jansAttrTyp character varying 64 YES None Data type of attribute. Values can be string, photo, numeric, date jansClaimName character varying 64 YES None Used by jans in conjunction with jansttributeName to map claims to attributes in LDAP. jansAttrUsgTyp character varying 64 YES None TODO - Usg? Value can be OpenID jansAttrViewTyp jsonb None YES None Specify in exclude who can view an attribute, admin or user jansSAML1URI character varying 64 YES None SAML 1 uri of attribute jansSAML2URI character varying 64 YES None SAML 2 uri of attribute jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansNameIdTyp character varying 64 YES None NameId Typ jansSourceAttr character varying 64 YES None Source Attr for this Attr jansRegExp character varying 64 YES None Regular expression used to validate attribute data jansTooltip character varying 64 YES None Custom tooltip to be shown on the UI jansValidation text None YES None This data has information about attribute Validation", "title": "jansAttr"}, {"location": "janssen-server/reference/database/pgsql-schema/#janspassresetreq", "text": "Field Type Character Maximum Length Null Default Comment creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansGuid character varying 64 YES None A random string to mark temporary tokens personInum character varying 64 YES None Inum of a person", "title": "jansPassResetReq"}, {"location": "janssen-server/reference/database/pgsql-schema/#janssessid", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier sid character varying 64 YES None Sess Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansLastAccessTime timestamp without time zone None YES None Last access time jansUsrDN character varying 128 YES None jans Usr DN authnTime timestamp without time zone None YES None jans Authn Time jansState character varying 64 YES None jansState jansSessState text None YES None jans Sess State jansPermissionGranted boolean None YES None jans Permission Granted jansAsJwt boolean None YES None Boolean field to indicate whether object is used as JWT jansJwt text None YES None JWT representation of the object or otherwise jwt associated with the object jansPermissionGrantedMap text None YES None jans Permission Granted Map jansInvolvedClnts text None YES None Involved clients deviceSecret character varying 64 YES None deviceSecret jansSessAttr text None YES None jansSessAttr", "title": "jansSessId"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansumarpt", "text": "Field Type Character Maximum Length Null Default Comment authnTime timestamp without time zone None YES None jans Authn Time clnId character varying 64 YES None jans Clnt id iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del tknCde character varying 80 YES None jans Tkn Code usrId character varying 64 YES None jans user id ssnId character varying 64 YES None jans Sess DN jansUmaPermission jsonb None YES None jans uma permission uuid character varying 64 YES None Unique identifier dpop character varying 64 YES None DPoP Proof authzCode character varying 64 YES None jans authorization code grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknTyp character varying 32 YES None jans Tkn Typ jansUsrDN character varying 128 YES None jans Usr DN chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash", "title": "jansUmaRPT"}, {"location": "janssen-server/reference/database/pgsql-schema/#janspushapp", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansId character varying 128 YES None Identifier jansName character varying 64 YES None Name jansPushAppConf character varying 64 YES None jansPush application configuration", "title": "jansPushApp"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansscr", "text": "Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number jansScr text None YES None Attr that contains script (python, java script) jansScrTyp character varying 64 YES None Attr that contains script type (e.g. python, java script)", "title": "jansScr"}, {"location": "janssen-server/reference/database/pgsql-schema/#janscustomscr", "text": "Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansScr text None YES None Attr that contains script (python, java script) jansScrTyp character varying 64 YES None Attr that contains script type (e.g. python, java script) jansProgLng character varying 64 YES None programming language jansModuleProperty jsonb None YES None Module property jansConfProperty jsonb None YES None Conf property jansLevel integer None YES None Level jansRevision integer None YES None Revision jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansScrError text None YES None Attr that contains first error which application get during it execution jansAlias jsonb None YES None jansAlias", "title": "jansCustomScr"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansdeviceregistration", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansDeviceKeyHandle character varying 128 YES None jansDeviceKeyHandle jansDeviceHashCode integer None YES None jansDeviceHashCode jansApp character varying 96 YES None jansApp jansDeviceRegistrationConf text None YES None jansDeviceRegistrationConf jansDeviceNotificationConf character varying 64 YES None Extended push notification configuration jansNickName character varying 64 YES None jansNickName jansDeviceData text None YES None jansDeviceData jansCounter integer None YES None jansCounter jansStatus character varying 16 YES None Status of the entry, used by many objectclasses del boolean None YES None del exp timestamp without time zone None YES None jans Exp personInum character varying 64 YES None Inum of a person creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansLastAccessTime timestamp without time zone None YES None Last access time", "title": "jansDeviceRegistration"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansu2freq", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansReqId character varying 64 YES None jansReqId jansReq text None YES None jansReq jansSessStateId character varying 64 YES None jansSessStateId del boolean None YES None del exp timestamp without time zone None YES None jans Exp personInum character varying 64 YES None Inum of a person creationDate timestamp without time zone None YES None Creation Date used for password reset requests", "title": "jansU2fReq"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansmetric", "text": "Field Type Character Maximum Length Null Default Comment jansStartDate timestamp without time zone None YES None Start date jansEndDate timestamp without time zone None YES None End date jansAppTyp character varying 64 YES None jans App Typ jansMetricTyp character varying 64 YES None Metric type creationDate timestamp without time zone None YES None Creation Date used for password reset requests del boolean None YES None del exp timestamp without time zone None YES None jans Exp jansData text None YES None OX data jansHost character varying 64 YES None jans host", "title": "jansMetric"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansumapct", "text": "Field Type Character Maximum Length Null Default Comment clnId character varying 64 YES None jans Clnt id iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del tknCde character varying 80 YES None jans Tkn Code ssnId character varying 64 YES None jans Sess DN jansClaimValues character varying 64 YES None Claim Values dpop character varying 64 YES None DPoP Proof authnTime timestamp without time zone None YES None jans Authn Time authzCode character varying 64 YES None jans authorization code grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknTyp character varying 32 YES None jans Tkn Typ usrId character varying 64 YES None jans user id jansUsrDN character varying 128 YES None jans Usr DN uuid character varying 64 YES None Unique identifier chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash", "title": "jansUmaPCT"}, {"location": "janssen-server/reference/database/pgsql-schema/#janscache", "text": "Field Type Character Maximum Length Null Default Comment uuid character varying 64 YES None Unique identifier iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del dat text None YES None OX data", "title": "jansCache"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansfido2registrationentry", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansApp character varying 96 YES None jansApp jansSessStateId character varying 64 YES None jansSessStateId jansCodeChallenge character varying 64 YES None OX PKCE code challenge jansCodeChallengeHash integer None YES None OX code challenge hash jansPublicKeyId character varying 96 YES None jansPublicKeyId jansPublicKeyIdHash integer None YES None jansPublicKeyIdHash personInum character varying 64 YES None Inum of a person jansRegistrationData text None YES None jansRegistrationData jansDeviceData text None YES None jansDeviceData jansDeviceNotificationConf character varying 64 YES None Extended push notification configuration jansCounter integer None YES None jansCounter jansStatus character varying 16 YES None Status of the entry, used by many objectclasses exp timestamp without time zone None YES None jans Exp del boolean None YES None del", "title": "jansFido2RegistrationEntry"}, {"location": "janssen-server/reference/database/pgsql-schema/#janspushdevice", "text": "Field Type Character Maximum Length Null Default Comment jansUsrId character varying 64 YES None jans user id jansId character varying 128 YES None Identifier jansPushApp text None YES None jansPush application DN jansPushDeviceConf character varying 64 YES None jansPush device configuration jansTyp character varying 64 YES None jans type", "title": "jansPushDevice"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansclntauthz", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansClntId jsonb None YES None jans Clnt id jansUsrId character varying 64 YES None jans user id exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansScope jsonb None YES None jans Attr Scope", "title": "jansClntAuthz"}, {"location": "janssen-server/reference/database/pgsql-schema/#janssectoridentifier", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansRedirectURI jsonb None YES None jans Redirect URI jansClntId jsonb None YES None jans Clnt id", "title": "jansSectorIdentifier"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansfido2authnentry", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansApp character varying 96 YES None jansApp jansSessStateId character varying 64 YES None jansSessStateId jansCodeChallenge character varying 64 YES None OX PKCE code challenge jansCodeChallengeHash integer None YES None OX code challenge hash personInum character varying 64 YES None Inum of a person jansAuthData text None YES None jansAuthData jansStatus character varying 16 YES None Status of the entry, used by many objectclasses exp timestamp without time zone None YES None jans Exp del boolean None YES None del", "title": "jansFido2AuthnEntry"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansrp", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier dat text None YES None OX data", "title": "jansRp"}, {"location": "janssen-server/reference/database/pgsql-schema/#janscibareq", "text": "Field Type Character Maximum Length Null Default Comment authReqId character varying 64 YES None Authn request id clnId character varying 64 YES None jans Clnt id usrId character varying 64 YES None jans user id creationDate timestamp without time zone None YES None Creation Date used for password reset requests exp timestamp without time zone None YES None jans Exp jansStatus character varying 16 YES None Status of the entry, used by many objectclasses", "title": "jansCibaReq"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansstatentry", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier dat text None YES None OX data jansData text None YES None OX data attr text None YES None Attrs", "title": "jansStatEntry"}, {"location": "janssen-server/reference/database/pgsql-schema/#janspar", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del", "title": "jansPar"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansinummap", "text": "Field Type Character Maximum Length Null Default Comment jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansPrimaryKeyAttrName character varying 64 YES None Primary Key Attribute Name jansPrimaryKeyValue character varying 64 YES None Primary Key Value jansSecondaryKeyAttrName character varying 64 YES None Secondary Key Attribute Name jansSecondaryKeyValue character varying 64 YES None Secondary Key Value jansTertiaryKeyAttrName character varying 64 YES None Tertiary Key Attribute Name jansTertiaryKeyValue character varying 64 YES None Tertiary Key Value", "title": "jansInumMap"}, {"location": "janssen-server/reference/database/pgsql-schema/#agmflowrun", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier agFlowSt text None YES None Details of a running agama flow instance agFlowEncCont text None YES None Continuation associated to a running agama flow instance jansCustomMessage character varying 128 YES None exclude custom welcome message exp timestamp without time zone None YES None jans Exp", "title": "agmFlowRun"}, {"location": "janssen-server/reference/database/pgsql-schema/#agmflow", "text": "Field Type Character Maximum Length Null Default Comment agFlowQname character varying 64 YES None Full name of an agama flow agFlowMeta text None YES None Metadata of an agama flow jansScr text None YES None Attr that contains script (python, java script) jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansScrError text None YES None Attr that contains first error which application get during it execution agFlowTrans text None YES None Transpiled code of an agama flow jansRevision integer None YES None Revision jansCustomMessage character varying 128 YES None exclude custom welcome message", "title": "agmFlow"}, {"location": "janssen-server/reference/database/pgsql-schema/#adsprjdeployment", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansStartDate timestamp without time zone None YES None Start date jansEndDate timestamp without time zone None YES None End date adsPrjAssets text None YES None Assets of an ADS project adsPrjDeplDetails text None YES None Misc details associated to an ADS project", "title": "adsPrjDeployment"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansdocument", "text": "Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number displayName character varying 128 YES None preferred name of a person to be used when displaying entries document character varying 64 YES None Save Document in DB creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansModuleProperty jsonb None YES None Module property jansLevel integer None YES None Level jansRevision integer None YES None Revision jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansAlias jsonb None YES None jansAlias", "title": "jansDocument"}, {"location": "janssen-server/reference/database/rdbms-erwin/", "tags": ["administration", "reference", "database"], "text": "Generic tables structure #", "title": "RDBMS Erwin Table"}, {"location": "janssen-server/reference/database/rdbms-erwin/#generic-tables-structure", "text": "", "title": "Generic tables structure"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/", "tags": ["administration", "reference", "json", "feature-flags"], "text": "Janssen Auth Server Feature Flags # Feature Flag Name Description ACTIVE_SESSION Enable/Disable active session endpoint Details CIBA Enable/Disable OpenID Connect Client Initiated Backchannel Authentication Flow(CIBA) flow support Details CLIENTINFO Enable/Disable client info endpoint Details DEVICE_AUTHZ Enable/Disable support for device authorization Details END_SESSION Enable/Disable end session endpoint Details HEALTH_CHECK Enable/Disable health-check endpoint Details ID_GENERATION Enable/Disable ID Generation endpoint Details INTROSPECTION Enable/Disable token introspection endpoint Details JANS_CONFIGURATION Enable/Disable .well-known configuration endpoint Details METRIC Enable/Disable metric reporter feature Details PAR Enable/Disable Pushed Authorization Requests(PAR) feature Details REGISTRATION Enable/Disable client registration endpoint Details REVOKE_SESSION Enable/Disable session revocation endpoint Details REVOKE_TOKEN Enable/Disable token revocation endpoint Details SSA Enable/Disable Software Statement Assertion(SSA) feature Details STAT Enable/Disable Stat service Details STATUS_SESSION Enable/Disable session status check endpoint Details U2F Enable/Disable support for Universal 2nd Factor(U2F) protocol Details UMA Enable/Disable support for User-Managed Access (UMA) Details USERINFO Enable/Disable OpenID Connect userinfo endpoint Details ACTIVE_SESSION # Description: Enable/Disable active session endpoint Required: No Default value: None CIBA # Description: Enable/Disable OpenID Connect Client Initiated Backchannel Authentication Flow(CIBA) flow support Required: No Default value: None CLIENTINFO # Description: Enable/Disable client info endpoint Required: No Default value: None DEVICE_AUTHZ # Description: Enable/Disable support for device authorization Required: No Default value: None END_SESSION # Description: Enable/Disable end session endpoint Required: No Default value: None HEALTH_CHECK # Description: Enable/Disable health-check endpoint Required: No Default value: None ID_GENERATION # Description: Enable/Disable ID Generation endpoint Required: No Default value: None INTROSPECTION # Description: Enable/Disable token introspection endpoint Required: No Default value: None JANS_CONFIGURATION # Description: Enable/Disable .well-known configuration endpoint Required: No Default value: None METRIC # Description: Enable/Disable metric reporter feature Required: No Default value: None PAR # Description: Enable/Disable Pushed Authorization Requests(PAR) feature Required: No Default value: None REGISTRATION # Description: Enable/Disable client registration endpoint Required: No Default value: None REVOKE_SESSION # Description: Enable/Disable session revocation endpoint Required: No Default value: None REVOKE_TOKEN # Description: Enable/Disable token revocation endpoint Required: No Default value: None SSA # Description: Enable/Disable Software Statement Assertion(SSA) feature Required: No Default value: None STAT # Description: Enable/Disable Stat service Required: No Default value: None STATUS_SESSION # Description: Enable/Disable session status check endpoint Required: No Default value: None U2F # Description: Enable/Disable support for Universal 2nd Factor(U2F) protocol Required: No Default value: None UMA # Description: Enable/Disable support for User-Managed Access (UMA) Required: No Default value: None USERINFO # Description: Enable/Disable OpenID Connect userinfo endpoint Required: No Default value: None", "title": "Auth Server"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#janssen-auth-server-feature-flags", "text": "Feature Flag Name Description ACTIVE_SESSION Enable/Disable active session endpoint Details CIBA Enable/Disable OpenID Connect Client Initiated Backchannel Authentication Flow(CIBA) flow support Details CLIENTINFO Enable/Disable client info endpoint Details DEVICE_AUTHZ Enable/Disable support for device authorization Details END_SESSION Enable/Disable end session endpoint Details HEALTH_CHECK Enable/Disable health-check endpoint Details ID_GENERATION Enable/Disable ID Generation endpoint Details INTROSPECTION Enable/Disable token introspection endpoint Details JANS_CONFIGURATION Enable/Disable .well-known configuration endpoint Details METRIC Enable/Disable metric reporter feature Details PAR Enable/Disable Pushed Authorization Requests(PAR) feature Details REGISTRATION Enable/Disable client registration endpoint Details REVOKE_SESSION Enable/Disable session revocation endpoint Details REVOKE_TOKEN Enable/Disable token revocation endpoint Details SSA Enable/Disable Software Statement Assertion(SSA) feature Details STAT Enable/Disable Stat service Details STATUS_SESSION Enable/Disable session status check endpoint Details U2F Enable/Disable support for Universal 2nd Factor(U2F) protocol Details UMA Enable/Disable support for User-Managed Access (UMA) Details USERINFO Enable/Disable OpenID Connect userinfo endpoint Details", "title": "Janssen Auth Server Feature Flags"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#active_session", "text": "Description: Enable/Disable active session endpoint Required: No Default value: None", "title": "ACTIVE_SESSION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#ciba", "text": "Description: Enable/Disable OpenID Connect Client Initiated Backchannel Authentication Flow(CIBA) flow support Required: No Default value: None", "title": "CIBA"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#clientinfo", "text": "Description: Enable/Disable client info endpoint Required: No Default value: None", "title": "CLIENTINFO"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#device_authz", "text": "Description: Enable/Disable support for device authorization Required: No Default value: None", "title": "DEVICE_AUTHZ"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#end_session", "text": "Description: Enable/Disable end session endpoint Required: No Default value: None", "title": "END_SESSION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#health_check", "text": "Description: Enable/Disable health-check endpoint Required: No Default value: None", "title": "HEALTH_CHECK"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#id_generation", "text": "Description: Enable/Disable ID Generation endpoint Required: No Default value: None", "title": "ID_GENERATION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#introspection", "text": "Description: Enable/Disable token introspection endpoint Required: No Default value: None", "title": "INTROSPECTION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#jans_configuration", "text": "Description: Enable/Disable .well-known configuration endpoint Required: No Default value: None", "title": "JANS_CONFIGURATION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#metric", "text": "Description: Enable/Disable metric reporter feature Required: No Default value: None", "title": "METRIC"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#par", "text": "Description: Enable/Disable Pushed Authorization Requests(PAR) feature Required: No Default value: None", "title": "PAR"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#registration", "text": "Description: Enable/Disable client registration endpoint Required: No Default value: None", "title": "REGISTRATION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#revoke_session", "text": "Description: Enable/Disable session revocation endpoint Required: No Default value: None", "title": "REVOKE_SESSION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#revoke_token", "text": "Description: Enable/Disable token revocation endpoint Required: No Default value: None", "title": "REVOKE_TOKEN"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#ssa", "text": "Description: Enable/Disable Software Statement Assertion(SSA) feature Required: No Default value: None", "title": "SSA"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#stat", "text": "Description: Enable/Disable Stat service Required: No Default value: None", "title": "STAT"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#status_session", "text": "Description: Enable/Disable session status check endpoint Required: No Default value: None", "title": "STATUS_SESSION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#u2f", "text": "Description: Enable/Disable support for Universal 2nd Factor(U2F) protocol Required: No Default value: None", "title": "U2F"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#uma", "text": "Description: Enable/Disable support for User-Managed Access (UMA) Required: No Default value: None", "title": "UMA"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#userinfo", "text": "Description: Enable/Disable OpenID Connect userinfo endpoint Required: No Default value: None", "title": "USERINFO"}, {"location": "janssen-server/reference/json/properties/config-api-properties/", "text": "Overview # Please use the left navigation menu to browse the content of this section while we are still working on developing content for Overview page. Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "Config API"}, {"location": "janssen-server/reference/json/properties/config-api-properties/#overview", "text": "Please use the left navigation menu to browse the content of this section while we are still working on developing content for Overview page. Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "Overview"}, {"location": "janssen-server/reference/json/properties/fido2-properties/", "tags": ["administration", "reference", "json", "properties"], "text": "Fido2 Configuration Properties # Property Name Description authenticationHistoryExpiration Expiration time in seconds for approved authentication requests Details authenticatorCertsFolder Authenticators certificates folder Details baseEndpoint The base URL for Fido2 endpoints Details checkU2fAttestations Boolean value indicating if U2f attestation needs to be checked Details cleanServiceBatchChunkSize Each clean up iteration fetches chunk of expired data per base dn and removes it from storage Details cleanServiceInterval Time interval for the Clean Service in seconds Details disableJdkLogger Boolean value specifying whether to enable JDK Loggers Details externalLoggerConfiguration Path to external Fido2 logging configuration Details issuer URL using the https scheme for Issuer identifier Details loggingLayout Logging layout used for Fido2 Details loggingLevel Logging level for Fido2 logger Details mdsAccessToken MDS access token Details mdsCertsFolder MDS TOC root certificates folder Details mdsTocsFolder MDS TOC files folder Details metadataUrlsProvider String value to provide source of URLs with external metadata Details metricReporterEnabled Boolean value specifying whether metric reporter is enabled Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep report data Details personCustomObjectClassList Custom object class list for dynamic person enrolment Details enabledFidoAlgorithms List of Requested Credential Types Details rp Requested Parties Authenticators metadata in json format Details serverMetadataFolder Authenticators metadata in json format Details sessionIdPersistInCache Boolean value specifying whether to persist session_id in cache Details unfinishedRequestExpiration Expiration time in seconds for pending enrollment/authentication requests Details useLocalCache Boolean value to indicate if Local Cache is to be used Details debugUserAutoEnrollment Allow to enroll users on enrollment/authentication requests Details authenticationHistoryExpiration # Description: Expiration time in seconds for approved authentication requests Required: No Default value: None authenticatorCertsFolder # Description: Authenticators certificates folder Required: No Default value: None baseEndpoint # Description: The base URL for Fido2 endpoints Required: No Default value: None checkU2fAttestations # Description: Boolean value indicating if U2f attestation needs to be checked Required: No Default value: None cleanServiceBatchChunkSize # Description: Each clean up iteration fetches chunk of expired data per base dn and removes it from storage Required: No Default value: None cleanServiceInterval # Description: Time interval for the Clean Service in seconds Required: No Default value: None disableJdkLogger # Description: Boolean value specifying whether to enable JDK Loggers Required: No Default value: None externalLoggerConfiguration # Description: Path to external Fido2 logging configuration Required: No Default value: None issuer # Description: URL using the https scheme for Issuer identifier Required: No Default value: None loggingLayout # Description: Logging layout used for Fido2 Required: No Default value: None loggingLevel # Description: Logging level for Fido2 logger Required: No Default value: None mdsAccessToken # Description: MDS access token Required: No Default value: None mdsCertsFolder # Description: MDS TOC root certificates folder Required: No Default value: None mdsTocsFolder # Description: MDS TOC files folder Required: No Default value: None metadataUrlsProvider # Description: String value to provide source of URLs with external metadata Required: No Default value: None metricReporterEnabled # Description: Boolean value specifying whether metric reporter is enabled Required: No Default value: None metricReporterInterval # Description: The interval for metric reporter in seconds Required: No Default value: None metricReporterKeepDataDays # Description: The days to keep report data Required: No Default value: None personCustomObjectClassList # Description: Custom object class list for dynamic person enrolment Required: No Default value: None enabledFidoAlgorithms # Description: List of Requested Credential Types Required: No Default value: None rp # Description: Requested Parties Authenticators metadata in json format Required: No Default value: None serverMetadataFolder # Description: Authenticators metadata in json format Required: No Default value: None sessionIdPersistInCache # Description: Boolean value specifying whether to persist session_id in cache Required: No Default value: false unfinishedRequestExpiration # Description: Expiration time in seconds for pending enrollment/authentication requests Required: No Default value: None useLocalCache # Description: Boolean value to indicate if Local Cache is to be used Required: No Default value: None debugUserAutoEnrollment # Description: Allow to enroll users on enrollment/authentication requests Required: No Default value: None", "title": "FIDO"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#fido2-configuration-properties", "text": "Property Name Description authenticationHistoryExpiration Expiration time in seconds for approved authentication requests Details authenticatorCertsFolder Authenticators certificates folder Details baseEndpoint The base URL for Fido2 endpoints Details checkU2fAttestations Boolean value indicating if U2f attestation needs to be checked Details cleanServiceBatchChunkSize Each clean up iteration fetches chunk of expired data per base dn and removes it from storage Details cleanServiceInterval Time interval for the Clean Service in seconds Details disableJdkLogger Boolean value specifying whether to enable JDK Loggers Details externalLoggerConfiguration Path to external Fido2 logging configuration Details issuer URL using the https scheme for Issuer identifier Details loggingLayout Logging layout used for Fido2 Details loggingLevel Logging level for Fido2 logger Details mdsAccessToken MDS access token Details mdsCertsFolder MDS TOC root certificates folder Details mdsTocsFolder MDS TOC files folder Details metadataUrlsProvider String value to provide source of URLs with external metadata Details metricReporterEnabled Boolean value specifying whether metric reporter is enabled Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep report data Details personCustomObjectClassList Custom object class list for dynamic person enrolment Details enabledFidoAlgorithms List of Requested Credential Types Details rp Requested Parties Authenticators metadata in json format Details serverMetadataFolder Authenticators metadata in json format Details sessionIdPersistInCache Boolean value specifying whether to persist session_id in cache Details unfinishedRequestExpiration Expiration time in seconds for pending enrollment/authentication requests Details useLocalCache Boolean value to indicate if Local Cache is to be used Details debugUserAutoEnrollment Allow to enroll users on enrollment/authentication requests Details", "title": "Fido2 Configuration Properties"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#authenticationhistoryexpiration", "text": "Description: Expiration time in seconds for approved authentication requests Required: No Default value: None", "title": "authenticationHistoryExpiration"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#authenticatorcertsfolder", "text": "Description: Authenticators certificates folder Required: No Default value: None", "title": "authenticatorCertsFolder"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#baseendpoint", "text": "Description: The base URL for Fido2 endpoints Required: No Default value: None", "title": "baseEndpoint"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#checku2fattestations", "text": "Description: Boolean value indicating if U2f attestation needs to be checked Required: No Default value: None", "title": "checkU2fAttestations"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#cleanservicebatchchunksize", "text": "Description: Each clean up iteration fetches chunk of expired data per base dn and removes it from storage Required: No Default value: None", "title": "cleanServiceBatchChunkSize"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#cleanserviceinterval", "text": "Description: Time interval for the Clean Service in seconds Required: No Default value: None", "title": "cleanServiceInterval"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#disablejdklogger", "text": "Description: Boolean value specifying whether to enable JDK Loggers Required: No Default value: None", "title": "disableJdkLogger"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#externalloggerconfiguration", "text": "Description: Path to external Fido2 logging configuration Required: No Default value: None", "title": "externalLoggerConfiguration"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#issuer", "text": "Description: URL using the https scheme for Issuer identifier Required: No Default value: None", "title": "issuer"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#logginglayout", "text": "Description: Logging layout used for Fido2 Required: No Default value: None", "title": "loggingLayout"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#logginglevel", "text": "Description: Logging level for Fido2 logger Required: No Default value: None", "title": "loggingLevel"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#mdsaccesstoken", "text": "Description: MDS access token Required: No Default value: None", "title": "mdsAccessToken"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#mdscertsfolder", "text": "Description: MDS TOC root certificates folder Required: No Default value: None", "title": "mdsCertsFolder"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#mdstocsfolder", "text": "Description: MDS TOC files folder Required: No Default value: None", "title": "mdsTocsFolder"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#metadataurlsprovider", "text": "Description: String value to provide source of URLs with external metadata Required: No Default value: None", "title": "metadataUrlsProvider"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#metricreporterenabled", "text": "Description: Boolean value specifying whether metric reporter is enabled Required: No Default value: None", "title": "metricReporterEnabled"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#metricreporterinterval", "text": "Description: The interval for metric reporter in seconds Required: No Default value: None", "title": "metricReporterInterval"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#metricreporterkeepdatadays", "text": "Description: The days to keep report data Required: No Default value: None", "title": "metricReporterKeepDataDays"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#personcustomobjectclasslist", "text": "Description: Custom object class list for dynamic person enrolment Required: No Default value: None", "title": "personCustomObjectClassList"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#enabledfidoalgorithms", "text": "Description: List of Requested Credential Types Required: No Default value: None", "title": "enabledFidoAlgorithms"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#rp", "text": "Description: Requested Parties Authenticators metadata in json format Required: No Default value: None", "title": "rp"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#servermetadatafolder", "text": "Description: Authenticators metadata in json format Required: No Default value: None", "title": "serverMetadataFolder"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#sessionidpersistincache", "text": "Description: Boolean value specifying whether to persist session_id in cache Required: No Default value: false", "title": "sessionIdPersistInCache"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#unfinishedrequestexpiration", "text": "Description: Expiration time in seconds for pending enrollment/authentication requests Required: No Default value: None", "title": "unfinishedRequestExpiration"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#uselocalcache", "text": "Description: Boolean value to indicate if Local Cache is to be used Required: No Default value: None", "title": "useLocalCache"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#debuguserautoenrollment", "text": "Description: Allow to enroll users on enrollment/authentication requests Required: No Default value: None", "title": "debugUserAutoEnrollment"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/", "tags": ["administration", "reference", "json", "properties"], "text": "Janssen Auth Server Configuration Properties # Property Name Description accessTokenLifetime The lifetime of the short lived Access Token Details accessTokenSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for the access token to encode the Claims in a JWT Details activeSessionAuthorizationScope Authorization Scope for active session Details agamaConfiguration Engine Config which offers an alternative way to build authentication flows in Janssen server Details allowAllValueForRevokeEndpoint Boolean value true allow all value for revoke endpoint Details allowBlankValuesInDiscoveryResponse Boolean value specifying whether to allow blank values in discovery response Details allowEndSessionWithUnmatchedSid default value false. If true, sid check will be skipped Details allowIdTokenWithoutImplicitGrantType Specifies if a token without implicit grant types is allowed Details allowPostLogoutRedirectWithoutValidation Allows post-logout redirect without validation for the End Session endpoint (still AS validates it against clientWhiteList url pattern property) Details allowSpontaneousScopes Specifies whether to allow spontaneous scopes Details authenticationFilters This list details filters for user authentication Details authenticationFiltersEnabled Boolean value specifying whether to enable user authentication filters Details authenticationProtectionConfiguration Authentication Brute Force Protection Configuration Details authorizationCodeLifetime The lifetime of the Authorization Code Details authorizationEncryptionAlgValuesSupported List of authorization encryption algorithms supported by this OP Details authorizationEncryptionEncValuesSupported A list of the authorization encryption algorithms supported Details authorizationEndpoint The authorization endpoint URL Details authorizationRequestCustomAllowedParameters This list details the allowed custom parameters for authorization requests Details authorizationSigningAlgValuesSupported List of authorization signing algorithms supported by this OP Details backchannelAuthenticationEndpoint Backchannel Authentication Endpoint Details backchannelAuthenticationRequestSigningAlgValuesSupported Backchannel Authentication Request Signing Alg Values Supported Details backchannelAuthenticationResponseExpiresIn Backchannel Authentication Response Expires In Details backchannelAuthenticationResponseInterval Backchannel Authentication Response Interval Details backchannelBindingMessagePattern Backchannel Binding Message Pattern Details backchannelClientId Backchannel Client Id Details backchannelDeviceRegistrationEndpoint Backchannel Device Registration Endpoint Details backchannelLoginHintClaims Backchannel Login Hint Claims Details backchannelRedirectUri Backchannel Redirect Uri Details backchannelRequestsProcessorJobChunkSize Each backchannel request processor iteration fetches chunk of data to be processed Details backchannelRequestsProcessorJobIntervalSec Specifies the allowable elapsed time in seconds backchannel request processor executes Details backchannelTokenDeliveryModesSupported Backchannel Token Delivery Modes Supported Details backchannelUserCodeParameterSupported Backchannel User Code Parameter Supported Details baseEndpoint The base URL for endpoints Details blockWebviewAuthorizationEnabled Enable/Disable block authorizations that originate from Webview (Mobile apps). Details changeSessionIdOnAuthentication Boolean value specifying whether change session_id on authentication. Default value is true Details checkSessionIFrame URL for an OP IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Details checkUserPresenceOnRefreshToken Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check. Details cibaEndUserNotificationConfig CIBA End User Notification Config Details cibaGrantLifeExtraTimeSec Specifies the CIBA Grant life extra time in seconds Details cibaMaxExpirationTimeAllowedSec Specifies the CIBA token expiration time in seconds Details claimsLocalesSupported This list details the languages and scripts supported for values in the claims being returned Details claimsParameterSupported Specifies whether the OP supports use of the claims parameter Details claimTypesSupported A list of the Claim Types that the OpenID Provider supports Details cleanServiceBatchChunkSize Clean service chunk size which is used during clean up Details cleanServiceInterval Time interval for the Clean Service in seconds Details clientAuthenticationFilters This list details filters for client authentication Details clientAuthenticationFiltersEnabled Boolean value specifying whether to enable client authentication filters Details clientBlackList This list specified which client redirection URIs are black-listed Details clientInfoEndpoint The Client Info endpoint URL Details clientRegDefaultToCodeFlowWithRefresh Boolean value specifying whether to add Authorization Code Flow with Refresh grant during client registratio Details clientWhiteList This list specifies which client redirection URIs are white-listed Details configurationUpdateInterval The interval for configuration update in seconds Details consentGatheringScriptBackwardCompatibility Boolean value specifying whether to turn on Consent Gathering Script backward compatibility mode. If true AS will pick up script with higher level globally. If false (default) AS will pick up script based on client configuration Details cookieDomain Sets cookie domain for all cookies created by OP Details corsConfigurationFilters This list specifies the CORS configuration filters Details cssLocation The location for CSS files Details customHeadersWithAuthorizationResponse Choose whether to enable the custom response header parameter to return custom headers with the authorization response Details dateFormatterPatterns List of key value date formatters, e.g. 'userinfo: 'yyyy-MM-dd', etc. Details dcrAuthorizationWithClientCredentials Boolean value indicating if DCR authorization to be performed using client credentials Details dcrAuthorizationWithMTLS Boolean value indicating if DCR authorization allowed with MTLS Details dcrForbidExpirationTimeInRequest Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration. Details dcrSignatureValidationEnabled Boolean value enables DCR signature validation. Default is false Details dcrSignatureValidationJwks Specifies JWKS for all DCR's validations Details dcrSignatureValidationJwksUri Specifies JWKS URI for all DCR's validations Details dcrSignatureValidationSharedSecret Specifies shared secret for Dynamic Client Registration Details dcrSignatureValidationSoftwareStatementJwksClaim Specifies claim name inside software statement. Value of claim should point to inlined JWKS Details dcrSignatureValidationSoftwareStatementJwksURIClaim Specifies claim name inside software statement. Value of claim should point to JWKS URI Details dcrSsaValidationConfigs DCR SSA Validation configurations used to perform validation of SSA or DCR Details defaultSignatureAlgorithm The default signature algorithm to sign ID Tokens Details defaultSubjectType The default subject type used for dynamic client registration Details deviceAuthzAcr Device authz acr Details deviceAuthzEndpoint URL for the Device Authorization Details deviceAuthzRequestExpiresIn Expiration time given for device authorization requests Details deviceAuthzResponseTypeToProcessAuthz Response type used to process device authz requests Details deviceAuthzTokenPollInterval Default interval returned to the client to process device token requests Details disableAuthnForMaxAgeZero Boolean value specifying whether to disable authentication when max_age=0 Details disableJdkLogger Choose whether to disable JDK loggers Details disablePromptConsent Boolean value specifying whether to disable prompt=consent Details disablePromptLogin Boolean value specifying whether to disable prompt=login Details disableU2fEndpoint Choose whether to disable U2F endpoints Details discoveryAllowedKeys List of configuration response claim allowed to be displayed in discovery endpoint Details discoveryCacheLifetimeInMinutes Lifetime of discovery cache Details discoveryDenyKeys List of configuration response claims which must not be displayed in discovery endpoint response Details displayValuesSupported A list of the display parameter values that the OpenID Provider supports Details dnName DN of certificate issuer Details dpopJtiCacheTime Demonstration of Proof-of-Possession (DPoP) cache time Details dpopNonceCacheTime Demonstration of Proof-of-Possession (DPoP) nonce cache time Details dpopSigningAlgValuesSupported Demonstration of Proof-of-Possession (DPoP) authorization signing algorithms supported Details dpopTimeframe Demonstration of Proof-of-Possession (DPoP) timeout Details dpopUseNonce Demonstration of Proof-of-Possession (DPoP) use nonce Details grantTypesSupportedByDynamicRegistration This list details which OAuth 2.0 grant types can be set up with the client registration API Details dynamicRegistrationAllowedPasswordGrantScopes List of grant scopes for dynamic registration Details dynamicRegistrationCustomAttributes This list details the custom attributes allowed for dynamic registration Details dynamicRegistrationCustomObjectClass LDAP custom object class for dynamic registration Details dynamicRegistrationDefaultCustomAttributes This map provides default custom attributes with values for dynamic registration Details dynamicRegistrationExpirationTime Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire Details dynamicRegistrationPasswordGrantTypeEnabled Boolean value specifying whether to enable Password Grant Type during Dynamic Registration Details dynamicRegistrationPersistClientAuthorizations Boolean value specifying whether to persist client authorizations Details dynamicRegistrationScopesParamEnabled Boolean value specifying whether to enable scopes parameter in dynamic registration Details enableClientGrantTypeUpdate Choose if client can update Grant Type values Details enabledOAuthAuditLogging enable OAuth Audit Logging Details endSessionEndpoint URL at the OP to which an RP can perform a redirect to request that the end user be logged out at the OP Details endSessionWithAccessToken Choose whether to accept access tokens to call end_session endpoint Details errorHandlingMethod A list of possible error handling methods. Possible values: remote (send error back to RP), internal (show error page) Details errorReasonEnabled Boolean value specifying whether to return detailed reason of the error from AS. Default value is false Details expirationNotificatorEnabled Boolean value specifying whether expiration notificator is enabled (used to identify expiration for persistence that support TTL, like Couchbase) Details expirationNotificatorIntervalInSeconds The expiration notificator interval in second Details expirationNotificatorMapSizeLimit The expiration notificator maximum size limit Details externalLoggerConfiguration The path to the external log4j2 logging configuration Details externalUriWhiteList This list specifies which external URIs can be called by AS (if empty any URI can be called) Details fapiCompatibility Boolean value specifying whether to turn on FAPI compatibility mode. If true AS behaves in more strict mode Details featureFlags List of enabled feature flags Details forceIdTokenHintPresence Boolean value specifying whether force id_token_hint parameter presence Details forceOfflineAccessScopeToEnableRefreshToken Boolean value specifying whether force offline_access scope to enable refresh_token grant type. Default value is true Details forceSignedRequestObject Boolean value true indicates that signed request object is mandatory Details frontChannelLogoutSessionSupported Choose whether to support front channel session logout Details grantTypesAndResponseTypesAutofixEnabled Boolean value specifying whether to Grant types and Response types can be auto fixed Details grantTypesSupported This list details which OAuth 2.0 grant types are supported by this OP Details httpLoggingEnabled Enable/disable request/response logging filter Details httpLoggingExcludePaths This list details the base URIs for which the request/response logging filter will not record activity Details httpLoggingResponseBodyContent Defines if Response body will be logged. Default value is false Details idGenerationEndpoint ID Generation endpoint URL Details idTokenEncryptionAlgValuesSupported A list of the JWE encryption algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenEncryptionEncValuesSupported A list of the JWE encryption algorithms (enc values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenFilterClaimsBasedOnAccessToken Boolean value specifying whether idToken filters claims based on accessToken Details idTokenLifetime The lifetime of the ID Token Details idTokenSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenTokenBindingCnfValuesSupported Array containing a list of the JWT Confirmation Method member names supported by the OP for Token Binding of ID Tokens. The presence of this parameter indicates that the OpenID Provider supports Token Binding of ID Tokens. If omitted, the default is that the OpenID Provider does not support Token Binding of ID Tokens Details imgLocation The location for image files Details includeSidInResponse Boolean value specifying whether to include sessionId in response Details introspectionAccessTokenMustHaveIntrospectionScope If True, rejects introspection requests if access_token does not have the 'introspection' scope in its authorization header. Comparing to 'uma_protection', 'introspection' scope is not allowed for dynamic registration' Details introspectionAccessTokenMustHaveUmaProtectionScope If True, rejects introspection requests if access_token does not have the uma_protection scope in its authorization header Details introspectionEndpoint Introspection endpoint URL Details introspectionResponseScopesBackwardCompatibility Boolean value specifying introspection response backward compatibility mode Details introspectionScriptBackwardCompatibility Boolean value specifying whether switch off client's introspection scripts (true value) and run all scripts that exists on server. Default value is false Details introspectionSkipAuthorization Specifies if authorization to be skipped for introspection Details invalidateSessionCookiesAfterAuthorizationFlow Boolean value to specify whether to invalidate session_id and consent_session_id cookies right after successful or unsuccessful authorization Details issuer URL using the https scheme that OP asserts as Issuer identifier Details jansId URL for the Inum generator Service Details jansOpenIdConnectVersion OpenID Connect Version Details jmsBrokerURISet JMS Broker URI Set Details jmsPassword JMS Password Details jmsUserName JMS UserName Details jsLocation The location for JavaScript files Details jwksAlgorithmsSupported A list of algorithms that will be used in JWKS endpoint Details jwksUri URL of the OP's JSON Web Key Set (JWK) document. This contains the signing key(s) the RP uses to validate signatures from the OP Details keepAuthenticatorAttributesOnAcrChange Boolean value specifying whether to keep authenticator attributes on ACR change Details keyAlgsAllowedForGeneration List of algorithm allowed to be used for key generation Details keyRegenerationEnabled Boolean value specifying whether to regenerate keys Details keyRegenerationInterval The interval for key regeneration in hours Details keySelectionStrategy Key Selection Strategy : OLDER, NEWER, FIRST Details keySignWithSameKeyButDiffAlg Specifies if signing to be done with same key but apply different algorithms Details keyStoreFile The Key Store File (JKS) Details keyStoreSecret The Key Store password Details legacyIdTokenClaims Choose whether to include claims in ID tokens Details logClientIdOnClientAuthentication Choose if application should log the Client ID on client authentication Details logClientNameOnClientAuthentication Choose if application should log the Client Name on client authentication Details loggingLayout Logging layout used for Jans Authorization Server loggers Details loggingLevel Specify the logging level of loggers Details logNotFoundEntityAsError Boolean value specifying whether to log not_found entity exception as error or as trace. Default value is false (trace). Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep metric reported data Details mtlsAuthorizationEndpoint URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Endpoint Details mtlsCheckSessionIFrame URL for Mutual TLS (mTLS) IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Details mtlsClientInfoEndpoint URL for Mutual TLS (mTLS) Client Info endpoint Details mtlsDeviceAuthzEndpoint Mutual TLS (mTLS) device authorization endpoint URL Details mtlsEndSessionEndpoint URL for Mutual TLS (mTLS) to which an RP can perform a redirect to request that the end user be logged out at the OP Details mtlsIdGenerationEndpoint Mutual TLS (mTLS) ID generation endpoint URL Details mtlsIntrospectionEndpoint Mutual TLS (mTLS) introspection endpoint URL Details mtlsJwksUri URL for Mutual TLS (mTLS) of the OP's JSON Web Key Set (JWK) document Details mtlsParEndpoint Mutual TLS (mTLS) Pushed Authorization Requests(PAR) endpoint URL Details mtlsRegistrationEndpoint Mutual TLS (mTLS) registration endpoint URL Details mtlsTokenEndpoint URL for Mutual TLS (mTLS) Authorization token Endpoint Details mtlsTokenRevocationEndpoint URL for Mutual TLS (mTLS) Authorization token revocation endpoint Details mtlsUserInfoEndpoint Mutual TLS (mTLS) user info endpoint URL Details openIdConfigurationEndpoint URL for the Open ID Connect Configuration Endpoint Details openIdDiscoveryEndpoint Discovery endpoint URL Details openidScopeBackwardCompatibility Set to false to only allow token endpoint request for openid scope with grant type equals to authorization_code, restrict access to userinfo to scope openid and only return id_token if scope contains openid Details openidSubAttribute Specifies which LDAP attribute is used for the subject identifier claim Details opPolicyUri URL that the OpenID Provider provides to the person registering the Client to read about the OP's requirements on how the Relying Party can use the data provided by the OP Details opTosUri URL that the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service Details pairwiseCalculationKey Key to calculate algorithmic pairwise IDs Details pairwiseCalculationSalt Salt to calculate algorithmic pairwise IDs Details pairwiseIdType the pairwise ID type Details parEndpoint URL for Pushed Authorisation Request (PAR) Endpoint Details persistIdToken Specifies whether to persist id_token (otherwise saves into cache) Details persistRefreshToken Specifies whether to persist refresh_token (otherwise saves into cache) Details personCustomObjectClassList This list details LDAP custom object classes for dynamic person enrollment Details publicSubjectIdentifierPerClientEnabled Specifies whether public subject identifier is allowed per client Details redirectUrisRegexEnabled Enable/Disable redirect uris validation using regular expression Details refreshTokenExtendLifetimeOnRotation Boolean value specifying whether to extend refresh tokens on rotation Details refreshTokenLifetime The lifetime of the Refresh Token Details registrationEndpoint Registration endpoint URL Details rejectEndSessionIfIdTokenExpired default value false. If true and id_token is not found in db, request is rejected Details rejectJwtWithNoneAlg Boolean value specifying whether reject JWT requested or validated with algorithm None. Default value is true Details removeRefreshTokensForClientOnLogout Boolean value specifying whether to remove Refresh Tokens on logout. Default value is true Details requestObjectEncryptionAlgValuesSupported A list of the JWE encryption algorithms (alg values) supported by the OP for Request Objects Details requestObjectEncryptionEncValuesSupported A list of the JWE encryption algorithms (enc values) supported by the OP for Request Objects Details requestObjectSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for Request Objects Details requestParameterSupported Boolean value specifying whether the OP supports use of the request parameter Details requestUriBlockList Block list for requestUri that can come to Authorization Endpoint (e.g. localhost) Details requestUriHashVerificationEnabled Boolean value specifying whether the OP supports use of the request_uri hash verification Details requestUriParameterSupported Boolean value specifying whether the OP supports use of the request_uri parameter Details requirePar Boolean value to indicate of Pushed Authorisation Request(PAR)is required Details requirePkce Boolean value true check for Proof Key for Code Exchange (PKCE) Details requireRequestObjectEncryption Boolean value true encrypts request object Details requireRequestUriRegistration Boolean value specifying whether the OP requires any request_uri values used to be pre-registered using the request_uris registration parameter Details responseModesSupported This list details which OAuth 2.0 response modes are supported by this OP Details responseTypesSupported This list details which OAuth 2.0 response_type values are supported by this OP. Details returnClientSecretOnRead Boolean value specifying whether a client_secret is returned on client GET or PUT. Set to true by default which means to return secret Details returnDeviceSecretFromAuthzEndpoint Details rotateClientRegistrationAccessTokenOnUsage Boolean value specifying whether to rotate client registration access token after each usage Details rotateDeviceSecret Details sectorIdentifierCacheLifetimeInMinutes Sector Identifier cache lifetime in minutes Details serverSessionIdLifetime Dedicated property to control lifetime of the server side OP session object in seconds. Overrides sessionIdLifetime. By default value is 0, so object lifetime equals sessionIdLifetime (which sets both cookie and object expiration). It can be useful if goal is to keep different values for client cookie and server object Details serviceDocumentation URL of a page containing human-readable information that developers might want or need to know when using the OpenID Provider Details sessionIdLifetime The lifetime of session id in seconds. If 0 or -1 then expiration is not set. session_id cookie expires when browser session ends Details sessionIdPersistInCache Boolean value specifying whether to persist session_id in cache Details sessionIdPersistOnPromptNone Boolean value specifying whether to persist session ID on prompt none Details sessionIdRequestParameterEnabled Boolean value specifying whether to enable session_id HTTP request parameter Details sessionIdUnauthenticatedUnusedLifetime The lifetime for unused unauthenticated session states Details sessionIdUnusedLifetime The lifetime for unused session states Details shareSubjectIdBetweenClientsWithSameSectorId When true, clients with the same Sector ID also share the same Subject ID Details skipAuthenticationFilterOptionsMethod Force Authentication Filtker to process OPTIONS request Details skipAuthorizationForOpenIdScopeAndPairwiseId Choose whether to skip authorization if a client has an OpenId scope and a pairwise ID Details skipRefreshTokenDuringRefreshing Boolean value specifying whether to skip refreshing tokens on refreshing Details softwareStatementValidationClaimName Validation claim name for software statement Details softwareStatementValidationType Validation type used for software statement Details spontaneousScopeLifetime The lifetime of spontaneous scope in seconds Details ssaConfiguration SSA Configuration Details statAuthorizationScope Scope required for Statistical Authorization Details staticDecryptionKid Specifies static decryption Kid Details staticKid Specifies static Kid Details statTimerIntervalInSeconds Statistical data capture time interval Details subjectIdentifiersPerClientSupported A list of the subject identifiers supported per client Details subjectTypesSupported This list details which Subject Identifier types that the OP supports. Valid types include pairwise and public. Details tokenEndpoint The token endpoint URL Details tokenEndpointAuthMethodsSupported A list of Client Authentication methods supported by this Token Endpoint Details tokenEndpointAuthSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the Token Endpoint for the signature on the JWT used to authenticate the Client at the Token Endpoint for the private_key_jwt and client_secret_jwt authentication methods Details tokenRevocationEndpoint The URL for the access_token or refresh_token revocation endpoint Details trustedClientEnabled Boolean value specifying whether a client is trusted and no authorization is required Details trustedSsaIssuers List of trusted SSA issuers with configuration (e.g. automatically granted scopes). Details uiLocalesSupported This list details the languages and scripts supported for the user interface Details umaAddScopesAutomatically Add UMA scopes automatically if it is not registered yet Details umaConfigurationEndpoint UMA Configuration endpoint URL Details umaGrantAccessIfNoPolicies Specify whether to grant access to resources if there is no any policies associated with scopes Details umaPctLifetime UMA PCT lifetime Details umaResourceLifetime UMA Resource lifetime Details umaRestrictResourceToAssociatedClient Restrict access to resource by associated client Details umaRptAsJwt Issue RPT as JWT or as random string Details umaRptLifetime UMA RPT lifetime Details umaTicketLifetime UMA ticket lifetime Details umaValidateClaimToken Validate claim_token as id_token assuming it is issued by local id Details updateClientAccessTime Choose if application should update oxLastAccessTime/oxLastLogonTime attributes upon client authentication Details updateUserLastLogonTime Choose if application should update oxLastLogonTime attribute upon user authentication Details useHighestLevelScriptIfAcrScriptNotFound Enable/Disable usage of highest level script in case ACR script does not exist Details useLocalCache Cache in local memory cache attributes, scopes, clients and organization entry with expiration 60 seconds Details useNestedJwtDuringEncryption Boolean value specifying whether to use nested Jwt during encryption Details userInfoEncryptionAlgValuesSupported This JSON Array lists which JWS encryption algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details userInfoEncryptionEncValuesSupported This JSON Array lists which JWS encryption algorithms (enc values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details userInfoEndpoint The User Info endpoint URL Details userInfoSigningAlgValuesSupported This JSON Array lists which JWS signing algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details webKeysStorage Web Key Storage Type Details accessTokenLifetime # Description: The lifetime of the short lived Access Token Required: No Default value: None accessTokenSigningAlgValuesSupported # Description: A list of the JWS signing algorithms (alg values) supported by the OP for the access token to encode the Claims in a JWT Required: No Default value: None activeSessionAuthorizationScope # Description: Authorization Scope for active session Required: No Default value: None agamaConfiguration # Description: Engine Config which offers an alternative way to build authentication flows in Janssen server Required: No Default value: None allowAllValueForRevokeEndpoint # Description: Boolean value true allow all value for revoke endpoint Required: No Default value: false allowBlankValuesInDiscoveryResponse # Description: Boolean value specifying whether to allow blank values in discovery response Required: No Default value: false allowEndSessionWithUnmatchedSid # Description: default value false. If true, sid check will be skipped Required: No Default value: false allowIdTokenWithoutImplicitGrantType # Description: Specifies if a token without implicit grant types is allowed Required: No Default value: None allowPostLogoutRedirectWithoutValidation # Description: Allows post-logout redirect without validation for the End Session endpoint (still AS validates it against clientWhiteList url pattern property) Required: No Default value: false allowSpontaneousScopes # Description: Specifies whether to allow spontaneous scopes Required: No Default value: None authenticationFilters # Description: This list details filters for user authentication Required: No Default value: None authenticationFiltersEnabled # Description: Boolean value specifying whether to enable user authentication filters Required: No Default value: None authenticationProtectionConfiguration # Description: Authentication Brute Force Protection Configuration Required: No Default value: None authorizationCodeLifetime # Description: The lifetime of the Authorization Code Required: No Default value: None authorizationEncryptionAlgValuesSupported # Description: List of authorization encryption algorithms supported by this OP Required: No Default value: None authorizationEncryptionEncValuesSupported # Description: A list of the authorization encryption algorithms supported Required: No Default value: None authorizationEndpoint # Description: The authorization endpoint URL Required: No Default value: None authorizationRequestCustomAllowedParameters # Description: This list details the allowed custom parameters for authorization requests Required: No Default value: None authorizationSigningAlgValuesSupported # Description: List of authorization signing algorithms supported by this OP Required: No Default value: None backchannelAuthenticationEndpoint # Description: Backchannel Authentication Endpoint Required: No Default value: None backchannelAuthenticationRequestSigningAlgValuesSupported # Description: Backchannel Authentication Request Signing Alg Values Supported Required: No Default value: None backchannelAuthenticationResponseExpiresIn # Description: Backchannel Authentication Response Expires In Required: No Default value: None backchannelAuthenticationResponseInterval # Description: Backchannel Authentication Response Interval Required: No Default value: None backchannelBindingMessagePattern # Description: Backchannel Binding Message Pattern Required: No Default value: None backchannelClientId # Description: Backchannel Client Id Required: No Default value: None backchannelDeviceRegistrationEndpoint # Description: Backchannel Device Registration Endpoint Required: No Default value: None backchannelLoginHintClaims # Description: Backchannel Login Hint Claims Required: No Default value: None backchannelRedirectUri # Description: Backchannel Redirect Uri Required: No Default value: None backchannelRequestsProcessorJobChunkSize # Description: Each backchannel request processor iteration fetches chunk of data to be processed Required: No Default value: None backchannelRequestsProcessorJobIntervalSec # Description: Specifies the allowable elapsed time in seconds backchannel request processor executes Required: No Default value: None backchannelTokenDeliveryModesSupported # Description: Backchannel Token Delivery Modes Supported Required: No Default value: None backchannelUserCodeParameterSupported # Description: Backchannel User Code Parameter Supported Required: No Default value: None baseEndpoint # Description: The base URL for endpoints Required: No Default value: None blockWebviewAuthorizationEnabled # Description: Enable/Disable block authorizations that originate from Webview (Mobile apps). Required: No Default value: false changeSessionIdOnAuthentication # Description: Boolean value specifying whether change session_id on authentication. Default value is true Required: No Default value: true checkSessionIFrame # Description: URL for an OP IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Required: No Default value: None checkUserPresenceOnRefreshToken # Description: Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check. Required: No Default value: false cibaEndUserNotificationConfig # Description: CIBA End User Notification Config Required: No Default value: None cibaGrantLifeExtraTimeSec # Description: Specifies the CIBA Grant life extra time in seconds Required: No Default value: None cibaMaxExpirationTimeAllowedSec # Description: Specifies the CIBA token expiration time in seconds Required: No Default value: None claimsLocalesSupported # Description: This list details the languages and scripts supported for values in the claims being returned Required: No Default value: None claimsParameterSupported # Description: Specifies whether the OP supports use of the claims parameter Required: No Default value: None claimTypesSupported # Description: A list of the Claim Types that the OpenID Provider supports Required: No Default value: None cleanServiceBatchChunkSize # Description: Clean service chunk size which is used during clean up Required: No Default value: 100 cleanServiceInterval # Description: Time interval for the Clean Service in seconds Required: No Default value: None clientAuthenticationFilters # Description: This list details filters for client authentication Required: No Default value: None clientAuthenticationFiltersEnabled # Description: Boolean value specifying whether to enable client authentication filters Required: No Default value: None clientBlackList # Description: This list specified which client redirection URIs are black-listed Required: No Default value: None clientInfoEndpoint # Description: The Client Info endpoint URL Required: No Default value: None clientRegDefaultToCodeFlowWithRefresh # Description: Boolean value specifying whether to add Authorization Code Flow with Refresh grant during client registratio Required: No Default value: None clientWhiteList # Description: This list specifies which client redirection URIs are white-listed Required: No Default value: None configurationUpdateInterval # Description: The interval for configuration update in seconds Required: No Default value: None consentGatheringScriptBackwardCompatibility # Description: Boolean value specifying whether to turn on Consent Gathering Script backward compatibility mode. If true AS will pick up script with higher level globally. If false (default) AS will pick up script based on client configuration Required: No Default value: false cookieDomain # Description: Sets cookie domain for all cookies created by OP Required: No Default value: None corsConfigurationFilters # Description: This list specifies the CORS configuration filters Required: No Default value: None cssLocation # Description: The location for CSS files Required: No Default value: None customHeadersWithAuthorizationResponse # Description: Choose whether to enable the custom response header parameter to return custom headers with the authorization response Required: No Default value: None dateFormatterPatterns # Description: List of key value date formatters, e.g. 'userinfo: 'yyyy-MM-dd', etc. Required: No Default value: None dcrAuthorizationWithClientCredentials # Description: Boolean value indicating if DCR authorization to be performed using client credentials Required: No Default value: false dcrAuthorizationWithMTLS # Description: Boolean value indicating if DCR authorization allowed with MTLS Required: No Default value: false dcrForbidExpirationTimeInRequest # Description: Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration. Required: No Default value: false dcrSignatureValidationEnabled # Description: Boolean value enables DCR signature validation. Default is false Required: No Default value: false dcrSignatureValidationJwks # Description: Specifies JWKS for all DCR's validations Required: No Default value: None dcrSignatureValidationJwksUri # Description: Specifies JWKS URI for all DCR's validations Required: No Default value: None dcrSignatureValidationSharedSecret # Description: Specifies shared secret for Dynamic Client Registration Required: No Default value: None dcrSignatureValidationSoftwareStatementJwksClaim # Description: Specifies claim name inside software statement. Value of claim should point to inlined JWKS Required: No Default value: None dcrSignatureValidationSoftwareStatementJwksURIClaim # Description: Specifies claim name inside software statement. Value of claim should point to JWKS URI Required: No Default value: None dcrSsaValidationConfigs # Description: DCR SSA Validation configurations used to perform validation of SSA or DCR Required: No Default value: None defaultSignatureAlgorithm # Description: The default signature algorithm to sign ID Tokens Required: No Default value: None defaultSubjectType # Description: The default subject type used for dynamic client registration Required: No Default value: None deviceAuthzAcr # Description: Device authz acr Required: No Default value: None deviceAuthzEndpoint # Description: URL for the Device Authorization Required: No Default value: None deviceAuthzRequestExpiresIn # Description: Expiration time given for device authorization requests Required: No Default value: None deviceAuthzResponseTypeToProcessAuthz # Description: Response type used to process device authz requests Required: No Default value: None deviceAuthzTokenPollInterval # Description: Default interval returned to the client to process device token requests Required: No Default value: None disableAuthnForMaxAgeZero # Description: Boolean value specifying whether to disable authentication when max_age=0 Required: No Default value: false disableJdkLogger # Description: Choose whether to disable JDK loggers Required: No Default value: true disablePromptConsent # Description: Boolean value specifying whether to disable prompt=consent Required: No Default value: false disablePromptLogin # Description: Boolean value specifying whether to disable prompt=login Required: No Default value: false disableU2fEndpoint # Description: Choose whether to disable U2F endpoints Required: No Default value: false discoveryAllowedKeys # Description: List of configuration response claim allowed to be displayed in discovery endpoint Required: No Default value: None discoveryCacheLifetimeInMinutes # Description: Lifetime of discovery cache Required: No Default value: 60 discoveryDenyKeys # Description: List of configuration response claims which must not be displayed in discovery endpoint response Required: No Default value: None displayValuesSupported # Description: A list of the display parameter values that the OpenID Provider supports Required: No Default value: None dnName # Description: DN of certificate issuer Required: No Default value: None dpopJtiCacheTime # Description: Demonstration of Proof-of-Possession (DPoP) cache time Required: No Default value: 3600 dpopNonceCacheTime # Description: Demonstration of Proof-of-Possession (DPoP) nonce cache time Required: No Default value: 3600 dpopSigningAlgValuesSupported # Description: Demonstration of Proof-of-Possession (DPoP) authorization signing algorithms supported Required: No Default value: None dpopTimeframe # Description: Demonstration of Proof-of-Possession (DPoP) timeout Required: No Default value: 5 dpopUseNonce # Description: Demonstration of Proof-of-Possession (DPoP) use nonce Required: No Default value: false grantTypesSupportedByDynamicRegistration # Description: This list details which OAuth 2.0 grant types can be set up with the client registration API Required: No Default value: None dynamicRegistrationAllowedPasswordGrantScopes # Description: List of grant scopes for dynamic registration Required: No Default value: None dynamicRegistrationCustomAttributes # Description: This list details the custom attributes allowed for dynamic registration Required: No Default value: None dynamicRegistrationCustomObjectClass # Description: LDAP custom object class for dynamic registration Required: No Default value: None dynamicRegistrationDefaultCustomAttributes # Description: This map provides default custom attributes with values for dynamic registration Required: No Default value: None dynamicRegistrationExpirationTime # Description: Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire Required: No Default value: -1 dynamicRegistrationPasswordGrantTypeEnabled # Description: Boolean value specifying whether to enable Password Grant Type during Dynamic Registration Required: No Default value: false dynamicRegistrationPersistClientAuthorizations # Description: Boolean value specifying whether to persist client authorizations Required: No Default value: None dynamicRegistrationScopesParamEnabled # Description: Boolean value specifying whether to enable scopes parameter in dynamic registration Required: No Default value: None enableClientGrantTypeUpdate # Description: Choose if client can update Grant Type values Required: No Default value: None enabledOAuthAuditLogging # Description: enable OAuth Audit Logging Required: No Default value: None endSessionEndpoint # Description: URL at the OP to which an RP can perform a redirect to request that the end user be logged out at the OP Required: No Default value: None endSessionWithAccessToken # Description: Choose whether to accept access tokens to call end_session endpoint Required: No Default value: None errorHandlingMethod # Description: A list of possible error handling methods. Possible values: remote (send error back to RP), internal (show error page) Required: No Default value: remote errorReasonEnabled # Description: Boolean value specifying whether to return detailed reason of the error from AS. Default value is false Required: No Default value: false expirationNotificatorEnabled # Description: Boolean value specifying whether expiration notificator is enabled (used to identify expiration for persistence that support TTL, like Couchbase) Required: No Default value: false expirationNotificatorIntervalInSeconds # Description: The expiration notificator interval in second Required: No Default value: None expirationNotificatorMapSizeLimit # Description: The expiration notificator maximum size limit Required: No Default value: None externalLoggerConfiguration # Description: The path to the external log4j2 logging configuration Required: No Default value: None externalUriWhiteList # Description: This list specifies which external URIs can be called by AS (if empty any URI can be called) Required: No Default value: None fapiCompatibility # Description: Boolean value specifying whether to turn on FAPI compatibility mode. If true AS behaves in more strict mode Required: No Default value: false featureFlags # Description: List of enabled feature flags Required: No Default value: None forceIdTokenHintPresence # Description: Boolean value specifying whether force id_token_hint parameter presence Required: No Default value: false forceOfflineAccessScopeToEnableRefreshToken # Description: Boolean value specifying whether force offline_access scope to enable refresh_token grant type. Default value is true Required: No Default value: true forceSignedRequestObject # Description: Boolean value true indicates that signed request object is mandatory Required: No Default value: false frontChannelLogoutSessionSupported # Description: Choose whether to support front channel session logout Required: No Default value: None grantTypesAndResponseTypesAutofixEnabled # Description: Boolean value specifying whether to Grant types and Response types can be auto fixed Required: No Default value: None grantTypesSupported # Description: This list details which OAuth 2.0 grant types are supported by this OP Required: No Default value: None httpLoggingEnabled # Description: Enable/disable request/response logging filter Required: No Default value: None httpLoggingExcludePaths # Description: This list details the base URIs for which the request/response logging filter will not record activity Required: No Default value: None httpLoggingResponseBodyContent # Description: Defines if Response body will be logged. Default value is false Required: No Default value: false idGenerationEndpoint # Description: ID Generation endpoint URL Required: No Default value: None idTokenEncryptionAlgValuesSupported # Description: A list of the JWE encryption algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None idTokenEncryptionEncValuesSupported # Description: A list of the JWE encryption algorithms (enc values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None idTokenFilterClaimsBasedOnAccessToken # Description: Boolean value specifying whether idToken filters claims based on accessToken Required: No Default value: None idTokenLifetime # Description: The lifetime of the ID Token Required: No Default value: None idTokenSigningAlgValuesSupported # Description: A list of the JWS signing algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None idTokenTokenBindingCnfValuesSupported # Description: Array containing a list of the JWT Confirmation Method member names supported by the OP for Token Binding of ID Tokens. The presence of this parameter indicates that the OpenID Provider supports Token Binding of ID Tokens. If omitted, the default is that the OpenID Provider does not support Token Binding of ID Tokens Required: No Default value: None imgLocation # Description: The location for image files Required: No Default value: None includeSidInResponse # Description: Boolean value specifying whether to include sessionId in response Required: No Default value: false introspectionAccessTokenMustHaveIntrospectionScope # Description: If True, rejects introspection requests if access_token does not have the 'introspection' scope in its authorization header. Comparing to 'uma_protection', 'introspection' scope is not allowed for dynamic registration' Required: No Default value: false introspectionAccessTokenMustHaveUmaProtectionScope # Description: If True, rejects introspection requests if access_token does not have the uma_protection scope in its authorization header Required: No Default value: false introspectionEndpoint # Description: Introspection endpoint URL Required: No Default value: None introspectionResponseScopesBackwardCompatibility # Description: Boolean value specifying introspection response backward compatibility mode Required: No Default value: false introspectionScriptBackwardCompatibility # Description: Boolean value specifying whether switch off client's introspection scripts (true value) and run all scripts that exists on server. Default value is false Required: No Default value: false introspectionSkipAuthorization # Description: Specifies if authorization to be skipped for introspection Required: No Default value: None invalidateSessionCookiesAfterAuthorizationFlow # Description: Boolean value to specify whether to invalidate session_id and consent_session_id cookies right after successful or unsuccessful authorization Required: No Default value: false issuer # Description: URL using the https scheme that OP asserts as Issuer identifier Required: No Default value: None jansId # Description: URL for the Inum generator Service Required: No Default value: None jansOpenIdConnectVersion # Description: OpenID Connect Version Required: No Default value: None jmsBrokerURISet # Description: JMS Broker URI Set Required: No Default value: None jmsPassword # Description: JMS Password Required: No Default value: None jmsUserName # Description: JMS UserName Required: No Default value: None jsLocation # Description: The location for JavaScript files Required: No Default value: None jwksAlgorithmsSupported # Description: A list of algorithms that will be used in JWKS endpoint Required: No Default value: None jwksUri # Description: URL of the OP's JSON Web Key Set (JWK) document. This contains the signing key(s) the RP uses to validate signatures from the OP Required: No Default value: None keepAuthenticatorAttributesOnAcrChange # Description: Boolean value specifying whether to keep authenticator attributes on ACR change Required: No Default value: false keyAlgsAllowedForGeneration # Description: List of algorithm allowed to be used for key generation Required: No Default value: None keyRegenerationEnabled # Description: Boolean value specifying whether to regenerate keys Required: No Default value: None keyRegenerationInterval # Description: The interval for key regeneration in hours Required: No Default value: None keySelectionStrategy # Description: Key Selection Strategy : OLDER, NEWER, FIRST Required: No Default value: OLDER keySignWithSameKeyButDiffAlg # Description: Specifies if signing to be done with same key but apply different algorithms Required: No Default value: None keyStoreFile # Description: The Key Store File (JKS) Required: No Default value: None keyStoreSecret # Description: The Key Store password Required: No Default value: None legacyIdTokenClaims # Description: Choose whether to include claims in ID tokens Required: No Default value: None logClientIdOnClientAuthentication # Description: Choose if application should log the Client ID on client authentication Required: No Default value: None logClientNameOnClientAuthentication # Description: Choose if application should log the Client Name on client authentication Required: No Default value: None loggingLayout # Description: Logging layout used for Jans Authorization Server loggers Required: No Default value: None loggingLevel # Description: Specify the logging level of loggers Required: No Default value: None logNotFoundEntityAsError # Description: Boolean value specifying whether to log not_found entity exception as error or as trace. Default value is false (trace). Required: No Default value: None metricReporterInterval # Description: The interval for metric reporter in seconds Required: No Default value: None metricReporterKeepDataDays # Description: The days to keep metric reported data Required: No Default value: None mtlsAuthorizationEndpoint # Description: URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Endpoint Required: No Default value: None mtlsCheckSessionIFrame # Description: URL for Mutual TLS (mTLS) IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Required: No Default value: None mtlsClientInfoEndpoint # Description: URL for Mutual TLS (mTLS) Client Info endpoint Required: No Default value: None mtlsDeviceAuthzEndpoint # Description: Mutual TLS (mTLS) device authorization endpoint URL Required: No Default value: None mtlsEndSessionEndpoint # Description: URL for Mutual TLS (mTLS) to which an RP can perform a redirect to request that the end user be logged out at the OP Required: No Default value: None mtlsIdGenerationEndpoint # Description: Mutual TLS (mTLS) ID generation endpoint URL Required: No Default value: None mtlsIntrospectionEndpoint # Description: Mutual TLS (mTLS) introspection endpoint URL Required: No Default value: None mtlsJwksUri # Description: URL for Mutual TLS (mTLS) of the OP's JSON Web Key Set (JWK) document Required: No Default value: None mtlsParEndpoint # Description: Mutual TLS (mTLS) Pushed Authorization Requests(PAR) endpoint URL Required: No Default value: None mtlsRegistrationEndpoint # Description: Mutual TLS (mTLS) registration endpoint URL Required: No Default value: None mtlsTokenEndpoint # Description: URL for Mutual TLS (mTLS) Authorization token Endpoint Required: No Default value: None mtlsTokenRevocationEndpoint # Description: URL for Mutual TLS (mTLS) Authorization token revocation endpoint Required: No Default value: None mtlsUserInfoEndpoint # Description: Mutual TLS (mTLS) user info endpoint URL Required: No Default value: None openIdConfigurationEndpoint # Description: URL for the Open ID Connect Configuration Endpoint Required: No Default value: None openIdDiscoveryEndpoint # Description: Discovery endpoint URL Required: No Default value: None openidScopeBackwardCompatibility # Description: Set to false to only allow token endpoint request for openid scope with grant type equals to authorization_code, restrict access to userinfo to scope openid and only return id_token if scope contains openid Required: No Default value: false openidSubAttribute # Description: Specifies which LDAP attribute is used for the subject identifier claim Required: No Default value: None opPolicyUri # Description: URL that the OpenID Provider provides to the person registering the Client to read about the OP's requirements on how the Relying Party can use the data provided by the OP Required: No Default value: None opTosUri # Description: URL that the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service Required: No Default value: None pairwiseCalculationKey # Description: Key to calculate algorithmic pairwise IDs Required: No Default value: None pairwiseCalculationSalt # Description: Salt to calculate algorithmic pairwise IDs Required: No Default value: None pairwiseIdType # Description: the pairwise ID type Required: No Default value: None parEndpoint # Description: URL for Pushed Authorisation Request (PAR) Endpoint Required: No Default value: None persistIdToken # Description: Specifies whether to persist id_token (otherwise saves into cache) Required: No Default value: false persistRefreshToken # Description: Specifies whether to persist refresh_token (otherwise saves into cache) Required: No Default value: true personCustomObjectClassList # Description: This list details LDAP custom object classes for dynamic person enrollment Required: No Default value: None publicSubjectIdentifierPerClientEnabled # Description: Specifies whether public subject identifier is allowed per client Required: No Default value: false redirectUrisRegexEnabled # Description: Enable/Disable redirect uris validation using regular expression Required: No Default value: false refreshTokenExtendLifetimeOnRotation # Description: Boolean value specifying whether to extend refresh tokens on rotation Required: No Default value: false refreshTokenLifetime # Description: The lifetime of the Refresh Token Required: No Default value: None registrationEndpoint # Description: Registration endpoint URL Required: No Default value: None rejectEndSessionIfIdTokenExpired # Description: default value false. If true and id_token is not found in db, request is rejected Required: No Default value: false rejectJwtWithNoneAlg # Description: Boolean value specifying whether reject JWT requested or validated with algorithm None. Default value is true Required: No Default value: true removeRefreshTokensForClientOnLogout # Description: Boolean value specifying whether to remove Refresh Tokens on logout. Default value is true Required: No Default value: true requestObjectEncryptionAlgValuesSupported # Description: A list of the JWE encryption algorithms (alg values) supported by the OP for Request Objects Required: No Default value: None requestObjectEncryptionEncValuesSupported # Description: A list of the JWE encryption algorithms (enc values) supported by the OP for Request Objects Required: No Default value: None requestObjectSigningAlgValuesSupported # Description: A list of the JWS signing algorithms (alg values) supported by the OP for Request Objects Required: No Default value: None requestParameterSupported # Description: Boolean value specifying whether the OP supports use of the request parameter Required: No Default value: None requestUriBlockList # Description: Block list for requestUri that can come to Authorization Endpoint (e.g. localhost) Required: No Default value: None requestUriHashVerificationEnabled # Description: Boolean value specifying whether the OP supports use of the request_uri hash verification Required: No Default value: None requestUriParameterSupported # Description: Boolean value specifying whether the OP supports use of the request_uri parameter Required: No Default value: None requirePar # Description: Boolean value to indicate of Pushed Authorisation Request(PAR)is required Required: No Default value: false requirePkce # Description: Boolean value true check for Proof Key for Code Exchange (PKCE) Required: No Default value: false requireRequestObjectEncryption # Description: Boolean value true encrypts request object Required: No Default value: false requireRequestUriRegistration # Description: Boolean value specifying whether the OP requires any request_uri values used to be pre-registered using the request_uris registration parameter Required: No Default value: None responseModesSupported # Description: This list details which OAuth 2.0 response modes are supported by this OP Required: No Default value: None responseTypesSupported # Description: This list details which OAuth 2.0 response_type values are supported by this OP. Required: No Default value: By default, every combination of code, token and id_token is supported. returnClientSecretOnRead # Description: Boolean value specifying whether a client_secret is returned on client GET or PUT. Set to true by default which means to return secret Required: No Default value: false returnDeviceSecretFromAuthzEndpoint # Description: Required: No Default value: false rotateClientRegistrationAccessTokenOnUsage # Description: Boolean value specifying whether to rotate client registration access token after each usage Required: No Default value: false rotateDeviceSecret # Description: Required: No Default value: false sectorIdentifierCacheLifetimeInMinutes # Description: Sector Identifier cache lifetime in minutes Required: No Default value: 1440 serverSessionIdLifetime # Description: Dedicated property to control lifetime of the server side OP session object in seconds. Overrides sessionIdLifetime. By default value is 0, so object lifetime equals sessionIdLifetime (which sets both cookie and object expiration). It can be useful if goal is to keep different values for client cookie and server object Required: No Default value: None serviceDocumentation # Description: URL of a page containing human-readable information that developers might want or need to know when using the OpenID Provider Required: No Default value: None sessionIdLifetime # Description: The lifetime of session id in seconds. If 0 or -1 then expiration is not set. session_id cookie expires when browser session ends Required: No Default value: None sessionIdPersistInCache # Description: Boolean value specifying whether to persist session_id in cache Required: No Default value: false sessionIdPersistOnPromptNone # Description: Boolean value specifying whether to persist session ID on prompt none Required: No Default value: None sessionIdRequestParameterEnabled # Description: Boolean value specifying whether to enable session_id HTTP request parameter Required: No Default value: false sessionIdUnauthenticatedUnusedLifetime # Description: The lifetime for unused unauthenticated session states Required: No Default value: None sessionIdUnusedLifetime # Description: The lifetime for unused session states Required: No Default value: None shareSubjectIdBetweenClientsWithSameSectorId # Description: When true, clients with the same Sector ID also share the same Subject ID Required: No Default value: false skipAuthenticationFilterOptionsMethod # Description: Force Authentication Filtker to process OPTIONS request Required: No Default value: true skipAuthorizationForOpenIdScopeAndPairwiseId # Description: Choose whether to skip authorization if a client has an OpenId scope and a pairwise ID Required: No Default value: false skipRefreshTokenDuringRefreshing # Description: Boolean value specifying whether to skip refreshing tokens on refreshing Required: No Default value: false softwareStatementValidationClaimName # Description: Validation claim name for software statement Required: No Default value: None softwareStatementValidationType # Description: Validation type used for software statement Required: No Default value: None spontaneousScopeLifetime # Description: The lifetime of spontaneous scope in seconds Required: No Default value: None ssaConfiguration # Description: SSA Configuration Required: No Default value: None statAuthorizationScope # Description: Scope required for Statistical Authorization Required: No Default value: None staticDecryptionKid # Description: Specifies static decryption Kid Required: No Default value: None staticKid # Description: Specifies static Kid Required: No Default value: None statTimerIntervalInSeconds # Description: Statistical data capture time interval Required: No Default value: None subjectIdentifiersPerClientSupported # Description: A list of the subject identifiers supported per client Required: No Default value: None subjectTypesSupported # Description: This list details which Subject Identifier types that the OP supports. Valid types include pairwise and public. Required: No Default value: None tokenEndpoint # Description: The token endpoint URL Required: No Default value: None tokenEndpointAuthMethodsSupported # Description: A list of Client Authentication methods supported by this Token Endpoint Required: No Default value: None tokenEndpointAuthSigningAlgValuesSupported # Description: A list of the JWS signing algorithms (alg values) supported by the Token Endpoint for the signature on the JWT used to authenticate the Client at the Token Endpoint for the private_key_jwt and client_secret_jwt authentication methods Required: No Default value: None tokenRevocationEndpoint # Description: The URL for the access_token or refresh_token revocation endpoint Required: No Default value: None trustedClientEnabled # Description: Boolean value specifying whether a client is trusted and no authorization is required Required: No Default value: None trustedSsaIssuers # Description: List of trusted SSA issuers with configuration (e.g. automatically granted scopes). Required: No Default value: None uiLocalesSupported # Description: This list details the languages and scripts supported for the user interface Required: No Default value: None umaAddScopesAutomatically # Description: Add UMA scopes automatically if it is not registered yet Required: No Default value: None umaConfigurationEndpoint # Description: UMA Configuration endpoint URL Required: No Default value: None umaGrantAccessIfNoPolicies # Description: Specify whether to grant access to resources if there is no any policies associated with scopes Required: No Default value: false umaPctLifetime # Description: UMA PCT lifetime Required: No Default value: None umaResourceLifetime # Description: UMA Resource lifetime Required: No Default value: None umaRestrictResourceToAssociatedClient # Description: Restrict access to resource by associated client Required: No Default value: false umaRptAsJwt # Description: Issue RPT as JWT or as random string Required: No Default value: false umaRptLifetime # Description: UMA RPT lifetime Required: No Default value: None umaTicketLifetime # Description: UMA ticket lifetime Required: No Default value: None umaValidateClaimToken # Description: Validate claim_token as id_token assuming it is issued by local id Required: No Default value: false updateClientAccessTime # Description: Choose if application should update oxLastAccessTime/oxLastLogonTime attributes upon client authentication Required: No Default value: None updateUserLastLogonTime # Description: Choose if application should update oxLastLogonTime attribute upon user authentication Required: No Default value: None useHighestLevelScriptIfAcrScriptNotFound # Description: Enable/Disable usage of highest level script in case ACR script does not exist Required: No Default value: false useLocalCache # Description: Cache in local memory cache attributes, scopes, clients and organization entry with expiration 60 seconds Required: No Default value: false useNestedJwtDuringEncryption # Description: Boolean value specifying whether to use nested Jwt during encryption Required: No Default value: true userInfoEncryptionAlgValuesSupported # Description: This JSON Array lists which JWS encryption algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None userInfoEncryptionEncValuesSupported # Description: This JSON Array lists which JWS encryption algorithms (enc values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None userInfoEndpoint # Description: The User Info endpoint URL Required: No Default value: None userInfoSigningAlgValuesSupported # Description: This JSON Array lists which JWS signing algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None webKeysStorage # Description: Web Key Storage Type Required: No Default value: None", "title": "Auth Server"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#janssen-auth-server-configuration-properties", "text": "Property Name Description accessTokenLifetime The lifetime of the short lived Access Token Details accessTokenSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for the access token to encode the Claims in a JWT Details activeSessionAuthorizationScope Authorization Scope for active session Details agamaConfiguration Engine Config which offers an alternative way to build authentication flows in Janssen server Details allowAllValueForRevokeEndpoint Boolean value true allow all value for revoke endpoint Details allowBlankValuesInDiscoveryResponse Boolean value specifying whether to allow blank values in discovery response Details allowEndSessionWithUnmatchedSid default value false. If true, sid check will be skipped Details allowIdTokenWithoutImplicitGrantType Specifies if a token without implicit grant types is allowed Details allowPostLogoutRedirectWithoutValidation Allows post-logout redirect without validation for the End Session endpoint (still AS validates it against clientWhiteList url pattern property) Details allowSpontaneousScopes Specifies whether to allow spontaneous scopes Details authenticationFilters This list details filters for user authentication Details authenticationFiltersEnabled Boolean value specifying whether to enable user authentication filters Details authenticationProtectionConfiguration Authentication Brute Force Protection Configuration Details authorizationCodeLifetime The lifetime of the Authorization Code Details authorizationEncryptionAlgValuesSupported List of authorization encryption algorithms supported by this OP Details authorizationEncryptionEncValuesSupported A list of the authorization encryption algorithms supported Details authorizationEndpoint The authorization endpoint URL Details authorizationRequestCustomAllowedParameters This list details the allowed custom parameters for authorization requests Details authorizationSigningAlgValuesSupported List of authorization signing algorithms supported by this OP Details backchannelAuthenticationEndpoint Backchannel Authentication Endpoint Details backchannelAuthenticationRequestSigningAlgValuesSupported Backchannel Authentication Request Signing Alg Values Supported Details backchannelAuthenticationResponseExpiresIn Backchannel Authentication Response Expires In Details backchannelAuthenticationResponseInterval Backchannel Authentication Response Interval Details backchannelBindingMessagePattern Backchannel Binding Message Pattern Details backchannelClientId Backchannel Client Id Details backchannelDeviceRegistrationEndpoint Backchannel Device Registration Endpoint Details backchannelLoginHintClaims Backchannel Login Hint Claims Details backchannelRedirectUri Backchannel Redirect Uri Details backchannelRequestsProcessorJobChunkSize Each backchannel request processor iteration fetches chunk of data to be processed Details backchannelRequestsProcessorJobIntervalSec Specifies the allowable elapsed time in seconds backchannel request processor executes Details backchannelTokenDeliveryModesSupported Backchannel Token Delivery Modes Supported Details backchannelUserCodeParameterSupported Backchannel User Code Parameter Supported Details baseEndpoint The base URL for endpoints Details blockWebviewAuthorizationEnabled Enable/Disable block authorizations that originate from Webview (Mobile apps). Details changeSessionIdOnAuthentication Boolean value specifying whether change session_id on authentication. Default value is true Details checkSessionIFrame URL for an OP IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Details checkUserPresenceOnRefreshToken Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check. Details cibaEndUserNotificationConfig CIBA End User Notification Config Details cibaGrantLifeExtraTimeSec Specifies the CIBA Grant life extra time in seconds Details cibaMaxExpirationTimeAllowedSec Specifies the CIBA token expiration time in seconds Details claimsLocalesSupported This list details the languages and scripts supported for values in the claims being returned Details claimsParameterSupported Specifies whether the OP supports use of the claims parameter Details claimTypesSupported A list of the Claim Types that the OpenID Provider supports Details cleanServiceBatchChunkSize Clean service chunk size which is used during clean up Details cleanServiceInterval Time interval for the Clean Service in seconds Details clientAuthenticationFilters This list details filters for client authentication Details clientAuthenticationFiltersEnabled Boolean value specifying whether to enable client authentication filters Details clientBlackList This list specified which client redirection URIs are black-listed Details clientInfoEndpoint The Client Info endpoint URL Details clientRegDefaultToCodeFlowWithRefresh Boolean value specifying whether to add Authorization Code Flow with Refresh grant during client registratio Details clientWhiteList This list specifies which client redirection URIs are white-listed Details configurationUpdateInterval The interval for configuration update in seconds Details consentGatheringScriptBackwardCompatibility Boolean value specifying whether to turn on Consent Gathering Script backward compatibility mode. If true AS will pick up script with higher level globally. If false (default) AS will pick up script based on client configuration Details cookieDomain Sets cookie domain for all cookies created by OP Details corsConfigurationFilters This list specifies the CORS configuration filters Details cssLocation The location for CSS files Details customHeadersWithAuthorizationResponse Choose whether to enable the custom response header parameter to return custom headers with the authorization response Details dateFormatterPatterns List of key value date formatters, e.g. 'userinfo: 'yyyy-MM-dd', etc. Details dcrAuthorizationWithClientCredentials Boolean value indicating if DCR authorization to be performed using client credentials Details dcrAuthorizationWithMTLS Boolean value indicating if DCR authorization allowed with MTLS Details dcrForbidExpirationTimeInRequest Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration. Details dcrSignatureValidationEnabled Boolean value enables DCR signature validation. Default is false Details dcrSignatureValidationJwks Specifies JWKS for all DCR's validations Details dcrSignatureValidationJwksUri Specifies JWKS URI for all DCR's validations Details dcrSignatureValidationSharedSecret Specifies shared secret for Dynamic Client Registration Details dcrSignatureValidationSoftwareStatementJwksClaim Specifies claim name inside software statement. Value of claim should point to inlined JWKS Details dcrSignatureValidationSoftwareStatementJwksURIClaim Specifies claim name inside software statement. Value of claim should point to JWKS URI Details dcrSsaValidationConfigs DCR SSA Validation configurations used to perform validation of SSA or DCR Details defaultSignatureAlgorithm The default signature algorithm to sign ID Tokens Details defaultSubjectType The default subject type used for dynamic client registration Details deviceAuthzAcr Device authz acr Details deviceAuthzEndpoint URL for the Device Authorization Details deviceAuthzRequestExpiresIn Expiration time given for device authorization requests Details deviceAuthzResponseTypeToProcessAuthz Response type used to process device authz requests Details deviceAuthzTokenPollInterval Default interval returned to the client to process device token requests Details disableAuthnForMaxAgeZero Boolean value specifying whether to disable authentication when max_age=0 Details disableJdkLogger Choose whether to disable JDK loggers Details disablePromptConsent Boolean value specifying whether to disable prompt=consent Details disablePromptLogin Boolean value specifying whether to disable prompt=login Details disableU2fEndpoint Choose whether to disable U2F endpoints Details discoveryAllowedKeys List of configuration response claim allowed to be displayed in discovery endpoint Details discoveryCacheLifetimeInMinutes Lifetime of discovery cache Details discoveryDenyKeys List of configuration response claims which must not be displayed in discovery endpoint response Details displayValuesSupported A list of the display parameter values that the OpenID Provider supports Details dnName DN of certificate issuer Details dpopJtiCacheTime Demonstration of Proof-of-Possession (DPoP) cache time Details dpopNonceCacheTime Demonstration of Proof-of-Possession (DPoP) nonce cache time Details dpopSigningAlgValuesSupported Demonstration of Proof-of-Possession (DPoP) authorization signing algorithms supported Details dpopTimeframe Demonstration of Proof-of-Possession (DPoP) timeout Details dpopUseNonce Demonstration of Proof-of-Possession (DPoP) use nonce Details grantTypesSupportedByDynamicRegistration This list details which OAuth 2.0 grant types can be set up with the client registration API Details dynamicRegistrationAllowedPasswordGrantScopes List of grant scopes for dynamic registration Details dynamicRegistrationCustomAttributes This list details the custom attributes allowed for dynamic registration Details dynamicRegistrationCustomObjectClass LDAP custom object class for dynamic registration Details dynamicRegistrationDefaultCustomAttributes This map provides default custom attributes with values for dynamic registration Details dynamicRegistrationExpirationTime Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire Details dynamicRegistrationPasswordGrantTypeEnabled Boolean value specifying whether to enable Password Grant Type during Dynamic Registration Details dynamicRegistrationPersistClientAuthorizations Boolean value specifying whether to persist client authorizations Details dynamicRegistrationScopesParamEnabled Boolean value specifying whether to enable scopes parameter in dynamic registration Details enableClientGrantTypeUpdate Choose if client can update Grant Type values Details enabledOAuthAuditLogging enable OAuth Audit Logging Details endSessionEndpoint URL at the OP to which an RP can perform a redirect to request that the end user be logged out at the OP Details endSessionWithAccessToken Choose whether to accept access tokens to call end_session endpoint Details errorHandlingMethod A list of possible error handling methods. Possible values: remote (send error back to RP), internal (show error page) Details errorReasonEnabled Boolean value specifying whether to return detailed reason of the error from AS. Default value is false Details expirationNotificatorEnabled Boolean value specifying whether expiration notificator is enabled (used to identify expiration for persistence that support TTL, like Couchbase) Details expirationNotificatorIntervalInSeconds The expiration notificator interval in second Details expirationNotificatorMapSizeLimit The expiration notificator maximum size limit Details externalLoggerConfiguration The path to the external log4j2 logging configuration Details externalUriWhiteList This list specifies which external URIs can be called by AS (if empty any URI can be called) Details fapiCompatibility Boolean value specifying whether to turn on FAPI compatibility mode. If true AS behaves in more strict mode Details featureFlags List of enabled feature flags Details forceIdTokenHintPresence Boolean value specifying whether force id_token_hint parameter presence Details forceOfflineAccessScopeToEnableRefreshToken Boolean value specifying whether force offline_access scope to enable refresh_token grant type. Default value is true Details forceSignedRequestObject Boolean value true indicates that signed request object is mandatory Details frontChannelLogoutSessionSupported Choose whether to support front channel session logout Details grantTypesAndResponseTypesAutofixEnabled Boolean value specifying whether to Grant types and Response types can be auto fixed Details grantTypesSupported This list details which OAuth 2.0 grant types are supported by this OP Details httpLoggingEnabled Enable/disable request/response logging filter Details httpLoggingExcludePaths This list details the base URIs for which the request/response logging filter will not record activity Details httpLoggingResponseBodyContent Defines if Response body will be logged. Default value is false Details idGenerationEndpoint ID Generation endpoint URL Details idTokenEncryptionAlgValuesSupported A list of the JWE encryption algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenEncryptionEncValuesSupported A list of the JWE encryption algorithms (enc values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenFilterClaimsBasedOnAccessToken Boolean value specifying whether idToken filters claims based on accessToken Details idTokenLifetime The lifetime of the ID Token Details idTokenSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenTokenBindingCnfValuesSupported Array containing a list of the JWT Confirmation Method member names supported by the OP for Token Binding of ID Tokens. The presence of this parameter indicates that the OpenID Provider supports Token Binding of ID Tokens. If omitted, the default is that the OpenID Provider does not support Token Binding of ID Tokens Details imgLocation The location for image files Details includeSidInResponse Boolean value specifying whether to include sessionId in response Details introspectionAccessTokenMustHaveIntrospectionScope If True, rejects introspection requests if access_token does not have the 'introspection' scope in its authorization header. Comparing to 'uma_protection', 'introspection' scope is not allowed for dynamic registration' Details introspectionAccessTokenMustHaveUmaProtectionScope If True, rejects introspection requests if access_token does not have the uma_protection scope in its authorization header Details introspectionEndpoint Introspection endpoint URL Details introspectionResponseScopesBackwardCompatibility Boolean value specifying introspection response backward compatibility mode Details introspectionScriptBackwardCompatibility Boolean value specifying whether switch off client's introspection scripts (true value) and run all scripts that exists on server. Default value is false Details introspectionSkipAuthorization Specifies if authorization to be skipped for introspection Details invalidateSessionCookiesAfterAuthorizationFlow Boolean value to specify whether to invalidate session_id and consent_session_id cookies right after successful or unsuccessful authorization Details issuer URL using the https scheme that OP asserts as Issuer identifier Details jansId URL for the Inum generator Service Details jansOpenIdConnectVersion OpenID Connect Version Details jmsBrokerURISet JMS Broker URI Set Details jmsPassword JMS Password Details jmsUserName JMS UserName Details jsLocation The location for JavaScript files Details jwksAlgorithmsSupported A list of algorithms that will be used in JWKS endpoint Details jwksUri URL of the OP's JSON Web Key Set (JWK) document. This contains the signing key(s) the RP uses to validate signatures from the OP Details keepAuthenticatorAttributesOnAcrChange Boolean value specifying whether to keep authenticator attributes on ACR change Details keyAlgsAllowedForGeneration List of algorithm allowed to be used for key generation Details keyRegenerationEnabled Boolean value specifying whether to regenerate keys Details keyRegenerationInterval The interval for key regeneration in hours Details keySelectionStrategy Key Selection Strategy : OLDER, NEWER, FIRST Details keySignWithSameKeyButDiffAlg Specifies if signing to be done with same key but apply different algorithms Details keyStoreFile The Key Store File (JKS) Details keyStoreSecret The Key Store password Details legacyIdTokenClaims Choose whether to include claims in ID tokens Details logClientIdOnClientAuthentication Choose if application should log the Client ID on client authentication Details logClientNameOnClientAuthentication Choose if application should log the Client Name on client authentication Details loggingLayout Logging layout used for Jans Authorization Server loggers Details loggingLevel Specify the logging level of loggers Details logNotFoundEntityAsError Boolean value specifying whether to log not_found entity exception as error or as trace. Default value is false (trace). Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep metric reported data Details mtlsAuthorizationEndpoint URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Endpoint Details mtlsCheckSessionIFrame URL for Mutual TLS (mTLS) IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Details mtlsClientInfoEndpoint URL for Mutual TLS (mTLS) Client Info endpoint Details mtlsDeviceAuthzEndpoint Mutual TLS (mTLS) device authorization endpoint URL Details mtlsEndSessionEndpoint URL for Mutual TLS (mTLS) to which an RP can perform a redirect to request that the end user be logged out at the OP Details mtlsIdGenerationEndpoint Mutual TLS (mTLS) ID generation endpoint URL Details mtlsIntrospectionEndpoint Mutual TLS (mTLS) introspection endpoint URL Details mtlsJwksUri URL for Mutual TLS (mTLS) of the OP's JSON Web Key Set (JWK) document Details mtlsParEndpoint Mutual TLS (mTLS) Pushed Authorization Requests(PAR) endpoint URL Details mtlsRegistrationEndpoint Mutual TLS (mTLS) registration endpoint URL Details mtlsTokenEndpoint URL for Mutual TLS (mTLS) Authorization token Endpoint Details mtlsTokenRevocationEndpoint URL for Mutual TLS (mTLS) Authorization token revocation endpoint Details mtlsUserInfoEndpoint Mutual TLS (mTLS) user info endpoint URL Details openIdConfigurationEndpoint URL for the Open ID Connect Configuration Endpoint Details openIdDiscoveryEndpoint Discovery endpoint URL Details openidScopeBackwardCompatibility Set to false to only allow token endpoint request for openid scope with grant type equals to authorization_code, restrict access to userinfo to scope openid and only return id_token if scope contains openid Details openidSubAttribute Specifies which LDAP attribute is used for the subject identifier claim Details opPolicyUri URL that the OpenID Provider provides to the person registering the Client to read about the OP's requirements on how the Relying Party can use the data provided by the OP Details opTosUri URL that the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service Details pairwiseCalculationKey Key to calculate algorithmic pairwise IDs Details pairwiseCalculationSalt Salt to calculate algorithmic pairwise IDs Details pairwiseIdType the pairwise ID type Details parEndpoint URL for Pushed Authorisation Request (PAR) Endpoint Details persistIdToken Specifies whether to persist id_token (otherwise saves into cache) Details persistRefreshToken Specifies whether to persist refresh_token (otherwise saves into cache) Details personCustomObjectClassList This list details LDAP custom object classes for dynamic person enrollment Details publicSubjectIdentifierPerClientEnabled Specifies whether public subject identifier is allowed per client Details redirectUrisRegexEnabled Enable/Disable redirect uris validation using regular expression Details refreshTokenExtendLifetimeOnRotation Boolean value specifying whether to extend refresh tokens on rotation Details refreshTokenLifetime The lifetime of the Refresh Token Details registrationEndpoint Registration endpoint URL Details rejectEndSessionIfIdTokenExpired default value false. If true and id_token is not found in db, request is rejected Details rejectJwtWithNoneAlg Boolean value specifying whether reject JWT requested or validated with algorithm None. Default value is true Details removeRefreshTokensForClientOnLogout Boolean value specifying whether to remove Refresh Tokens on logout. Default value is true Details requestObjectEncryptionAlgValuesSupported A list of the JWE encryption algorithms (alg values) supported by the OP for Request Objects Details requestObjectEncryptionEncValuesSupported A list of the JWE encryption algorithms (enc values) supported by the OP for Request Objects Details requestObjectSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for Request Objects Details requestParameterSupported Boolean value specifying whether the OP supports use of the request parameter Details requestUriBlockList Block list for requestUri that can come to Authorization Endpoint (e.g. localhost) Details requestUriHashVerificationEnabled Boolean value specifying whether the OP supports use of the request_uri hash verification Details requestUriParameterSupported Boolean value specifying whether the OP supports use of the request_uri parameter Details requirePar Boolean value to indicate of Pushed Authorisation Request(PAR)is required Details requirePkce Boolean value true check for Proof Key for Code Exchange (PKCE) Details requireRequestObjectEncryption Boolean value true encrypts request object Details requireRequestUriRegistration Boolean value specifying whether the OP requires any request_uri values used to be pre-registered using the request_uris registration parameter Details responseModesSupported This list details which OAuth 2.0 response modes are supported by this OP Details responseTypesSupported This list details which OAuth 2.0 response_type values are supported by this OP. Details returnClientSecretOnRead Boolean value specifying whether a client_secret is returned on client GET or PUT. Set to true by default which means to return secret Details returnDeviceSecretFromAuthzEndpoint Details rotateClientRegistrationAccessTokenOnUsage Boolean value specifying whether to rotate client registration access token after each usage Details rotateDeviceSecret Details sectorIdentifierCacheLifetimeInMinutes Sector Identifier cache lifetime in minutes Details serverSessionIdLifetime Dedicated property to control lifetime of the server side OP session object in seconds. Overrides sessionIdLifetime. By default value is 0, so object lifetime equals sessionIdLifetime (which sets both cookie and object expiration). It can be useful if goal is to keep different values for client cookie and server object Details serviceDocumentation URL of a page containing human-readable information that developers might want or need to know when using the OpenID Provider Details sessionIdLifetime The lifetime of session id in seconds. If 0 or -1 then expiration is not set. session_id cookie expires when browser session ends Details sessionIdPersistInCache Boolean value specifying whether to persist session_id in cache Details sessionIdPersistOnPromptNone Boolean value specifying whether to persist session ID on prompt none Details sessionIdRequestParameterEnabled Boolean value specifying whether to enable session_id HTTP request parameter Details sessionIdUnauthenticatedUnusedLifetime The lifetime for unused unauthenticated session states Details sessionIdUnusedLifetime The lifetime for unused session states Details shareSubjectIdBetweenClientsWithSameSectorId When true, clients with the same Sector ID also share the same Subject ID Details skipAuthenticationFilterOptionsMethod Force Authentication Filtker to process OPTIONS request Details skipAuthorizationForOpenIdScopeAndPairwiseId Choose whether to skip authorization if a client has an OpenId scope and a pairwise ID Details skipRefreshTokenDuringRefreshing Boolean value specifying whether to skip refreshing tokens on refreshing Details softwareStatementValidationClaimName Validation claim name for software statement Details softwareStatementValidationType Validation type used for software statement Details spontaneousScopeLifetime The lifetime of spontaneous scope in seconds Details ssaConfiguration SSA Configuration Details statAuthorizationScope Scope required for Statistical Authorization Details staticDecryptionKid Specifies static decryption Kid Details staticKid Specifies static Kid Details statTimerIntervalInSeconds Statistical data capture time interval Details subjectIdentifiersPerClientSupported A list of the subject identifiers supported per client Details subjectTypesSupported This list details which Subject Identifier types that the OP supports. Valid types include pairwise and public. Details tokenEndpoint The token endpoint URL Details tokenEndpointAuthMethodsSupported A list of Client Authentication methods supported by this Token Endpoint Details tokenEndpointAuthSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the Token Endpoint for the signature on the JWT used to authenticate the Client at the Token Endpoint for the private_key_jwt and client_secret_jwt authentication methods Details tokenRevocationEndpoint The URL for the access_token or refresh_token revocation endpoint Details trustedClientEnabled Boolean value specifying whether a client is trusted and no authorization is required Details trustedSsaIssuers List of trusted SSA issuers with configuration (e.g. automatically granted scopes). Details uiLocalesSupported This list details the languages and scripts supported for the user interface Details umaAddScopesAutomatically Add UMA scopes automatically if it is not registered yet Details umaConfigurationEndpoint UMA Configuration endpoint URL Details umaGrantAccessIfNoPolicies Specify whether to grant access to resources if there is no any policies associated with scopes Details umaPctLifetime UMA PCT lifetime Details umaResourceLifetime UMA Resource lifetime Details umaRestrictResourceToAssociatedClient Restrict access to resource by associated client Details umaRptAsJwt Issue RPT as JWT or as random string Details umaRptLifetime UMA RPT lifetime Details umaTicketLifetime UMA ticket lifetime Details umaValidateClaimToken Validate claim_token as id_token assuming it is issued by local id Details updateClientAccessTime Choose if application should update oxLastAccessTime/oxLastLogonTime attributes upon client authentication Details updateUserLastLogonTime Choose if application should update oxLastLogonTime attribute upon user authentication Details useHighestLevelScriptIfAcrScriptNotFound Enable/Disable usage of highest level script in case ACR script does not exist Details useLocalCache Cache in local memory cache attributes, scopes, clients and organization entry with expiration 60 seconds Details useNestedJwtDuringEncryption Boolean value specifying whether to use nested Jwt during encryption Details userInfoEncryptionAlgValuesSupported This JSON Array lists which JWS encryption algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details userInfoEncryptionEncValuesSupported This JSON Array lists which JWS encryption algorithms (enc values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details userInfoEndpoint The User Info endpoint URL Details userInfoSigningAlgValuesSupported This JSON Array lists which JWS signing algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details webKeysStorage Web Key Storage Type Details", "title": "Janssen Auth Server Configuration Properties"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#accesstokenlifetime", "text": "Description: The lifetime of the short lived Access Token Required: No Default value: None", "title": "accessTokenLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#accesstokensigningalgvaluessupported", "text": "Description: A list of the JWS signing algorithms (alg values) supported by the OP for the access token to encode the Claims in a JWT Required: No Default value: None", "title": "accessTokenSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#activesessionauthorizationscope", "text": "Description: Authorization Scope for active session Required: No Default value: None", "title": "activeSessionAuthorizationScope"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#agamaconfiguration", "text": "Description: Engine Config which offers an alternative way to build authentication flows in Janssen server Required: No Default value: None", "title": "agamaConfiguration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowallvalueforrevokeendpoint", "text": "Description: Boolean value true allow all value for revoke endpoint Required: No Default value: false", "title": "allowAllValueForRevokeEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowblankvaluesindiscoveryresponse", "text": "Description: Boolean value specifying whether to allow blank values in discovery response Required: No Default value: false", "title": "allowBlankValuesInDiscoveryResponse"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowendsessionwithunmatchedsid", "text": "Description: default value false. If true, sid check will be skipped Required: No Default value: false", "title": "allowEndSessionWithUnmatchedSid"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowidtokenwithoutimplicitgranttype", "text": "Description: Specifies if a token without implicit grant types is allowed Required: No Default value: None", "title": "allowIdTokenWithoutImplicitGrantType"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowpostlogoutredirectwithoutvalidation", "text": "Description: Allows post-logout redirect without validation for the End Session endpoint (still AS validates it against clientWhiteList url pattern property) Required: No Default value: false", "title": "allowPostLogoutRedirectWithoutValidation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowspontaneousscopes", "text": "Description: Specifies whether to allow spontaneous scopes Required: No Default value: None", "title": "allowSpontaneousScopes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authenticationfilters", "text": "Description: This list details filters for user authentication Required: No Default value: None", "title": "authenticationFilters"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authenticationfiltersenabled", "text": "Description: Boolean value specifying whether to enable user authentication filters Required: No Default value: None", "title": "authenticationFiltersEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authenticationprotectionconfiguration", "text": "Description: Authentication Brute Force Protection Configuration Required: No Default value: None", "title": "authenticationProtectionConfiguration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationcodelifetime", "text": "Description: The lifetime of the Authorization Code Required: No Default value: None", "title": "authorizationCodeLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationencryptionalgvaluessupported", "text": "Description: List of authorization encryption algorithms supported by this OP Required: No Default value: None", "title": "authorizationEncryptionAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationencryptionencvaluessupported", "text": "Description: A list of the authorization encryption algorithms supported Required: No Default value: None", "title": "authorizationEncryptionEncValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationendpoint", "text": "Description: The authorization endpoint URL Required: No Default value: None", "title": "authorizationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationrequestcustomallowedparameters", "text": "Description: This list details the allowed custom parameters for authorization requests Required: No Default value: None", "title": "authorizationRequestCustomAllowedParameters"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationsigningalgvaluessupported", "text": "Description: List of authorization signing algorithms supported by this OP Required: No Default value: None", "title": "authorizationSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelauthenticationendpoint", "text": "Description: Backchannel Authentication Endpoint Required: No Default value: None", "title": "backchannelAuthenticationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelauthenticationrequestsigningalgvaluessupported", "text": "Description: Backchannel Authentication Request Signing Alg Values Supported Required: No Default value: None", "title": "backchannelAuthenticationRequestSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelauthenticationresponseexpiresin", "text": "Description: Backchannel Authentication Response Expires In Required: No Default value: None", "title": "backchannelAuthenticationResponseExpiresIn"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelauthenticationresponseinterval", "text": "Description: Backchannel Authentication Response Interval Required: No Default value: None", "title": "backchannelAuthenticationResponseInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelbindingmessagepattern", "text": "Description: Backchannel Binding Message Pattern Required: No Default value: None", "title": "backchannelBindingMessagePattern"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelclientid", "text": "Description: Backchannel Client Id Required: No Default value: None", "title": "backchannelClientId"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchanneldeviceregistrationendpoint", "text": "Description: Backchannel Device Registration Endpoint Required: No Default value: None", "title": "backchannelDeviceRegistrationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelloginhintclaims", "text": "Description: Backchannel Login Hint Claims Required: No Default value: None", "title": "backchannelLoginHintClaims"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelredirecturi", "text": "Description: Backchannel Redirect Uri Required: No Default value: None", "title": "backchannelRedirectUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelrequestsprocessorjobchunksize", "text": "Description: Each backchannel request processor iteration fetches chunk of data to be processed Required: No Default value: None", "title": "backchannelRequestsProcessorJobChunkSize"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelrequestsprocessorjobintervalsec", "text": "Description: Specifies the allowable elapsed time in seconds backchannel request processor executes Required: No Default value: None", "title": "backchannelRequestsProcessorJobIntervalSec"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchanneltokendeliverymodessupported", "text": "Description: Backchannel Token Delivery Modes Supported Required: No Default value: None", "title": "backchannelTokenDeliveryModesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelusercodeparametersupported", "text": "Description: Backchannel User Code Parameter Supported Required: No Default value: None", "title": "backchannelUserCodeParameterSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#baseendpoint", "text": "Description: The base URL for endpoints Required: No Default value: None", "title": "baseEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#blockwebviewauthorizationenabled", "text": "Description: Enable/Disable block authorizations that originate from Webview (Mobile apps). Required: No Default value: false", "title": "blockWebviewAuthorizationEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#changesessionidonauthentication", "text": "Description: Boolean value specifying whether change session_id on authentication. Default value is true Required: No Default value: true", "title": "changeSessionIdOnAuthentication"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#checksessioniframe", "text": "Description: URL for an OP IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Required: No Default value: None", "title": "checkSessionIFrame"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#checkuserpresenceonrefreshtoken", "text": "Description: Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check. Required: No Default value: false", "title": "checkUserPresenceOnRefreshToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cibaendusernotificationconfig", "text": "Description: CIBA End User Notification Config Required: No Default value: None", "title": "cibaEndUserNotificationConfig"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cibagrantlifeextratimesec", "text": "Description: Specifies the CIBA Grant life extra time in seconds Required: No Default value: None", "title": "cibaGrantLifeExtraTimeSec"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cibamaxexpirationtimeallowedsec", "text": "Description: Specifies the CIBA token expiration time in seconds Required: No Default value: None", "title": "cibaMaxExpirationTimeAllowedSec"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#claimslocalessupported", "text": "Description: This list details the languages and scripts supported for values in the claims being returned Required: No Default value: None", "title": "claimsLocalesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#claimsparametersupported", "text": "Description: Specifies whether the OP supports use of the claims parameter Required: No Default value: None", "title": "claimsParameterSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#claimtypessupported", "text": "Description: A list of the Claim Types that the OpenID Provider supports Required: No Default value: None", "title": "claimTypesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cleanservicebatchchunksize", "text": "Description: Clean service chunk size which is used during clean up Required: No Default value: 100", "title": "cleanServiceBatchChunkSize"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cleanserviceinterval", "text": "Description: Time interval for the Clean Service in seconds Required: No Default value: None", "title": "cleanServiceInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientauthenticationfilters", "text": "Description: This list details filters for client authentication Required: No Default value: None", "title": "clientAuthenticationFilters"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientauthenticationfiltersenabled", "text": "Description: Boolean value specifying whether to enable client authentication filters Required: No Default value: None", "title": "clientAuthenticationFiltersEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientblacklist", "text": "Description: This list specified which client redirection URIs are black-listed Required: No Default value: None", "title": "clientBlackList"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientinfoendpoint", "text": "Description: The Client Info endpoint URL Required: No Default value: None", "title": "clientInfoEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientregdefaulttocodeflowwithrefresh", "text": "Description: Boolean value specifying whether to add Authorization Code Flow with Refresh grant during client registratio Required: No Default value: None", "title": "clientRegDefaultToCodeFlowWithRefresh"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientwhitelist", "text": "Description: This list specifies which client redirection URIs are white-listed Required: No Default value: None", "title": "clientWhiteList"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#configurationupdateinterval", "text": "Description: The interval for configuration update in seconds Required: No Default value: None", "title": "configurationUpdateInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#consentgatheringscriptbackwardcompatibility", "text": "Description: Boolean value specifying whether to turn on Consent Gathering Script backward compatibility mode. If true AS will pick up script with higher level globally. If false (default) AS will pick up script based on client configuration Required: No Default value: false", "title": "consentGatheringScriptBackwardCompatibility"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cookiedomain", "text": "Description: Sets cookie domain for all cookies created by OP Required: No Default value: None", "title": "cookieDomain"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#corsconfigurationfilters", "text": "Description: This list specifies the CORS configuration filters Required: No Default value: None", "title": "corsConfigurationFilters"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#csslocation", "text": "Description: The location for CSS files Required: No Default value: None", "title": "cssLocation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#customheaderswithauthorizationresponse", "text": "Description: Choose whether to enable the custom response header parameter to return custom headers with the authorization response Required: No Default value: None", "title": "customHeadersWithAuthorizationResponse"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dateformatterpatterns", "text": "Description: List of key value date formatters, e.g. 'userinfo: 'yyyy-MM-dd', etc. Required: No Default value: None", "title": "dateFormatterPatterns"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrauthorizationwithclientcredentials", "text": "Description: Boolean value indicating if DCR authorization to be performed using client credentials Required: No Default value: false", "title": "dcrAuthorizationWithClientCredentials"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrauthorizationwithmtls", "text": "Description: Boolean value indicating if DCR authorization allowed with MTLS Required: No Default value: false", "title": "dcrAuthorizationWithMTLS"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrforbidexpirationtimeinrequest", "text": "Description: Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration. Required: No Default value: false", "title": "dcrForbidExpirationTimeInRequest"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationenabled", "text": "Description: Boolean value enables DCR signature validation. Default is false Required: No Default value: false", "title": "dcrSignatureValidationEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationjwks", "text": "Description: Specifies JWKS for all DCR's validations Required: No Default value: None", "title": "dcrSignatureValidationJwks"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationjwksuri", "text": "Description: Specifies JWKS URI for all DCR's validations Required: No Default value: None", "title": "dcrSignatureValidationJwksUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationsharedsecret", "text": "Description: Specifies shared secret for Dynamic Client Registration Required: No Default value: None", "title": "dcrSignatureValidationSharedSecret"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationsoftwarestatementjwksclaim", "text": "Description: Specifies claim name inside software statement. Value of claim should point to inlined JWKS Required: No Default value: None", "title": "dcrSignatureValidationSoftwareStatementJwksClaim"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationsoftwarestatementjwksuriclaim", "text": "Description: Specifies claim name inside software statement. Value of claim should point to JWKS URI Required: No Default value: None", "title": "dcrSignatureValidationSoftwareStatementJwksURIClaim"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrssavalidationconfigs", "text": "Description: DCR SSA Validation configurations used to perform validation of SSA or DCR Required: No Default value: None", "title": "dcrSsaValidationConfigs"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#defaultsignaturealgorithm", "text": "Description: The default signature algorithm to sign ID Tokens Required: No Default value: None", "title": "defaultSignatureAlgorithm"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#defaultsubjecttype", "text": "Description: The default subject type used for dynamic client registration Required: No Default value: None", "title": "defaultSubjectType"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#deviceauthzacr", "text": "Description: Device authz acr Required: No Default value: None", "title": "deviceAuthzAcr"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#deviceauthzendpoint", "text": "Description: URL for the Device Authorization Required: No Default value: None", "title": "deviceAuthzEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#deviceauthzrequestexpiresin", "text": "Description: Expiration time given for device authorization requests Required: No Default value: None", "title": "deviceAuthzRequestExpiresIn"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#deviceauthzresponsetypetoprocessauthz", "text": "Description: Response type used to process device authz requests Required: No Default value: None", "title": "deviceAuthzResponseTypeToProcessAuthz"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#deviceauthztokenpollinterval", "text": "Description: Default interval returned to the client to process device token requests Required: No Default value: None", "title": "deviceAuthzTokenPollInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#disableauthnformaxagezero", "text": "Description: Boolean value specifying whether to disable authentication when max_age=0 Required: No Default value: false", "title": "disableAuthnForMaxAgeZero"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#disablejdklogger", "text": "Description: Choose whether to disable JDK loggers Required: No Default value: true", "title": "disableJdkLogger"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#disablepromptconsent", "text": "Description: Boolean value specifying whether to disable prompt=consent Required: No Default value: false", "title": "disablePromptConsent"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#disablepromptlogin", "text": "Description: Boolean value specifying whether to disable prompt=login Required: No Default value: false", "title": "disablePromptLogin"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#disableu2fendpoint", "text": "Description: Choose whether to disable U2F endpoints Required: No Default value: false", "title": "disableU2fEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#discoveryallowedkeys", "text": "Description: List of configuration response claim allowed to be displayed in discovery endpoint Required: No Default value: None", "title": "discoveryAllowedKeys"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#discoverycachelifetimeinminutes", "text": "Description: Lifetime of discovery cache Required: No Default value: 60", "title": "discoveryCacheLifetimeInMinutes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#discoverydenykeys", "text": "Description: List of configuration response claims which must not be displayed in discovery endpoint response Required: No Default value: None", "title": "discoveryDenyKeys"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#displayvaluessupported", "text": "Description: A list of the display parameter values that the OpenID Provider supports Required: No Default value: None", "title": "displayValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dnname", "text": "Description: DN of certificate issuer Required: No Default value: None", "title": "dnName"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dpopjticachetime", "text": "Description: Demonstration of Proof-of-Possession (DPoP) cache time Required: No Default value: 3600", "title": "dpopJtiCacheTime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dpopnoncecachetime", "text": "Description: Demonstration of Proof-of-Possession (DPoP) nonce cache time Required: No Default value: 3600", "title": "dpopNonceCacheTime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dpopsigningalgvaluessupported", "text": "Description: Demonstration of Proof-of-Possession (DPoP) authorization signing algorithms supported Required: No Default value: None", "title": "dpopSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dpoptimeframe", "text": "Description: Demonstration of Proof-of-Possession (DPoP) timeout Required: No Default value: 5", "title": "dpopTimeframe"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dpopusenonce", "text": "Description: Demonstration of Proof-of-Possession (DPoP) use nonce Required: No Default value: false", "title": "dpopUseNonce"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#granttypessupportedbydynamicregistration", "text": "Description: This list details which OAuth 2.0 grant types can be set up with the client registration API Required: No Default value: None", "title": "grantTypesSupportedByDynamicRegistration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationallowedpasswordgrantscopes", "text": "Description: List of grant scopes for dynamic registration Required: No Default value: None", "title": "dynamicRegistrationAllowedPasswordGrantScopes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationcustomattributes", "text": "Description: This list details the custom attributes allowed for dynamic registration Required: No Default value: None", "title": "dynamicRegistrationCustomAttributes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationcustomobjectclass", "text": "Description: LDAP custom object class for dynamic registration Required: No Default value: None", "title": "dynamicRegistrationCustomObjectClass"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationdefaultcustomattributes", "text": "Description: This map provides default custom attributes with values for dynamic registration Required: No Default value: None", "title": "dynamicRegistrationDefaultCustomAttributes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationexpirationtime", "text": "Description: Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire Required: No Default value: -1", "title": "dynamicRegistrationExpirationTime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationpasswordgranttypeenabled", "text": "Description: Boolean value specifying whether to enable Password Grant Type during Dynamic Registration Required: No Default value: false", "title": "dynamicRegistrationPasswordGrantTypeEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationpersistclientauthorizations", "text": "Description: Boolean value specifying whether to persist client authorizations Required: No Default value: None", "title": "dynamicRegistrationPersistClientAuthorizations"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationscopesparamenabled", "text": "Description: Boolean value specifying whether to enable scopes parameter in dynamic registration Required: No Default value: None", "title": "dynamicRegistrationScopesParamEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#enableclientgranttypeupdate", "text": "Description: Choose if client can update Grant Type values Required: No Default value: None", "title": "enableClientGrantTypeUpdate"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#enabledoauthauditlogging", "text": "Description: enable OAuth Audit Logging Required: No Default value: None", "title": "enabledOAuthAuditLogging"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#endsessionendpoint", "text": "Description: URL at the OP to which an RP can perform a redirect to request that the end user be logged out at the OP Required: No Default value: None", "title": "endSessionEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#endsessionwithaccesstoken", "text": "Description: Choose whether to accept access tokens to call end_session endpoint Required: No Default value: None", "title": "endSessionWithAccessToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#errorhandlingmethod", "text": "Description: A list of possible error handling methods. Possible values: remote (send error back to RP), internal (show error page) Required: No Default value: remote", "title": "errorHandlingMethod"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#errorreasonenabled", "text": "Description: Boolean value specifying whether to return detailed reason of the error from AS. Default value is false Required: No Default value: false", "title": "errorReasonEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#expirationnotificatorenabled", "text": "Description: Boolean value specifying whether expiration notificator is enabled (used to identify expiration for persistence that support TTL, like Couchbase) Required: No Default value: false", "title": "expirationNotificatorEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#expirationnotificatorintervalinseconds", "text": "Description: The expiration notificator interval in second Required: No Default value: None", "title": "expirationNotificatorIntervalInSeconds"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#expirationnotificatormapsizelimit", "text": "Description: The expiration notificator maximum size limit Required: No Default value: None", "title": "expirationNotificatorMapSizeLimit"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#externalloggerconfiguration", "text": "Description: The path to the external log4j2 logging configuration Required: No Default value: None", "title": "externalLoggerConfiguration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#externaluriwhitelist", "text": "Description: This list specifies which external URIs can be called by AS (if empty any URI can be called) Required: No Default value: None", "title": "externalUriWhiteList"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#fapicompatibility", "text": "Description: Boolean value specifying whether to turn on FAPI compatibility mode. If true AS behaves in more strict mode Required: No Default value: false", "title": "fapiCompatibility"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#featureflags", "text": "Description: List of enabled feature flags Required: No Default value: None", "title": "featureFlags"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#forceidtokenhintpresence", "text": "Description: Boolean value specifying whether force id_token_hint parameter presence Required: No Default value: false", "title": "forceIdTokenHintPresence"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#forceofflineaccessscopetoenablerefreshtoken", "text": "Description: Boolean value specifying whether force offline_access scope to enable refresh_token grant type. Default value is true Required: No Default value: true", "title": "forceOfflineAccessScopeToEnableRefreshToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#forcesignedrequestobject", "text": "Description: Boolean value true indicates that signed request object is mandatory Required: No Default value: false", "title": "forceSignedRequestObject"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#frontchannellogoutsessionsupported", "text": "Description: Choose whether to support front channel session logout Required: No Default value: None", "title": "frontChannelLogoutSessionSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#granttypesandresponsetypesautofixenabled", "text": "Description: Boolean value specifying whether to Grant types and Response types can be auto fixed Required: No Default value: None", "title": "grantTypesAndResponseTypesAutofixEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#granttypessupported", "text": "Description: This list details which OAuth 2.0 grant types are supported by this OP Required: No Default value: None", "title": "grantTypesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#httploggingenabled", "text": "Description: Enable/disable request/response logging filter Required: No Default value: None", "title": "httpLoggingEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#httploggingexcludepaths", "text": "Description: This list details the base URIs for which the request/response logging filter will not record activity Required: No Default value: None", "title": "httpLoggingExcludePaths"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#httploggingresponsebodycontent", "text": "Description: Defines if Response body will be logged. Default value is false Required: No Default value: false", "title": "httpLoggingResponseBodyContent"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idgenerationendpoint", "text": "Description: ID Generation endpoint URL Required: No Default value: None", "title": "idGenerationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokenencryptionalgvaluessupported", "text": "Description: A list of the JWE encryption algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None", "title": "idTokenEncryptionAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokenencryptionencvaluessupported", "text": "Description: A list of the JWE encryption algorithms (enc values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None", "title": "idTokenEncryptionEncValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokenfilterclaimsbasedonaccesstoken", "text": "Description: Boolean value specifying whether idToken filters claims based on accessToken Required: No Default value: None", "title": "idTokenFilterClaimsBasedOnAccessToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokenlifetime", "text": "Description: The lifetime of the ID Token Required: No Default value: None", "title": "idTokenLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokensigningalgvaluessupported", "text": "Description: A list of the JWS signing algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None", "title": "idTokenSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokentokenbindingcnfvaluessupported", "text": "Description: Array containing a list of the JWT Confirmation Method member names supported by the OP for Token Binding of ID Tokens. The presence of this parameter indicates that the OpenID Provider supports Token Binding of ID Tokens. If omitted, the default is that the OpenID Provider does not support Token Binding of ID Tokens Required: No Default value: None", "title": "idTokenTokenBindingCnfValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#imglocation", "text": "Description: The location for image files Required: No Default value: None", "title": "imgLocation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#includesidinresponse", "text": "Description: Boolean value specifying whether to include sessionId in response Required: No Default value: false", "title": "includeSidInResponse"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionaccesstokenmusthaveintrospectionscope", "text": "Description: If True, rejects introspection requests if access_token does not have the 'introspection' scope in its authorization header. Comparing to 'uma_protection', 'introspection' scope is not allowed for dynamic registration' Required: No Default value: false", "title": "introspectionAccessTokenMustHaveIntrospectionScope"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionaccesstokenmusthaveumaprotectionscope", "text": "Description: If True, rejects introspection requests if access_token does not have the uma_protection scope in its authorization header Required: No Default value: false", "title": "introspectionAccessTokenMustHaveUmaProtectionScope"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionendpoint", "text": "Description: Introspection endpoint URL Required: No Default value: None", "title": "introspectionEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionresponsescopesbackwardcompatibility", "text": "Description: Boolean value specifying introspection response backward compatibility mode Required: No Default value: false", "title": "introspectionResponseScopesBackwardCompatibility"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionscriptbackwardcompatibility", "text": "Description: Boolean value specifying whether switch off client's introspection scripts (true value) and run all scripts that exists on server. Default value is false Required: No Default value: false", "title": "introspectionScriptBackwardCompatibility"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionskipauthorization", "text": "Description: Specifies if authorization to be skipped for introspection Required: No Default value: None", "title": "introspectionSkipAuthorization"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#invalidatesessioncookiesafterauthorizationflow", "text": "Description: Boolean value to specify whether to invalidate session_id and consent_session_id cookies right after successful or unsuccessful authorization Required: No Default value: false", "title": "invalidateSessionCookiesAfterAuthorizationFlow"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#issuer", "text": "Description: URL using the https scheme that OP asserts as Issuer identifier Required: No Default value: None", "title": "issuer"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jansid", "text": "Description: URL for the Inum generator Service Required: No Default value: None", "title": "jansId"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jansopenidconnectversion", "text": "Description: OpenID Connect Version Required: No Default value: None", "title": "jansOpenIdConnectVersion"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jmsbrokeruriset", "text": "Description: JMS Broker URI Set Required: No Default value: None", "title": "jmsBrokerURISet"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jmspassword", "text": "Description: JMS Password Required: No Default value: None", "title": "jmsPassword"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jmsusername", "text": "Description: JMS UserName Required: No Default value: None", "title": "jmsUserName"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jslocation", "text": "Description: The location for JavaScript files Required: No Default value: None", "title": "jsLocation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jwksalgorithmssupported", "text": "Description: A list of algorithms that will be used in JWKS endpoint Required: No Default value: None", "title": "jwksAlgorithmsSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jwksuri", "text": "Description: URL of the OP's JSON Web Key Set (JWK) document. This contains the signing key(s) the RP uses to validate signatures from the OP Required: No Default value: None", "title": "jwksUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keepauthenticatorattributesonacrchange", "text": "Description: Boolean value specifying whether to keep authenticator attributes on ACR change Required: No Default value: false", "title": "keepAuthenticatorAttributesOnAcrChange"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keyalgsallowedforgeneration", "text": "Description: List of algorithm allowed to be used for key generation Required: No Default value: None", "title": "keyAlgsAllowedForGeneration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keyregenerationenabled", "text": "Description: Boolean value specifying whether to regenerate keys Required: No Default value: None", "title": "keyRegenerationEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keyregenerationinterval", "text": "Description: The interval for key regeneration in hours Required: No Default value: None", "title": "keyRegenerationInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keyselectionstrategy", "text": "Description: Key Selection Strategy : OLDER, NEWER, FIRST Required: No Default value: OLDER", "title": "keySelectionStrategy"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keysignwithsamekeybutdiffalg", "text": "Description: Specifies if signing to be done with same key but apply different algorithms Required: No Default value: None", "title": "keySignWithSameKeyButDiffAlg"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keystorefile", "text": "Description: The Key Store File (JKS) Required: No Default value: None", "title": "keyStoreFile"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keystoresecret", "text": "Description: The Key Store password Required: No Default value: None", "title": "keyStoreSecret"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#legacyidtokenclaims", "text": "Description: Choose whether to include claims in ID tokens Required: No Default value: None", "title": "legacyIdTokenClaims"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#logclientidonclientauthentication", "text": "Description: Choose if application should log the Client ID on client authentication Required: No Default value: None", "title": "logClientIdOnClientAuthentication"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#logclientnameonclientauthentication", "text": "Description: Choose if application should log the Client Name on client authentication Required: No Default value: None", "title": "logClientNameOnClientAuthentication"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#logginglayout", "text": "Description: Logging layout used for Jans Authorization Server loggers Required: No Default value: None", "title": "loggingLayout"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#logginglevel", "text": "Description: Specify the logging level of loggers Required: No Default value: None", "title": "loggingLevel"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#lognotfoundentityaserror", "text": "Description: Boolean value specifying whether to log not_found entity exception as error or as trace. Default value is false (trace). Required: No Default value: None", "title": "logNotFoundEntityAsError"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#metricreporterinterval", "text": "Description: The interval for metric reporter in seconds Required: No Default value: None", "title": "metricReporterInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#metricreporterkeepdatadays", "text": "Description: The days to keep metric reported data Required: No Default value: None", "title": "metricReporterKeepDataDays"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsauthorizationendpoint", "text": "Description: URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Endpoint Required: No Default value: None", "title": "mtlsAuthorizationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlschecksessioniframe", "text": "Description: URL for Mutual TLS (mTLS) IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Required: No Default value: None", "title": "mtlsCheckSessionIFrame"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsclientinfoendpoint", "text": "Description: URL for Mutual TLS (mTLS) Client Info endpoint Required: No Default value: None", "title": "mtlsClientInfoEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsdeviceauthzendpoint", "text": "Description: Mutual TLS (mTLS) device authorization endpoint URL Required: No Default value: None", "title": "mtlsDeviceAuthzEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsendsessionendpoint", "text": "Description: URL for Mutual TLS (mTLS) to which an RP can perform a redirect to request that the end user be logged out at the OP Required: No Default value: None", "title": "mtlsEndSessionEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsidgenerationendpoint", "text": "Description: Mutual TLS (mTLS) ID generation endpoint URL Required: No Default value: None", "title": "mtlsIdGenerationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsintrospectionendpoint", "text": "Description: Mutual TLS (mTLS) introspection endpoint URL Required: No Default value: None", "title": "mtlsIntrospectionEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsjwksuri", "text": "Description: URL for Mutual TLS (mTLS) of the OP's JSON Web Key Set (JWK) document Required: No Default value: None", "title": "mtlsJwksUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsparendpoint", "text": "Description: Mutual TLS (mTLS) Pushed Authorization Requests(PAR) endpoint URL Required: No Default value: None", "title": "mtlsParEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsregistrationendpoint", "text": "Description: Mutual TLS (mTLS) registration endpoint URL Required: No Default value: None", "title": "mtlsRegistrationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlstokenendpoint", "text": "Description: URL for Mutual TLS (mTLS) Authorization token Endpoint Required: No Default value: None", "title": "mtlsTokenEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlstokenrevocationendpoint", "text": "Description: URL for Mutual TLS (mTLS) Authorization token revocation endpoint Required: No Default value: None", "title": "mtlsTokenRevocationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsuserinfoendpoint", "text": "Description: Mutual TLS (mTLS) user info endpoint URL Required: No Default value: None", "title": "mtlsUserInfoEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#openidconfigurationendpoint", "text": "Description: URL for the Open ID Connect Configuration Endpoint Required: No Default value: None", "title": "openIdConfigurationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#openiddiscoveryendpoint", "text": "Description: Discovery endpoint URL Required: No Default value: None", "title": "openIdDiscoveryEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#openidscopebackwardcompatibility", "text": "Description: Set to false to only allow token endpoint request for openid scope with grant type equals to authorization_code, restrict access to userinfo to scope openid and only return id_token if scope contains openid Required: No Default value: false", "title": "openidScopeBackwardCompatibility"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#openidsubattribute", "text": "Description: Specifies which LDAP attribute is used for the subject identifier claim Required: No Default value: None", "title": "openidSubAttribute"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#oppolicyuri", "text": "Description: URL that the OpenID Provider provides to the person registering the Client to read about the OP's requirements on how the Relying Party can use the data provided by the OP Required: No Default value: None", "title": "opPolicyUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#optosuri", "text": "Description: URL that the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service Required: No Default value: None", "title": "opTosUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#pairwisecalculationkey", "text": "Description: Key to calculate algorithmic pairwise IDs Required: No Default value: None", "title": "pairwiseCalculationKey"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#pairwisecalculationsalt", "text": "Description: Salt to calculate algorithmic pairwise IDs Required: No Default value: None", "title": "pairwiseCalculationSalt"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#pairwiseidtype", "text": "Description: the pairwise ID type Required: No Default value: None", "title": "pairwiseIdType"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#parendpoint", "text": "Description: URL for Pushed Authorisation Request (PAR) Endpoint Required: No Default value: None", "title": "parEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#persistidtoken", "text": "Description: Specifies whether to persist id_token (otherwise saves into cache) Required: No Default value: false", "title": "persistIdToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#persistrefreshtoken", "text": "Description: Specifies whether to persist refresh_token (otherwise saves into cache) Required: No Default value: true", "title": "persistRefreshToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#personcustomobjectclasslist", "text": "Description: This list details LDAP custom object classes for dynamic person enrollment Required: No Default value: None", "title": "personCustomObjectClassList"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#publicsubjectidentifierperclientenabled", "text": "Description: Specifies whether public subject identifier is allowed per client Required: No Default value: false", "title": "publicSubjectIdentifierPerClientEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#redirecturisregexenabled", "text": "Description: Enable/Disable redirect uris validation using regular expression Required: No Default value: false", "title": "redirectUrisRegexEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#refreshtokenextendlifetimeonrotation", "text": "Description: Boolean value specifying whether to extend refresh tokens on rotation Required: No Default value: false", "title": "refreshTokenExtendLifetimeOnRotation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#refreshtokenlifetime", "text": "Description: The lifetime of the Refresh Token Required: No Default value: None", "title": "refreshTokenLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#registrationendpoint", "text": "Description: Registration endpoint URL Required: No Default value: None", "title": "registrationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#rejectendsessionifidtokenexpired", "text": "Description: default value false. If true and id_token is not found in db, request is rejected Required: No Default value: false", "title": "rejectEndSessionIfIdTokenExpired"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#rejectjwtwithnonealg", "text": "Description: Boolean value specifying whether reject JWT requested or validated with algorithm None. Default value is true Required: No Default value: true", "title": "rejectJwtWithNoneAlg"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#removerefreshtokensforclientonlogout", "text": "Description: Boolean value specifying whether to remove Refresh Tokens on logout. Default value is true Required: No Default value: true", "title": "removeRefreshTokensForClientOnLogout"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requestobjectencryptionalgvaluessupported", "text": "Description: A list of the JWE encryption algorithms (alg values) supported by the OP for Request Objects Required: No Default value: None", "title": "requestObjectEncryptionAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requestobjectencryptionencvaluessupported", "text": "Description: A list of the JWE encryption algorithms (enc values) supported by the OP for Request Objects Required: No Default value: None", "title": "requestObjectEncryptionEncValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requestobjectsigningalgvaluessupported", "text": "Description: A list of the JWS signing algorithms (alg values) supported by the OP for Request Objects Required: No Default value: None", "title": "requestObjectSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requestparametersupported", "text": "Description: Boolean value specifying whether the OP supports use of the request parameter Required: No Default value: None", "title": "requestParameterSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requesturiblocklist", "text": "Description: Block list for requestUri that can come to Authorization Endpoint (e.g. localhost) Required: No Default value: None", "title": "requestUriBlockList"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requesturihashverificationenabled", "text": "Description: Boolean value specifying whether the OP supports use of the request_uri hash verification Required: No Default value: None", "title": "requestUriHashVerificationEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requesturiparametersupported", "text": "Description: Boolean value specifying whether the OP supports use of the request_uri parameter Required: No Default value: None", "title": "requestUriParameterSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requirepar", "text": "Description: Boolean value to indicate of Pushed Authorisation Request(PAR)is required Required: No Default value: false", "title": "requirePar"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requirepkce", "text": "Description: Boolean value true check for Proof Key for Code Exchange (PKCE) Required: No Default value: false", "title": "requirePkce"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requirerequestobjectencryption", "text": "Description: Boolean value true encrypts request object Required: No Default value: false", "title": "requireRequestObjectEncryption"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requirerequesturiregistration", "text": "Description: Boolean value specifying whether the OP requires any request_uri values used to be pre-registered using the request_uris registration parameter Required: No Default value: None", "title": "requireRequestUriRegistration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#responsemodessupported", "text": "Description: This list details which OAuth 2.0 response modes are supported by this OP Required: No Default value: None", "title": "responseModesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#responsetypessupported", "text": "Description: This list details which OAuth 2.0 response_type values are supported by this OP. Required: No Default value: By default, every combination of code, token and id_token is supported.", "title": "responseTypesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#returnclientsecretonread", "text": "Description: Boolean value specifying whether a client_secret is returned on client GET or PUT. Set to true by default which means to return secret Required: No Default value: false", "title": "returnClientSecretOnRead"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#returndevicesecretfromauthzendpoint", "text": "Description: Required: No Default value: false", "title": "returnDeviceSecretFromAuthzEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#rotateclientregistrationaccesstokenonusage", "text": "Description: Boolean value specifying whether to rotate client registration access token after each usage Required: No Default value: false", "title": "rotateClientRegistrationAccessTokenOnUsage"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#rotatedevicesecret", "text": "Description: Required: No Default value: false", "title": "rotateDeviceSecret"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sectoridentifiercachelifetimeinminutes", "text": "Description: Sector Identifier cache lifetime in minutes Required: No Default value: 1440", "title": "sectorIdentifierCacheLifetimeInMinutes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#serversessionidlifetime", "text": "Description: Dedicated property to control lifetime of the server side OP session object in seconds. Overrides sessionIdLifetime. By default value is 0, so object lifetime equals sessionIdLifetime (which sets both cookie and object expiration). It can be useful if goal is to keep different values for client cookie and server object Required: No Default value: None", "title": "serverSessionIdLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#servicedocumentation", "text": "Description: URL of a page containing human-readable information that developers might want or need to know when using the OpenID Provider Required: No Default value: None", "title": "serviceDocumentation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidlifetime", "text": "Description: The lifetime of session id in seconds. If 0 or -1 then expiration is not set. session_id cookie expires when browser session ends Required: No Default value: None", "title": "sessionIdLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidpersistincache", "text": "Description: Boolean value specifying whether to persist session_id in cache Required: No Default value: false", "title": "sessionIdPersistInCache"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidpersistonpromptnone", "text": "Description: Boolean value specifying whether to persist session ID on prompt none Required: No Default value: None", "title": "sessionIdPersistOnPromptNone"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidrequestparameterenabled", "text": "Description: Boolean value specifying whether to enable session_id HTTP request parameter Required: No Default value: false", "title": "sessionIdRequestParameterEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidunauthenticatedunusedlifetime", "text": "Description: The lifetime for unused unauthenticated session states Required: No Default value: None", "title": "sessionIdUnauthenticatedUnusedLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidunusedlifetime", "text": "Description: The lifetime for unused session states Required: No Default value: None", "title": "sessionIdUnusedLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sharesubjectidbetweenclientswithsamesectorid", "text": "Description: When true, clients with the same Sector ID also share the same Subject ID Required: No Default value: false", "title": "shareSubjectIdBetweenClientsWithSameSectorId"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#skipauthenticationfilteroptionsmethod", "text": "Description: Force Authentication Filtker to process OPTIONS request Required: No Default value: true", "title": "skipAuthenticationFilterOptionsMethod"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#skipauthorizationforopenidscopeandpairwiseid", "text": "Description: Choose whether to skip authorization if a client has an OpenId scope and a pairwise ID Required: No Default value: false", "title": "skipAuthorizationForOpenIdScopeAndPairwiseId"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#skiprefreshtokenduringrefreshing", "text": "Description: Boolean value specifying whether to skip refreshing tokens on refreshing Required: No Default value: false", "title": "skipRefreshTokenDuringRefreshing"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#softwarestatementvalidationclaimname", "text": "Description: Validation claim name for software statement Required: No Default value: None", "title": "softwareStatementValidationClaimName"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#softwarestatementvalidationtype", "text": "Description: Validation type used for software statement Required: No Default value: None", "title": "softwareStatementValidationType"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#spontaneousscopelifetime", "text": "Description: The lifetime of spontaneous scope in seconds Required: No Default value: None", "title": "spontaneousScopeLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#ssaconfiguration", "text": "Description: SSA Configuration Required: No Default value: None", "title": "ssaConfiguration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#statauthorizationscope", "text": "Description: Scope required for Statistical Authorization Required: No Default value: None", "title": "statAuthorizationScope"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#staticdecryptionkid", "text": "Description: Specifies static decryption Kid Required: No Default value: None", "title": "staticDecryptionKid"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#statickid", "text": "Description: Specifies static Kid Required: No Default value: None", "title": "staticKid"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#stattimerintervalinseconds", "text": "Description: Statistical data capture time interval Required: No Default value: None", "title": "statTimerIntervalInSeconds"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#subjectidentifiersperclientsupported", "text": "Description: A list of the subject identifiers supported per client Required: No Default value: None", "title": "subjectIdentifiersPerClientSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#subjecttypessupported", "text": "Description: This list details which Subject Identifier types that the OP supports. Valid types include pairwise and public. Required: No Default value: None", "title": "subjectTypesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#tokenendpoint", "text": "Description: The token endpoint URL Required: No Default value: None", "title": "tokenEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#tokenendpointauthmethodssupported", "text": "Description: A list of Client Authentication methods supported by this Token Endpoint Required: No Default value: None", "title": "tokenEndpointAuthMethodsSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#tokenendpointauthsigningalgvaluessupported", "text": "Description: A list of the JWS signing algorithms (alg values) supported by the Token Endpoint for the signature on the JWT used to authenticate the Client at the Token Endpoint for the private_key_jwt and client_secret_jwt authentication methods Required: No Default value: None", "title": "tokenEndpointAuthSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#tokenrevocationendpoint", "text": "Description: The URL for the access_token or refresh_token revocation endpoint Required: No Default value: None", "title": "tokenRevocationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#trustedclientenabled", "text": "Description: Boolean value specifying whether a client is trusted and no authorization is required Required: No Default value: None", "title": "trustedClientEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#trustedssaissuers", "text": "Description: List of trusted SSA issuers with configuration (e.g. automatically granted scopes). Required: No Default value: None", "title": "trustedSsaIssuers"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#uilocalessupported", "text": "Description: This list details the languages and scripts supported for the user interface Required: No Default value: None", "title": "uiLocalesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umaaddscopesautomatically", "text": "Description: Add UMA scopes automatically if it is not registered yet Required: No Default value: None", "title": "umaAddScopesAutomatically"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umaconfigurationendpoint", "text": "Description: UMA Configuration endpoint URL Required: No Default value: None", "title": "umaConfigurationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umagrantaccessifnopolicies", "text": "Description: Specify whether to grant access to resources if there is no any policies associated with scopes Required: No Default value: false", "title": "umaGrantAccessIfNoPolicies"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umapctlifetime", "text": "Description: UMA PCT lifetime Required: No Default value: None", "title": "umaPctLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umaresourcelifetime", "text": "Description: UMA Resource lifetime Required: No Default value: None", "title": "umaResourceLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umarestrictresourcetoassociatedclient", "text": "Description: Restrict access to resource by associated client Required: No Default value: false", "title": "umaRestrictResourceToAssociatedClient"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umarptasjwt", "text": "Description: Issue RPT as JWT or as random string Required: No Default value: false", "title": "umaRptAsJwt"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umarptlifetime", "text": "Description: UMA RPT lifetime Required: No Default value: None", "title": "umaRptLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umaticketlifetime", "text": "Description: UMA ticket lifetime Required: No Default value: None", "title": "umaTicketLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umavalidateclaimtoken", "text": "Description: Validate claim_token as id_token assuming it is issued by local id Required: No Default value: false", "title": "umaValidateClaimToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#updateclientaccesstime", "text": "Description: Choose if application should update oxLastAccessTime/oxLastLogonTime attributes upon client authentication Required: No Default value: None", "title": "updateClientAccessTime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#updateuserlastlogontime", "text": "Description: Choose if application should update oxLastLogonTime attribute upon user authentication Required: No Default value: None", "title": "updateUserLastLogonTime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#usehighestlevelscriptifacrscriptnotfound", "text": "Description: Enable/Disable usage of highest level script in case ACR script does not exist Required: No Default value: false", "title": "useHighestLevelScriptIfAcrScriptNotFound"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#uselocalcache", "text": "Description: Cache in local memory cache attributes, scopes, clients and organization entry with expiration 60 seconds Required: No Default value: false", "title": "useLocalCache"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#usenestedjwtduringencryption", "text": "Description: Boolean value specifying whether to use nested Jwt during encryption Required: No Default value: true", "title": "useNestedJwtDuringEncryption"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#userinfoencryptionalgvaluessupported", "text": "Description: This JSON Array lists which JWS encryption algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None", "title": "userInfoEncryptionAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#userinfoencryptionencvaluessupported", "text": "Description: This JSON Array lists which JWS encryption algorithms (enc values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None", "title": "userInfoEncryptionEncValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#userinfoendpoint", "text": "Description: The User Info endpoint URL Required: No Default value: None", "title": "userInfoEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#userinfosigningalgvaluessupported", "text": "Description: This JSON Array lists which JWS signing algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None", "title": "userInfoSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#webkeysstorage", "text": "Description: Web Key Storage Type Required: No Default value: None", "title": "webKeysStorage"}, {"location": "janssen-server/reference/json/properties/scim-properties/", "tags": ["administration", "reference", "json", "properties"], "text": "SCIM Configuration Properties # Property Name Description applicationUrl Application base URL Details baseDN Application config Base DN Details baseEndpoint SCIM base endpoint URL Details bulkMaxOperations Specifies maximum bulk operations Details bulkMaxPayloadSize Specifies maximum payload size of bulk operations Details disableJdkLogger Boolean value specifying whether to enable JDK Loggers Details externalLoggerConfiguration Path to external log4j2 logging configuration Details loggingLayout Logging layout used for Server loggers Details loggingLevel Logging level for scim logger Details maxCount Maximum number of results per page Details metricReporterEnabled Metric reported data enabled flag Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep metric reported data Details oxAuthIssuer Jans Auth - Issuer identifier Details personCustomObjectClass Person Object Class Details protectionMode SCIM Protection Mode Details useLocalCache Boolean value specifying whether to enable local in-memory cache Details userExtensionSchemaURI User Extension Schema URI Details applicationUrl # Description: Application base URL Required: No Default value: None baseDN # Description: Application config Base DN Required: No Default value: None baseEndpoint # Description: SCIM base endpoint URL Required: No Default value: None bulkMaxOperations # Description: Specifies maximum bulk operations Required: No Default value: None bulkMaxPayloadSize # Description: Specifies maximum payload size of bulk operations Required: No Default value: None disableJdkLogger # Description: Boolean value specifying whether to enable JDK Loggers Required: No Default value: None externalLoggerConfiguration # Description: Path to external log4j2 logging configuration Required: No Default value: None loggingLayout # Description: Logging layout used for Server loggers Required: No Default value: None loggingLevel # Description: Logging level for scim logger Required: No Default value: None maxCount # Description: Maximum number of results per page Required: No Default value: None metricReporterEnabled # Description: Metric reported data enabled flag Required: No Default value: None metricReporterInterval # Description: The interval for metric reporter in seconds Required: No Default value: None metricReporterKeepDataDays # Description: The days to keep metric reported data Required: No Default value: None oxAuthIssuer # Description: Jans Auth - Issuer identifier Required: No Default value: None personCustomObjectClass # Description: Person Object Class Required: No Default value: None protectionMode # Description: SCIM Protection Mode Required: No Default value: None useLocalCache # Description: Boolean value specifying whether to enable local in-memory cache Required: No Default value: None userExtensionSchemaURI # Description: User Extension Schema URI Required: No Default value: None", "title": "SCIM"}, {"location": "janssen-server/reference/json/properties/scim-properties/#scim-configuration-properties", "text": "Property Name Description applicationUrl Application base URL Details baseDN Application config Base DN Details baseEndpoint SCIM base endpoint URL Details bulkMaxOperations Specifies maximum bulk operations Details bulkMaxPayloadSize Specifies maximum payload size of bulk operations Details disableJdkLogger Boolean value specifying whether to enable JDK Loggers Details externalLoggerConfiguration Path to external log4j2 logging configuration Details loggingLayout Logging layout used for Server loggers Details loggingLevel Logging level for scim logger Details maxCount Maximum number of results per page Details metricReporterEnabled Metric reported data enabled flag Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep metric reported data Details oxAuthIssuer Jans Auth - Issuer identifier Details personCustomObjectClass Person Object Class Details protectionMode SCIM Protection Mode Details useLocalCache Boolean value specifying whether to enable local in-memory cache Details userExtensionSchemaURI User Extension Schema URI Details", "title": "SCIM Configuration Properties"}, {"location": "janssen-server/reference/json/properties/scim-properties/#applicationurl", "text": "Description: Application base URL Required: No Default value: None", "title": "applicationUrl"}, {"location": "janssen-server/reference/json/properties/scim-properties/#basedn", "text": "Description: Application config Base DN Required: No Default value: None", "title": "baseDN"}, {"location": "janssen-server/reference/json/properties/scim-properties/#baseendpoint", "text": "Description: SCIM base endpoint URL Required: No Default value: None", "title": "baseEndpoint"}, {"location": "janssen-server/reference/json/properties/scim-properties/#bulkmaxoperations", "text": "Description: Specifies maximum bulk operations Required: No Default value: None", "title": "bulkMaxOperations"}, {"location": "janssen-server/reference/json/properties/scim-properties/#bulkmaxpayloadsize", "text": "Description: Specifies maximum payload size of bulk operations Required: No Default value: None", "title": "bulkMaxPayloadSize"}, {"location": "janssen-server/reference/json/properties/scim-properties/#disablejdklogger", "text": "Description: Boolean value specifying whether to enable JDK Loggers Required: No Default value: None", "title": "disableJdkLogger"}, {"location": "janssen-server/reference/json/properties/scim-properties/#externalloggerconfiguration", "text": "Description: Path to external log4j2 logging configuration Required: No Default value: None", "title": "externalLoggerConfiguration"}, {"location": "janssen-server/reference/json/properties/scim-properties/#logginglayout", "text": "Description: Logging layout used for Server loggers Required: No Default value: None", "title": "loggingLayout"}, {"location": "janssen-server/reference/json/properties/scim-properties/#logginglevel", "text": "Description: Logging level for scim logger Required: No Default value: None", "title": "loggingLevel"}, {"location": "janssen-server/reference/json/properties/scim-properties/#maxcount", "text": "Description: Maximum number of results per page Required: No Default value: None", "title": "maxCount"}, {"location": "janssen-server/reference/json/properties/scim-properties/#metricreporterenabled", "text": "Description: Metric reported data enabled flag Required: No Default value: None", "title": "metricReporterEnabled"}, {"location": "janssen-server/reference/json/properties/scim-properties/#metricreporterinterval", "text": "Description: The interval for metric reporter in seconds Required: No Default value: None", "title": "metricReporterInterval"}, {"location": "janssen-server/reference/json/properties/scim-properties/#metricreporterkeepdatadays", "text": "Description: The days to keep metric reported data Required: No Default value: None", "title": "metricReporterKeepDataDays"}, {"location": "janssen-server/reference/json/properties/scim-properties/#oxauthissuer", "text": "Description: Jans Auth - Issuer identifier Required: No Default value: None", "title": "oxAuthIssuer"}, {"location": "janssen-server/reference/json/properties/scim-properties/#personcustomobjectclass", "text": "Description: Person Object Class Required: No Default value: None", "title": "personCustomObjectClass"}, {"location": "janssen-server/reference/json/properties/scim-properties/#protectionmode", "text": "Description: SCIM Protection Mode Required: No Default value: None", "title": "protectionMode"}, {"location": "janssen-server/reference/json/properties/scim-properties/#uselocalcache", "text": "Description: Boolean value specifying whether to enable local in-memory cache Required: No Default value: None", "title": "useLocalCache"}, {"location": "janssen-server/reference/json/properties/scim-properties/#userextensionschemauri", "text": "Description: User Extension Schema URI Required: No Default value: None", "title": "userExtensionSchemaURI"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/", "tags": ["administration", "reference", "kubernetes", "configmap", "secret"], "text": "Overview # The config job creates a set of configurations (contains secrets and configmaps ) used by all Janssen services. Note We assume Janssen is installed in a namespace called jans Configmaps # The configmaps store non-sensitive data as key-value pairs. To check the values of the configmaps on the current deployment run: kubectl get configmap -n jans -o yaml Note that each key in configmaps is based on the schema below: { \"city\" : { \"type\" : \"string\" , \"description\" : \"Locality name (e.g. city)\" , \"example\" : \"Austin\" }, \"country_code\" : { \"type\" : \"string\" , \"minLength\" : 2 , \"maxLength\" : 2 , \"description\" : \"Country name (2 letter code)\" , \"example\" : \"US\" }, \"admin_email\" : { \"type\" : \"string\" , \"format\" : \"email\" , \"description\" : \"Email address\" , \"example\" : \"support@jans.io\" }, \"hostname\" : { \"type\" : \"string\" , \"description\" : \"Fully qualified domain name (FQDN)\" , \"example\" : \"demoexample.jans.io\" }, \"orgName\" : { \"type\" : \"string\" , \"description\" : \"Organization name\" , \"example\" : \"Janssen\" }, \"state\" : { \"type\" : \"string\" , \"description\" : \"State or Province Name\" , \"example\" : \"TX\" }, \"optional_scopes\" : { \"type\" : \"string\" , \"default\" : \"[]\" , \"description\" : \"List of optional scopes of components as string\" , \"example\" : \"[\\\"redis\\\", \\\"sql\\\"]\" }, \"auth_sig_keys\" : { \"type\" : \"string\" , \"default\" : \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" , \"description\" : \"Signature keys to generate\" , \"example\" : \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" }, \"auth_enc_keys\" : { \"type\" : \"string\" , \"default\" : \"RSA1_5 RSA-OAEP ECDH-ES\" , \"description\" : \"Encryption keys to generate\" , \"example\" : \"RSA1_5 RSA-OAEP ECDH-ES\" }, \"init_keys_exp\" : { \"type\" : \"integer\" , \"default\" : 48 , \"minimum\" : 1 , \"description\" : \"Initial expiration time (in hours) for generated keys\" , \"example\" : 24 }, \"admin_inum\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Inum for admin user\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"admin_ui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of admin-ui app\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"casa_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-casa app\" , \"example\" : \"1902.66bc89a1-075f-4a18-9349-a2908c1040e6\" }, \"jans_idp_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-idp app\" , \"example\" : \"jans-f13013e3-e4a7-4709-8b50-df459f489cd3\" }, \"jca_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-config-api app\" , \"example\" : \"1800.ca41fad2-6ab6-46b1-b4a9-3387992a8cb0\" }, \"scim_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-scim app\" , \"example\" : \"1201.dd7e7733-b548-45ee-aed1-74e7b4065801\" }, \"tui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-tui app\" , \"example\" : \"2000.4a67fad3-24cd-4d56-b5a3-7cfb2e9fbb05\" }, \"test_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of test app\" , \"example\" : \"174143d2-f7f6-4bda-baa0-a6a8fd01b77a\" }, \"kc_master_auth_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak master auth app\" , \"example\" : \"2103.22abf39d-f78f-4fb0-871e-dcb80bc1e43c\" }, \"kc_saml_openid_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak SAML OpenID app\" , \"example\" : \"2101.70394974-82ec-481e-9493-e96d3cf8072f\" }, \"kc_scheduler_api_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak scheduler API app\" , \"example\" : \"2102.d424af33-2069-4803-8426-4787af5fd933\" }, \"token_server_admin_ui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of token server app\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"auth_key_rotated_at\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Timestamp of last auth keys regeneration\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"auth_legacyIdTokenClaims\" : { \"type\" : \"string\" , \"default\" : \"false\" , \"enum\" : [ \"false\" , \"true\" ], \"description\" : \"Enable legacy ID token claim\" , \"example\" : \"false\" }, \"auth_openidScopeBackwardCompatibility\" : { \"type\" : \"string\" , \"default\" : \"false\" , \"enum\" : [ \"false\" , \"true\" ], \"description\" : \"Enable backward-compat OpenID scope\" , \"example\" : \"false\" }, \"auth_openid_jks_fn\" : { \"type\" : \"string\" , \"default\" : \"/etc/certs/auth-keys.jks\" , \"description\" : \"Path to keystore file contains private keys for jans-auth\" }, \"auth_openid_jwks_fn\" : { \"type\" : \"string\" , \"default\" : \"/etc/certs/auth-keys.json\" , \"description\" : \"Path to JSON file contains public keys for jans-auth\" }, \"default_openid_jks_dn_name\" : { \"type\" : \"string\" , \"default\" : \"CN=Janssen Auth CA Certificates\" , \"description\" : \"CommonName for jans-auth CA certificate\" }, \"kc_admin_username\" : { \"type\" : \"string\" , \"default\" : \"admin\" , \"description\" : \"Admin username of Keycloak\" , \"example\" : \"admin\" }, \"smtp_alias\" : { \"type\" : \"string\" , \"default\" : \"smtp_sig_ec256\" , \"description\" : \"Alias for SMTP entry in truststore\" , \"example\" : \"smtp_sig_ec256\" }, \"smtp_signing_alg\" : { \"type\" : \"string\" , \"default\" : \"SHA256withECDSA\" , \"description\" : \"SMTP signing algorithm\" , \"example\" : \"SHA256withECDSA\" } } Secrets # The secrets store sensitive data as key-value pairs. To check the values of the secrets on the current deployment run : kubectl get secret -n jans -o yaml Note that each key in secrets is based on the schema below: { \"admin_password\" : { \"type\" : \"string\" , \"description\" : \"Password for admin user\" }, \"sql_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for SQL (RDBMS) user\" }, \"encoded_salt\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Salt for encoding/decoding sensitive secret\" , \"example\" : \"hR8kBUtTxB25pDPCSHVRktAz\" }, \"google_credentials\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains Google application credentials\" , \"example\" : \"{\\n \\\"type\\\": \\\"service_account\\\",\\n \\\"project_id\\\": \\\"testing-project\\\"\\n}\\n\" }, \"aws_credentials\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS shared credentials\" , \"example\" : \"[default]\\naws_access_key_id = FAKE_ACCESS_KEY_ID\\naws_secret_access_key = FAKE_SECRET_ACCESS_KEY\\n\" }, \"aws_config\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS config\" , \"example\" : \"[default]\\nregion = us-west-1\\n\" }, \"aws_replica_regions\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS replica regions config\" , \"example\" : \"[{\\\"Region\\\": \\\"us-west-1\\\"}, {\\\"Region\\\": \\\"us-west-2\\\"}]\\n\" }, \"vault_role_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Vault RoleID\" }, \"vault_secret_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Vault SecretID\" }, \"kc_db_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for Keycloak RDBMS user\" }, \"admin_ui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for admin-ui client\" , \"x-encoding\" : \"3DES\" }, \"admin_ui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for admin-ui client\" }, \"auth_jks_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Private keys (keystore) of jans-auth\" }, \"auth_openid_jks_pass\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password of jans-auth keystore\" }, \"auth_openid_key_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Public keys (JWKS) of jans-auth\" }, \"casa_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-casa client\" , \"x-encoding\" : \"3DES\" }, \"casa_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-casa client\" }, \"encoded_admin_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password of admin\" , \"x-encoding\" : \"ldap_encode\" }, \"jans_idp_client_secret\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of jans-idp app\" }, \"jans_idp_user_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"User password for jans-idp\" }, \"jca_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-config-api client\" , \"x-encoding\" : \"3DES\" }, \"jca_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-config-api client\" }, \"kc_admin_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Admin password of Keycloak\" }, \"kc_master_auth_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak master auth app\" , \"x-encoding\" : \"3DES\" }, \"kc_master_auth_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak master auth app\" }, \"kc_saml_openid_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak SAML app\" , \"x-encoding\" : \"3DES\" }, \"kc_saml_openid_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak SAML app\" }, \"kc_scheduler_api_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak scheduler API app\" , \"x-encoding\" : \"3DES\" }, \"kc_scheduler_api_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak scheduler API app\" }, \"otp_configuration\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"OTP configuration string\" }, \"pairwiseCalculationKey\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Pairwise calculation key\" }, \"pairwiseCalculationSalt\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Pairwise calculation salt\" }, \"scim_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-scim client\" , \"x-encoding\" : \"3DES\" }, \"scim_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-scim client\" }, \"smtp_jks_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Private keys (keystore) of SMTP\" }, \"smtp_jks_pass\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password of SMTP keystore\" }, \"smtp_jks_pass_enc\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password of SMTP keystore\" }, \"ssl_ca_cert\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate for CA\" }, \"ssl_ca_key\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL key for CA\" }, \"ssl_cert\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate for the FQDN\" }, \"ssl_csr\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate signing request for the FQDN\" }, \"ssl_key\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL key for the FQDN\" }, \"super_gluu_creds\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SuperGluu credentials string\" }, \"test_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for test client\" , \"x-encoding\" : \"3DES\" }, \"test_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for test client\" }, \"token_server_admin_ui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for token server client\" , \"x-encoding\" : \"3DES\" }, \"token_server_admin_ui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for token server client\" }, \"tui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for TUI client\" , \"x-encoding\" : \"3DES\" }, \"tui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for TUI client\" }, \"redis_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for Redis user\" } } Example decoding secrets # Opening base64-decoded secrets # Get the tls-certificate from the backend secret kubectl get secret tls-certificate -n jans -o yaml Copy the value of the key you want to decode. For example: data: tls.crt: <encodedValue> Base64 decode the value echo <encodedValue> | base64 -d #replace encodedValue with the value from the previous command Using Configuration Schema # As mentioned earlier, the config job creates a set of configurations. This happens by using a Kubernetes secret named <janssen-release-name>-configuration-file that gets created during the helm chart installation. It contains a JSON schema with the necessary secrets and configmaps to install Janssen services. This secret is then mounted by the config job. Default configuration # apiVersion : v1 kind : Secret metadata : name : janssen-configuration-file namespace : jans labels : APP_NAME : configurator type : Opaque stringData : configuration.json : |- { \"_configmap\": { \"hostname\": \"demoexample.jans.io\", \"country_code\": \"US\", \"state\": \"TX\", \"city\": \"Austin\", \"admin_email\": \"support@jans.io\", \"orgName\": \"Janssen\", \"auth_sig_keys\": \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\", \"auth_enc_keys\": \"RSA1_5 RSA-OAEP ECDH-ES\", \"optional_scopes\": \"[\\\"redis\\\", \\\"sql\\\"]\", \"init_keys_exp\": 48 }, \"_secret\": { \"admin_password\": \"Test1234#\", \"sql_password\": \"Test1234#\", \"encoded_salt\": \"hR8kBUtTxB25pDPCSHVRktAz\" } } Note that _secret may contain other keys depending on the persistence used, the backend of the secrets/configmaps, etc. For example: Secrets/configmaps backend is set to google : \"_secret\" : { \"google_credentials\" : \"{\\n \\\"type\\\": \\\"service_account\\\",\\n \\\"project_id\\\": \\\"testing-project\\\"\\n}\" } Secrets backend is set to vault : \"_secret\" : { \"vault_role_id\" : \"c41a15f4-abcd-1234-abcd-d306bf9f3eb6\" , \"vault_secret_id\" : \"a7ae191c-abcd-1234-abcd-3733dc6b0813\" } Secrets/configmaps backend is set to aws : \"_secret\" : { \"aws_config\" : \"[default]\\nregion = us-west-1\\n\" , \"aws_credentials\" : \"[default]\\naws_access_key_id = FAKE_ACCESS_KEY_ID\\naws_secret_access_key = FAKE_SECRET_ACCESS_KEY\\n\" , \"aws_replica_regions\" : \"[{\\\"Region\\\": \\\"us-west-1\\\"}, {\\\"Region\\\": \\\"us-west-2\\\"}]\\n\" } Custom configuration # The default configuration schema is sufficient for most of the time. However, if there's a requirement to use a custom configuration or reusing an existing configuration, you can create a Kubernetes secret with the custom configuration schema. Warning The custom configuration schema is a BETA feature. Prepare the YAML file containing the custom configuration schema. We will name it custom-configuration-schema.yaml : apiVersion : v1 kind : Secret metadata : name : custom-configuration-schema namespace : jans type : Opaque stringData : configuration.json : |- { \"_configmap\": { \"hostname\": \"demoexample.jans.io\", \"country_code\": \"US\", \"state\": \"TX\", \"city\": \"Houston\", \"admin_email\": \"custom@example.com\", \"orgName\": \"custom-org\", \"optional_scopes\": \"[\\\"sql\\\"]\" }, \"_secret\": { \"admin_password\": \"Custom1234#\", \"sql_password\": \"Custom1234#\" } } Create the Kubernetes secret: kubectl -n jans apply -f custom-configuration-schema.yaml Specify the secret in values.yaml : global : cnConfiguratorCustomSchema : secretName : custom-configuration-schema Install the Janssen helm chart. Encrypting Configuration Schema # The encryption uses Helm-specific implementation of AES-256 CBC mode. Default configuration # The default configuration schema can be encrypted by specifying 32 alphanumeric characters to cnConfiguratorKey attribute (the default value is an empty string). global : cnConfiguratorKey : \"VMtVyFha8CfppdDGQSw8zEnfKXRvksAD\" The following example is what an encrypted default configuration looks like: apiVersion : v1 kind : Secret metadata : name : janssen-configuration-file namespace : jans stringData : configuration.json : |- sxySo+redacted+generated+by+helm/TNpE5PoUR2+JxXiHiLq8X5ibexJcfjAN0fKlqRvU= Custom configuration # If you are using a custom configuration schema, you will need to generate the string using sprig-aes CLI and paste it into a YAML manifest. # custom-configuration-schema.yaml apiVersion : v1 kind : Secret metadata : name : custom-configuration-schema namespace : jans type : Opaque stringData : configuration.json : |- sxySo+redacted+generated+by+sprigaes+JxXiHiLq8X5ibexJcfjAN0fKlqRvU= Add the key used when encrypting using sprig-aes. global : cnConfiguratorKey : \"VMtVyFha8CfppdDGQSw8zEnfKXRvksAD\"", "title": "Configuration Keys"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#overview", "text": "The config job creates a set of configurations (contains secrets and configmaps ) used by all Janssen services. Note We assume Janssen is installed in a namespace called jans", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#configmaps", "text": "The configmaps store non-sensitive data as key-value pairs. To check the values of the configmaps on the current deployment run: kubectl get configmap -n jans -o yaml Note that each key in configmaps is based on the schema below: { \"city\" : { \"type\" : \"string\" , \"description\" : \"Locality name (e.g. city)\" , \"example\" : \"Austin\" }, \"country_code\" : { \"type\" : \"string\" , \"minLength\" : 2 , \"maxLength\" : 2 , \"description\" : \"Country name (2 letter code)\" , \"example\" : \"US\" }, \"admin_email\" : { \"type\" : \"string\" , \"format\" : \"email\" , \"description\" : \"Email address\" , \"example\" : \"support@jans.io\" }, \"hostname\" : { \"type\" : \"string\" , \"description\" : \"Fully qualified domain name (FQDN)\" , \"example\" : \"demoexample.jans.io\" }, \"orgName\" : { \"type\" : \"string\" , \"description\" : \"Organization name\" , \"example\" : \"Janssen\" }, \"state\" : { \"type\" : \"string\" , \"description\" : \"State or Province Name\" , \"example\" : \"TX\" }, \"optional_scopes\" : { \"type\" : \"string\" , \"default\" : \"[]\" , \"description\" : \"List of optional scopes of components as string\" , \"example\" : \"[\\\"redis\\\", \\\"sql\\\"]\" }, \"auth_sig_keys\" : { \"type\" : \"string\" , \"default\" : \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" , \"description\" : \"Signature keys to generate\" , \"example\" : \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" }, \"auth_enc_keys\" : { \"type\" : \"string\" , \"default\" : \"RSA1_5 RSA-OAEP ECDH-ES\" , \"description\" : \"Encryption keys to generate\" , \"example\" : \"RSA1_5 RSA-OAEP ECDH-ES\" }, \"init_keys_exp\" : { \"type\" : \"integer\" , \"default\" : 48 , \"minimum\" : 1 , \"description\" : \"Initial expiration time (in hours) for generated keys\" , \"example\" : 24 }, \"admin_inum\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Inum for admin user\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"admin_ui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of admin-ui app\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"casa_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-casa app\" , \"example\" : \"1902.66bc89a1-075f-4a18-9349-a2908c1040e6\" }, \"jans_idp_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-idp app\" , \"example\" : \"jans-f13013e3-e4a7-4709-8b50-df459f489cd3\" }, \"jca_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-config-api app\" , \"example\" : \"1800.ca41fad2-6ab6-46b1-b4a9-3387992a8cb0\" }, \"scim_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-scim app\" , \"example\" : \"1201.dd7e7733-b548-45ee-aed1-74e7b4065801\" }, \"tui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-tui app\" , \"example\" : \"2000.4a67fad3-24cd-4d56-b5a3-7cfb2e9fbb05\" }, \"test_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of test app\" , \"example\" : \"174143d2-f7f6-4bda-baa0-a6a8fd01b77a\" }, \"kc_master_auth_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak master auth app\" , \"example\" : \"2103.22abf39d-f78f-4fb0-871e-dcb80bc1e43c\" }, \"kc_saml_openid_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak SAML OpenID app\" , \"example\" : \"2101.70394974-82ec-481e-9493-e96d3cf8072f\" }, \"kc_scheduler_api_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak scheduler API app\" , \"example\" : \"2102.d424af33-2069-4803-8426-4787af5fd933\" }, \"token_server_admin_ui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of token server app\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"auth_key_rotated_at\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Timestamp of last auth keys regeneration\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"auth_legacyIdTokenClaims\" : { \"type\" : \"string\" , \"default\" : \"false\" , \"enum\" : [ \"false\" , \"true\" ], \"description\" : \"Enable legacy ID token claim\" , \"example\" : \"false\" }, \"auth_openidScopeBackwardCompatibility\" : { \"type\" : \"string\" , \"default\" : \"false\" , \"enum\" : [ \"false\" , \"true\" ], \"description\" : \"Enable backward-compat OpenID scope\" , \"example\" : \"false\" }, \"auth_openid_jks_fn\" : { \"type\" : \"string\" , \"default\" : \"/etc/certs/auth-keys.jks\" , \"description\" : \"Path to keystore file contains private keys for jans-auth\" }, \"auth_openid_jwks_fn\" : { \"type\" : \"string\" , \"default\" : \"/etc/certs/auth-keys.json\" , \"description\" : \"Path to JSON file contains public keys for jans-auth\" }, \"default_openid_jks_dn_name\" : { \"type\" : \"string\" , \"default\" : \"CN=Janssen Auth CA Certificates\" , \"description\" : \"CommonName for jans-auth CA certificate\" }, \"kc_admin_username\" : { \"type\" : \"string\" , \"default\" : \"admin\" , \"description\" : \"Admin username of Keycloak\" , \"example\" : \"admin\" }, \"smtp_alias\" : { \"type\" : \"string\" , \"default\" : \"smtp_sig_ec256\" , \"description\" : \"Alias for SMTP entry in truststore\" , \"example\" : \"smtp_sig_ec256\" }, \"smtp_signing_alg\" : { \"type\" : \"string\" , \"default\" : \"SHA256withECDSA\" , \"description\" : \"SMTP signing algorithm\" , \"example\" : \"SHA256withECDSA\" } }", "title": "Configmaps"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#secrets", "text": "The secrets store sensitive data as key-value pairs. To check the values of the secrets on the current deployment run : kubectl get secret -n jans -o yaml Note that each key in secrets is based on the schema below: { \"admin_password\" : { \"type\" : \"string\" , \"description\" : \"Password for admin user\" }, \"sql_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for SQL (RDBMS) user\" }, \"encoded_salt\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Salt for encoding/decoding sensitive secret\" , \"example\" : \"hR8kBUtTxB25pDPCSHVRktAz\" }, \"google_credentials\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains Google application credentials\" , \"example\" : \"{\\n \\\"type\\\": \\\"service_account\\\",\\n \\\"project_id\\\": \\\"testing-project\\\"\\n}\\n\" }, \"aws_credentials\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS shared credentials\" , \"example\" : \"[default]\\naws_access_key_id = FAKE_ACCESS_KEY_ID\\naws_secret_access_key = FAKE_SECRET_ACCESS_KEY\\n\" }, \"aws_config\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS config\" , \"example\" : \"[default]\\nregion = us-west-1\\n\" }, \"aws_replica_regions\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS replica regions config\" , \"example\" : \"[{\\\"Region\\\": \\\"us-west-1\\\"}, {\\\"Region\\\": \\\"us-west-2\\\"}]\\n\" }, \"vault_role_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Vault RoleID\" }, \"vault_secret_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Vault SecretID\" }, \"kc_db_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for Keycloak RDBMS user\" }, \"admin_ui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for admin-ui client\" , \"x-encoding\" : \"3DES\" }, \"admin_ui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for admin-ui client\" }, \"auth_jks_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Private keys (keystore) of jans-auth\" }, \"auth_openid_jks_pass\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password of jans-auth keystore\" }, \"auth_openid_key_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Public keys (JWKS) of jans-auth\" }, \"casa_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-casa client\" , \"x-encoding\" : \"3DES\" }, \"casa_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-casa client\" }, \"encoded_admin_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password of admin\" , \"x-encoding\" : \"ldap_encode\" }, \"jans_idp_client_secret\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of jans-idp app\" }, \"jans_idp_user_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"User password for jans-idp\" }, \"jca_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-config-api client\" , \"x-encoding\" : \"3DES\" }, \"jca_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-config-api client\" }, \"kc_admin_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Admin password of Keycloak\" }, \"kc_master_auth_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak master auth app\" , \"x-encoding\" : \"3DES\" }, \"kc_master_auth_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak master auth app\" }, \"kc_saml_openid_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak SAML app\" , \"x-encoding\" : \"3DES\" }, \"kc_saml_openid_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak SAML app\" }, \"kc_scheduler_api_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak scheduler API app\" , \"x-encoding\" : \"3DES\" }, \"kc_scheduler_api_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak scheduler API app\" }, \"otp_configuration\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"OTP configuration string\" }, \"pairwiseCalculationKey\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Pairwise calculation key\" }, \"pairwiseCalculationSalt\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Pairwise calculation salt\" }, \"scim_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-scim client\" , \"x-encoding\" : \"3DES\" }, \"scim_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-scim client\" }, \"smtp_jks_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Private keys (keystore) of SMTP\" }, \"smtp_jks_pass\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password of SMTP keystore\" }, \"smtp_jks_pass_enc\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password of SMTP keystore\" }, \"ssl_ca_cert\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate for CA\" }, \"ssl_ca_key\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL key for CA\" }, \"ssl_cert\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate for the FQDN\" }, \"ssl_csr\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate signing request for the FQDN\" }, \"ssl_key\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL key for the FQDN\" }, \"super_gluu_creds\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SuperGluu credentials string\" }, \"test_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for test client\" , \"x-encoding\" : \"3DES\" }, \"test_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for test client\" }, \"token_server_admin_ui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for token server client\" , \"x-encoding\" : \"3DES\" }, \"token_server_admin_ui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for token server client\" }, \"tui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for TUI client\" , \"x-encoding\" : \"3DES\" }, \"tui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for TUI client\" }, \"redis_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for Redis user\" } }", "title": "Secrets"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#example-decoding-secrets", "text": "", "title": "Example decoding secrets"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#opening-base64-decoded-secrets", "text": "Get the tls-certificate from the backend secret kubectl get secret tls-certificate -n jans -o yaml Copy the value of the key you want to decode. For example: data: tls.crt: <encodedValue> Base64 decode the value echo <encodedValue> | base64 -d #replace encodedValue with the value from the previous command", "title": "Opening base64-decoded secrets"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#using-configuration-schema", "text": "As mentioned earlier, the config job creates a set of configurations. This happens by using a Kubernetes secret named <janssen-release-name>-configuration-file that gets created during the helm chart installation. It contains a JSON schema with the necessary secrets and configmaps to install Janssen services. This secret is then mounted by the config job.", "title": "Using Configuration Schema"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#default-configuration", "text": "apiVersion : v1 kind : Secret metadata : name : janssen-configuration-file namespace : jans labels : APP_NAME : configurator type : Opaque stringData : configuration.json : |- { \"_configmap\": { \"hostname\": \"demoexample.jans.io\", \"country_code\": \"US\", \"state\": \"TX\", \"city\": \"Austin\", \"admin_email\": \"support@jans.io\", \"orgName\": \"Janssen\", \"auth_sig_keys\": \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\", \"auth_enc_keys\": \"RSA1_5 RSA-OAEP ECDH-ES\", \"optional_scopes\": \"[\\\"redis\\\", \\\"sql\\\"]\", \"init_keys_exp\": 48 }, \"_secret\": { \"admin_password\": \"Test1234#\", \"sql_password\": \"Test1234#\", \"encoded_salt\": \"hR8kBUtTxB25pDPCSHVRktAz\" } } Note that _secret may contain other keys depending on the persistence used, the backend of the secrets/configmaps, etc. For example: Secrets/configmaps backend is set to google : \"_secret\" : { \"google_credentials\" : \"{\\n \\\"type\\\": \\\"service_account\\\",\\n \\\"project_id\\\": \\\"testing-project\\\"\\n}\" } Secrets backend is set to vault : \"_secret\" : { \"vault_role_id\" : \"c41a15f4-abcd-1234-abcd-d306bf9f3eb6\" , \"vault_secret_id\" : \"a7ae191c-abcd-1234-abcd-3733dc6b0813\" } Secrets/configmaps backend is set to aws : \"_secret\" : { \"aws_config\" : \"[default]\\nregion = us-west-1\\n\" , \"aws_credentials\" : \"[default]\\naws_access_key_id = FAKE_ACCESS_KEY_ID\\naws_secret_access_key = FAKE_SECRET_ACCESS_KEY\\n\" , \"aws_replica_regions\" : \"[{\\\"Region\\\": \\\"us-west-1\\\"}, {\\\"Region\\\": \\\"us-west-2\\\"}]\\n\" }", "title": "Default configuration"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#custom-configuration", "text": "The default configuration schema is sufficient for most of the time. However, if there's a requirement to use a custom configuration or reusing an existing configuration, you can create a Kubernetes secret with the custom configuration schema. Warning The custom configuration schema is a BETA feature. Prepare the YAML file containing the custom configuration schema. We will name it custom-configuration-schema.yaml : apiVersion : v1 kind : Secret metadata : name : custom-configuration-schema namespace : jans type : Opaque stringData : configuration.json : |- { \"_configmap\": { \"hostname\": \"demoexample.jans.io\", \"country_code\": \"US\", \"state\": \"TX\", \"city\": \"Houston\", \"admin_email\": \"custom@example.com\", \"orgName\": \"custom-org\", \"optional_scopes\": \"[\\\"sql\\\"]\" }, \"_secret\": { \"admin_password\": \"Custom1234#\", \"sql_password\": \"Custom1234#\" } } Create the Kubernetes secret: kubectl -n jans apply -f custom-configuration-schema.yaml Specify the secret in values.yaml : global : cnConfiguratorCustomSchema : secretName : custom-configuration-schema Install the Janssen helm chart.", "title": "Custom configuration"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#encrypting-configuration-schema", "text": "The encryption uses Helm-specific implementation of AES-256 CBC mode.", "title": "Encrypting Configuration Schema"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#default-configuration_1", "text": "The default configuration schema can be encrypted by specifying 32 alphanumeric characters to cnConfiguratorKey attribute (the default value is an empty string). global : cnConfiguratorKey : \"VMtVyFha8CfppdDGQSw8zEnfKXRvksAD\" The following example is what an encrypted default configuration looks like: apiVersion : v1 kind : Secret metadata : name : janssen-configuration-file namespace : jans stringData : configuration.json : |- sxySo+redacted+generated+by+helm/TNpE5PoUR2+JxXiHiLq8X5ibexJcfjAN0fKlqRvU=", "title": "Default configuration"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#custom-configuration_1", "text": "If you are using a custom configuration schema, you will need to generate the string using sprig-aes CLI and paste it into a YAML manifest. # custom-configuration-schema.yaml apiVersion : v1 kind : Secret metadata : name : custom-configuration-schema namespace : jans type : Opaque stringData : configuration.json : |- sxySo+redacted+generated+by+sprigaes+JxXiHiLq8X5ibexJcfjAN0fKlqRvU= Add the key used when encrypting using sprig-aes. global : cnConfiguratorKey : \"VMtVyFha8CfppdDGQSw8zEnfKXRvksAD\"", "title": "Custom configuration"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Docker image packaging for Janssen Authorization Server. Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_DEBUG_PORT : port of remote debugging (if omitted, remote debugging will be disabled). CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_AUTH_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_SYNC_INTERVAL : Interval between files sync (default to 300 seconds). CN_JACKRABBIT_ADMIN_ID : Admin username (default to admin ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/jans/conf/jackrabbit_admin_password ). CN_SYNC_JKS_ENABLED : Whether to enable JKS sync (default to false ). Enable this flag if using gluufederation/key-rotation:4.1.1_02 and below (for key-regeneration). CN_SYNC_JKS_INTERVAL : Interval of JKS sync in seconds (if needed); obsolete. GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_JETTY_REQUEST_HEADER_SIZE : Maximum size of request header accepted by Jetty (default to 8192 ). CN_AUTH_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_LOCK_ENABLED : Enable jans-lock as part of jans-auth . CN_OPA_URL : URL to OPA server (default to http://localhost:8181/v1 ). CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file. Configure app loggers # App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"auth_log_target\" : \"STDOUT\" , \"auth_log_level\" : \"INFO\" , \"http_log_target\" : \"FILE\" , \"http_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" , \"audit_log_target\" : \"FILE\" , \"audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"auth_log_target\":\"STDOUT\",\"script_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Configure plugin loggers # Plugin loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"lock_log_target\" : \"STDOUT\" , \"lock_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"lock_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", } Exposing metrics # As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterward, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Auth Server"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#overview", "text": "Docker image packaging for Janssen Authorization Server.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_DEBUG_PORT : port of remote debugging (if omitted, remote debugging will be disabled). CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_AUTH_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_SYNC_INTERVAL : Interval between files sync (default to 300 seconds). CN_JACKRABBIT_ADMIN_ID : Admin username (default to admin ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/jans/conf/jackrabbit_admin_password ). CN_SYNC_JKS_ENABLED : Whether to enable JKS sync (default to false ). Enable this flag if using gluufederation/key-rotation:4.1.1_02 and below (for key-regeneration). CN_SYNC_JKS_INTERVAL : Interval of JKS sync in seconds (if needed); obsolete. GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_JETTY_REQUEST_HEADER_SIZE : Maximum size of request header accepted by Jetty (default to 8192 ). CN_AUTH_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_LOCK_ENABLED : Enable jans-lock as part of jans-auth . CN_OPA_URL : URL to OPA server (default to http://localhost:8181/v1 ). CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#configure-app-loggers", "text": "App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"auth_log_target\" : \"STDOUT\" , \"auth_log_level\" : \"INFO\" , \"http_log_target\" : \"FILE\" , \"http_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" , \"audit_log_target\" : \"FILE\" , \"audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"auth_log_target\":\"STDOUT\",\"script_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure app loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#configure-plugin-loggers", "text": "Plugin loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"lock_log_target\" : \"STDOUT\" , \"lock_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"lock_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure plugin loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#exposing-metrics", "text": "As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterward, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Exposing metrics"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/", "text": "Overview # Docker assets for Casa Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault or kubernetes . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_CONFIGMAP : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_SYNC_INTERVAL : Interval between files sync (default to 300 seconds). CN_JACKRABBIT_ADMIN_ID : Admin username (default to admin ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/jans/conf/jackrabbit_admin_password ). CN_SQL_DB_DIALECT : Dialect name of SQL backend (one of mysql , pgsql ; default to mysql ). CN_SQL_DB_HOST : Host of SQL backend (default to localhost ). CN_SQL_DB_PORT : Port of SQL backend (default to 3306 ). CN_SQL_DB_NAME : Database name (default to jans ) CN_SQL_DB_USER : Username to interact with SQL backend (default to jans ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CASA_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_CASA_ADMIN_LOCK_FILE : Path to lock file to enable/disable administration feature (default to /opt/jans/jetty/jans-casa/.administrable ). If file is not exist, the feature is disabled. CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_CASA_JWKS_SIZE_LIMIT : Default HTTP size limit (in bytes) when retrieving remote JWKS (default to 100000 ). CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file. Configure app loggers # App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: OFF FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"casa_log_target\" : \"STDOUT\" , \"casa_log_level\" : \"INFO\" , \"timer_log_target\" : \"FILE\" , \"timer_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"casa_log_target\":\"STDOUT\",\"timer_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Exposing metrics # As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container. Hybrid mapping # Hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Casa"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#overview", "text": "Docker assets for Casa", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault or kubernetes . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_CONFIGMAP : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_SYNC_INTERVAL : Interval between files sync (default to 300 seconds). CN_JACKRABBIT_ADMIN_ID : Admin username (default to admin ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/jans/conf/jackrabbit_admin_password ). CN_SQL_DB_DIALECT : Dialect name of SQL backend (one of mysql , pgsql ; default to mysql ). CN_SQL_DB_HOST : Host of SQL backend (default to localhost ). CN_SQL_DB_PORT : Port of SQL backend (default to 3306 ). CN_SQL_DB_NAME : Database name (default to jans ) CN_SQL_DB_USER : Username to interact with SQL backend (default to jans ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CASA_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_CASA_ADMIN_LOCK_FILE : Path to lock file to enable/disable administration feature (default to /opt/jans/jetty/jans-casa/.administrable ). If file is not exist, the feature is disabled. CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_CASA_JWKS_SIZE_LIMIT : Default HTTP size limit (in bytes) when retrieving remote JWKS (default to 100000 ). CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#configure-app-loggers", "text": "App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: OFF FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"casa_log_target\" : \"STDOUT\" , \"casa_log_level\" : \"INFO\" , \"timer_log_target\" : \"FILE\" , \"timer_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"casa_log_target\":\"STDOUT\",\"timer_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure app loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#exposing-metrics", "text": "As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Exposing metrics"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#hybrid-mapping", "text": "Hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Container image to manage X.509 certificates and crypto keys in Janssen Server. The container is designed to run as a one-time command (or Job in Kubernetes world). Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_GOOGLE_SECRET_VERSION_ID : Google Secret Manager version ID (default to latest ). CN_SECRET_GOOGLE_SECRET_NAME_PREFIX : Prefix for Google Secret Manager name (default to jans ). CN_SECRET_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Google Secret Manager (default to secret ). CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_CONTAINER_METADATA : The name of scheduler to pull container metadata (one of docker or kubernetes ; default to docker ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. Usage # Commands # The following commands are supported by the container: patch prune patch # Updates X.509 certificates and/or crypto keys related to the service. Usage: certmanager patch [OPTIONS] SERVICE Patch cert and/or crypto keys for the targeted service. Options: --dry-run Enable dryrun mode. --opts KEY:VALUE Options for targeted service (can be set multiple times). -h, --help Show this message and exit. Global options: --dry-run --opts : service-dependent options, example: --opts interval:48 Supported services: web (nginx container or ingress) Load from existing or re-generate: /etc/certs/jans_https.crt /etc/certs/jans_https.key . Options: source : from-files or empty string valid-to : Validity length in days (default to 365 ) auth Re-generate: /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Options: interval : crypto keys expiration time (in hours) push-to-container : whether to push auth-keys.jks and auth-keys.json to auth-server containers (default to true ) key-strategy : key selection strategy (choose one of OLDER , NEWER , FIRST ; default to NEWER ) privkey-push-delay : delay time in seconds before pushing auth-keys.jks to auth containers (default to 0 ) privkey-push-strategy : key selection strategy after auth-keys.jks is pushed to auth containers (choose one of OLDER , NEWER , FIRST ; default to NEWER ) sig-keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) enc-keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) prune # Delete expired crypto keys (if any) related to the service. Usage: certmanager prune [OPTIONS] SERVICE Cleanup expired crypto keys for the targeted service. Options: --dry-run Enable dryrun mode. --opts KEY:VALUE Options for targeted service (can be set multiple times). -h, --help Show this message and exit. Global options: --dry-run --opts : service-dependent options, example: --opts interval:48 Supported services: auth Delete expired keys (if any) from the following files: /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Options: push-to-container : whether to push auth-keys.jks and auth-keys.json to auth containers (default to true ) sig-keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) enc-keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) Examples # Kubernetes CronJob example: kind : CronJob apiVersion : batch/v1beta1 metadata : name : auth-key-rotation spec : schedule : \"0 */48 * * *\" concurrencyPolicy : Forbid jobTemplate : spec : template : spec : containers : - name : auth-key-rotation image : ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly resources : requests : memory : \"300Mi\" cpu : \"300m\" limits : memory : \"300Mi\" cpu : \"300m\" envFrom : - configMapRef : name : jans-config-cm args : [ \"patch\" , \"auth\" , \"--opts\" , \"interval:48\" ] restartPolicy : Never Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Cert Manager"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#overview", "text": "Container image to manage X.509 certificates and crypto keys in Janssen Server. The container is designed to run as a one-time command (or Job in Kubernetes world).", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_GOOGLE_SECRET_VERSION_ID : Google Secret Manager version ID (default to latest ). CN_SECRET_GOOGLE_SECRET_NAME_PREFIX : Prefix for Google Secret Manager name (default to jans ). CN_SECRET_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Google Secret Manager (default to secret ). CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_CONTAINER_METADATA : The name of scheduler to pull container metadata (one of docker or kubernetes ; default to docker ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#usage", "text": "", "title": "Usage"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#commands", "text": "The following commands are supported by the container: patch prune", "title": "Commands"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#patch", "text": "Updates X.509 certificates and/or crypto keys related to the service. Usage: certmanager patch [OPTIONS] SERVICE Patch cert and/or crypto keys for the targeted service. Options: --dry-run Enable dryrun mode. --opts KEY:VALUE Options for targeted service (can be set multiple times). -h, --help Show this message and exit. Global options: --dry-run --opts : service-dependent options, example: --opts interval:48 Supported services: web (nginx container or ingress) Load from existing or re-generate: /etc/certs/jans_https.crt /etc/certs/jans_https.key . Options: source : from-files or empty string valid-to : Validity length in days (default to 365 ) auth Re-generate: /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Options: interval : crypto keys expiration time (in hours) push-to-container : whether to push auth-keys.jks and auth-keys.json to auth-server containers (default to true ) key-strategy : key selection strategy (choose one of OLDER , NEWER , FIRST ; default to NEWER ) privkey-push-delay : delay time in seconds before pushing auth-keys.jks to auth containers (default to 0 ) privkey-push-strategy : key selection strategy after auth-keys.jks is pushed to auth containers (choose one of OLDER , NEWER , FIRST ; default to NEWER ) sig-keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) enc-keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP )", "title": "patch"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#prune", "text": "Delete expired crypto keys (if any) related to the service. Usage: certmanager prune [OPTIONS] SERVICE Cleanup expired crypto keys for the targeted service. Options: --dry-run Enable dryrun mode. --opts KEY:VALUE Options for targeted service (can be set multiple times). -h, --help Show this message and exit. Global options: --dry-run --opts : service-dependent options, example: --opts interval:48 Supported services: auth Delete expired keys (if any) from the following files: /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Options: push-to-container : whether to push auth-keys.jks and auth-keys.json to auth containers (default to true ) sig-keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) enc-keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP )", "title": "prune"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#examples", "text": "Kubernetes CronJob example: kind : CronJob apiVersion : batch/v1beta1 metadata : name : auth-key-rotation spec : schedule : \"0 */48 * * *\" concurrencyPolicy : Forbid jobTemplate : spec : template : spec : containers : - name : auth-key-rotation image : ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly resources : requests : memory : \"300Mi\" cpu : \"300m\" limits : memory : \"300Mi\" cpu : \"300m\" envFrom : - configMapRef : name : jans-config-cm args : [ \"patch\" , \"auth\" , \"--opts\" , \"interval:48\" ] restartPolicy : Never", "title": "Examples"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Docker image packaging for config-api. Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault , kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_CONFIG_API_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_CONFIG_API_LOG_LEVEL : Log level for config api. Options include OFF , FATAL , ERROR , WARN , INFO , DEBUG , TRACE . and ALL . This defaults to INFO CN_AUTH_SERVER_URL : Base URL of Janssen Auth server, i.e. auth-server:8080 (default to empty string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CONFIG_API_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_CONFIG_API_PLUGINS : Comma-separated plugin names that should be enabled (available plugins are admin-ui , scim , fido2 , user-mgt , jans-link , kc-saml , kc-link , lock ). Note that unknown plugin name will be ignored. CN_TOKEN_SERVER_BASE_URL : Base URL of token server (default to empty). CN_TOKEN_SERVER_CERT_FILE : Path to token server certificate (default to /etc/certs/token_server.crt ). CN_ADMIN_UI_PLUGIN_LOGGERS : Custom logging configuration for AdminUI plugin in JSON-string format with hash type (see Configure plugin loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file. Configure app loggers # App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"config_api_log_target\" : \"STDOUT\" , \"config_api_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" , \"audit_log_target\" : \"FILE\" , \"audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"config_api_log_target\":\"STDOUT\",\"script_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Configure plugin loggers # Plugin loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"admin_ui_log_target\" : \"FILE\" , \"admin_ui_log_level\" : \"INFO\" , \"admin_ui_audit_log_target\" : \"FILE\" , \"admin_ui_audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"admin_ui_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", } Exposing metrics # As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Config API"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#overview", "text": "Docker image packaging for config-api.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault , kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_CONFIG_API_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_CONFIG_API_LOG_LEVEL : Log level for config api. Options include OFF , FATAL , ERROR , WARN , INFO , DEBUG , TRACE . and ALL . This defaults to INFO CN_AUTH_SERVER_URL : Base URL of Janssen Auth server, i.e. auth-server:8080 (default to empty string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CONFIG_API_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_CONFIG_API_PLUGINS : Comma-separated plugin names that should be enabled (available plugins are admin-ui , scim , fido2 , user-mgt , jans-link , kc-saml , kc-link , lock ). Note that unknown plugin name will be ignored. CN_TOKEN_SERVER_BASE_URL : Base URL of token server (default to empty). CN_TOKEN_SERVER_CERT_FILE : Path to token server certificate (default to /etc/certs/token_server.crt ). CN_ADMIN_UI_PLUGIN_LOGGERS : Custom logging configuration for AdminUI plugin in JSON-string format with hash type (see Configure plugin loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#configure-app-loggers", "text": "App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"config_api_log_target\" : \"STDOUT\" , \"config_api_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" , \"audit_log_target\" : \"FILE\" , \"audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"config_api_log_target\":\"STDOUT\",\"script_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure app loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#configure-plugin-loggers", "text": "Plugin loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"admin_ui_log_target\" : \"FILE\" , \"admin_ui_log_level\" : \"INFO\" , \"admin_ui_audit_log_target\" : \"FILE\" , \"admin_ui_audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"admin_ui_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure plugin loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#exposing-metrics", "text": "As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Exposing metrics"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Configurator is a tool to load (generate/restore) and/or dump (backup) the configuration (consists of configmaps and secrets). Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CONFIGURATION_SKIP_INITIALIZED : skip initialization if backend already initialized (default to false ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_DOMAIN : Validate certificate is downloaded from given domain. If set to true (default to false ), raise an error if cert is not downloaded. Note that the flag is ignored if mounted SSL cert and key files exist. Commands # The following commands are supported by the container: load dump load # The load command can be used either to generate/restore configmaps and secrets for the cluster. For fresh installation, generate the initial configuration by creating /path/to/host/volume/configuration.json similar to example below: { \"_configmap\" : { \"hostname\" : \"demoexample.jans.io\" , \"country_code\" : \"US\" , \"state\" : \"TX\" , \"city\" : \"Austin\" , \"admin_email\" : \"s@jans.io\" , \"orgName\" : \"Gluu Inc.\" }, \"_secret\" : { \"admin_password\" : \"S3cr3t+pass\" } } NOTE : configuration.json has optional attributes as seen below. _configmap : auth_sig_keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) auth_enc_keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) optional_scopes : list of optional scopes (as JSON string) that will be used (supported scopes are redis , sql ; default to empty list) init_keys_exp : the initial keys expiration time in hours (default to 48 ; extra 1 hour will be added for hard limit) _secret : sql_password : user's password to access SQL database (only used if optional_scopes list contains sql scope) encoded_salt : user-defined salt (24 characters length); if omitted, salt will be generated automatically Example of generating encoded_salt value: # using shell script cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 24 | head -n 1 # output: NFAG5g4R0NSkAZXHL8t2DScL # using python oneliner python -c 'import random, string; print(\"\".join(random.choices(string.ascii_letters + string.digits, k=24)))' # ouput: HsPzqiPkRzNySWlOVui8Ilmw To generate initial configmaps and secrets: Create config map config-generate-params to store the contents of configuration.json kubectl create cm config-generate-params --from-file = configuration.json Mount the configmap into container and apply the yaml: apiVersion : batch/v1 kind : Job metadata : name : configurator-load-job spec : template : spec : restartPolicy : Never volumes : - name : config-generate-params configMap : name : config-generate-params containers : - name : configurator-load image : ghcr.io/janssenproject/jans/configurator:$VERSION volumeMounts : - mountPath : /app/db/configuration.json name : config-generate-params subPath : configuration.json envFrom : - configMapRef : name : config-cm args : [ \"load\" ] A successful load command will dump the pre-populated configuration into /app/db/configuration.out.json . To restore configuration from configuration.out.json file: Create config map config-dump-params : kubectl create cm config-dump-params --from-file = configuration.out.json Mount the configmap into container and apply the yaml: apiVersion : batch/v1 kind : Job metadata : name : configurator-load-job spec : template : spec : restartPolicy : Never volumes : - name : config-dump-params configMap : name : config-dump-params containers : - name : configurator-load image : ghcr.io/janssenproject/jans/configurator:$VERSION volumeMounts : - mountPath : /app/db/configuration.out.json name : config-dump-params subPath : configuration.out.json envFrom : - configMapRef : name : config-cm args : [ \"load\" ] dump # The dump command will dump all configuration from the backends saved into the /app/db/configuration.out.json file. apiVersion : batch/v1 kind : Job metadata : name : configurator-dump-job spec : template : spec : restartPolicy : Never containers : - name : configurator-dump-job image : ghcr.io/janssenproject/jans/configurator:$VERSION command : - /bin/sh - -c - | /app/scripts/entrypoint.sh dump sleep 300 envFrom : - configMapRef : name : config-cm Copy over the files to host kubectl cp configurator-dump-job:/app/db .", "title": "Configurator"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#overview", "text": "Configurator is a tool to load (generate/restore) and/or dump (backup) the configuration (consists of configmaps and secrets).", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CONFIGURATION_SKIP_INITIALIZED : skip initialization if backend already initialized (default to false ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_DOMAIN : Validate certificate is downloaded from given domain. If set to true (default to false ), raise an error if cert is not downloaded. Note that the flag is ignored if mounted SSL cert and key files exist.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#commands", "text": "The following commands are supported by the container: load dump", "title": "Commands"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#load", "text": "The load command can be used either to generate/restore configmaps and secrets for the cluster. For fresh installation, generate the initial configuration by creating /path/to/host/volume/configuration.json similar to example below: { \"_configmap\" : { \"hostname\" : \"demoexample.jans.io\" , \"country_code\" : \"US\" , \"state\" : \"TX\" , \"city\" : \"Austin\" , \"admin_email\" : \"s@jans.io\" , \"orgName\" : \"Gluu Inc.\" }, \"_secret\" : { \"admin_password\" : \"S3cr3t+pass\" } } NOTE : configuration.json has optional attributes as seen below. _configmap : auth_sig_keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) auth_enc_keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) optional_scopes : list of optional scopes (as JSON string) that will be used (supported scopes are redis , sql ; default to empty list) init_keys_exp : the initial keys expiration time in hours (default to 48 ; extra 1 hour will be added for hard limit) _secret : sql_password : user's password to access SQL database (only used if optional_scopes list contains sql scope) encoded_salt : user-defined salt (24 characters length); if omitted, salt will be generated automatically Example of generating encoded_salt value: # using shell script cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 24 | head -n 1 # output: NFAG5g4R0NSkAZXHL8t2DScL # using python oneliner python -c 'import random, string; print(\"\".join(random.choices(string.ascii_letters + string.digits, k=24)))' # ouput: HsPzqiPkRzNySWlOVui8Ilmw To generate initial configmaps and secrets: Create config map config-generate-params to store the contents of configuration.json kubectl create cm config-generate-params --from-file = configuration.json Mount the configmap into container and apply the yaml: apiVersion : batch/v1 kind : Job metadata : name : configurator-load-job spec : template : spec : restartPolicy : Never volumes : - name : config-generate-params configMap : name : config-generate-params containers : - name : configurator-load image : ghcr.io/janssenproject/jans/configurator:$VERSION volumeMounts : - mountPath : /app/db/configuration.json name : config-generate-params subPath : configuration.json envFrom : - configMapRef : name : config-cm args : [ \"load\" ] A successful load command will dump the pre-populated configuration into /app/db/configuration.out.json . To restore configuration from configuration.out.json file: Create config map config-dump-params : kubectl create cm config-dump-params --from-file = configuration.out.json Mount the configmap into container and apply the yaml: apiVersion : batch/v1 kind : Job metadata : name : configurator-load-job spec : template : spec : restartPolicy : Never volumes : - name : config-dump-params configMap : name : config-dump-params containers : - name : configurator-load image : ghcr.io/janssenproject/jans/configurator:$VERSION volumeMounts : - mountPath : /app/db/configuration.out.json name : config-dump-params subPath : configuration.out.json envFrom : - configMapRef : name : config-cm args : [ \"load\" ]", "title": "load"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#dump", "text": "The dump command will dump all configuration from the backends saved into the /app/db/configuration.out.json file. apiVersion : batch/v1 kind : Job metadata : name : configurator-dump-job spec : template : spec : restartPolicy : Never containers : - name : configurator-dump-job image : ghcr.io/janssenproject/jans/configurator:$VERSION command : - /bin/sh - -c - | /app/scripts/entrypoint.sh dump sleep 300 envFrom : - configMapRef : name : config-cm Copy over the files to host kubectl cp configurator-dump-job:/app/db .", "title": "dump"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Docker image packaging for Fido2. Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_FIDO2_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_FIDO2_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file. Configure app loggers # App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"fido2_log_target\" : \"STDOUT\" , \"fido2_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"fido2_log_target\":\"STDOUT\",\"persistence_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", } Exposing metrics # As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "FIDO2"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#overview", "text": "Docker image packaging for Fido2.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_FIDO2_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_FIDO2_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#configure-app-loggers", "text": "App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"fido2_log_target\" : \"STDOUT\" , \"fido2_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"fido2_log_target\":\"STDOUT\",\"persistence_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure app loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#exposing-metrics", "text": "As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Exposing metrics"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/", "tags": ["administration", "installation", "quick-start", "docker compose", "docker image"], "text": "Warning This image is for testing and development purposes only. Use Janssen helm charts for production setups. Overview # Docker monolith image packaging for Janssen. This image packs janssen services including the auth-server, config-api, fido2, and scim. Pre-requisites # Docker Docker compose Environment Variables # Installation depends on the set of environment variables shown below. These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. ENV Description Default CN_HOSTNAME Hostname to install janssen with. demoexample.jans.io CN_ADMIN_PASS Password of the admin user. 1t5Fin3#security CN_ORG_NAME Organization name. Used for ssl cert generation. Janssen CN_EMAIL Email. Used for ssl cert generation. support@jans.io CN_CITY City. Used for ssl cert generation. Austin CN_STATE State. Used for ssl cert generation TX CN_COUNTRY Country. Used for ssl cert generation. US CN_INSTALL_MYSQL Install jans with mysql as the backend false CN_INSTALL_PGSQL Install jans with Postgres as the backend false CN_INSTALL_CONFIG_API Installs the Config API service. true CN_INSTALL_SCIM Installs the SCIM API service. true CN_INSTALL_FIDO2 Installs the FIDO2 API service. true RDBMS_DATABASE RDBMS jans database for MySQL or Postgres. jans RDBMS_USER RDBMS database user for MySQL or Postgres. jans RDBMS_PASSWORD RDBMS database user password for MySQL or Postgres. 1t5Fin3#security RDBMS_HOST RDBMS host for MySQL or Postgres. mysql which is the docker compose service name TEST_CLIENT_ID ID of test client in UUID which has all available scopes to access any jans API 9876baac-de39-4c23-8a78-674b59df8c09 TEST_CLIENT_SECRET Secret for test client 1t5Fin3#security TEST_CLIENT_TRUSTED Trust test client true TEST_CLIENT_REDIRECT_URI Not Implemented yet Redirect URI for test client. Multiple uri's with comma may be provided, if not provided redirect uris will be same as the config-api-client `` How to run # Download the compose file of your chosen persistence from mysql or postgres wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-mysql-compose.yml wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-postgres-compose.yml Download the script files wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/up.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/down.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/clean.sh Give execute permission to the scripts chmod u+x up.sh down.sh clean.sh This docker compose file runs two containers, the janssen monolith container and mysql container. To start the containers. ./up.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. To view the containers running docker compose -f jans-mysql-compose.yml ps To stop the containers. ./down.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. Configure Janssen Server # Access the Docker container shell using: docker compose -f jans-mysql-compose.yml exec jans /bin/bash #This opens a bash terminal in the running container You can grab client_id and client_pw (secret) pairs and other values from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Gluu flex as needed. For example you can run the TUI : python3 /opt/jans/jans-cli/config-cli-tui.py Access endpoints externally # Add to your /etc/hosts file the ip domain record which should be the ip of the instance docker is installed at and the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record you can hit endpoints such as https://demoexample.jans.io/.well-known/openid-configuration Clean up # Remove setup and volumes ./clean.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "Monolith"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#overview", "text": "Docker monolith image packaging for Janssen. This image packs janssen services including the auth-server, config-api, fido2, and scim.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#pre-requisites", "text": "Docker Docker compose", "title": "Pre-requisites"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#environment-variables", "text": "Installation depends on the set of environment variables shown below. These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. ENV Description Default CN_HOSTNAME Hostname to install janssen with. demoexample.jans.io CN_ADMIN_PASS Password of the admin user. 1t5Fin3#security CN_ORG_NAME Organization name. Used for ssl cert generation. Janssen CN_EMAIL Email. Used for ssl cert generation. support@jans.io CN_CITY City. Used for ssl cert generation. Austin CN_STATE State. Used for ssl cert generation TX CN_COUNTRY Country. Used for ssl cert generation. US CN_INSTALL_MYSQL Install jans with mysql as the backend false CN_INSTALL_PGSQL Install jans with Postgres as the backend false CN_INSTALL_CONFIG_API Installs the Config API service. true CN_INSTALL_SCIM Installs the SCIM API service. true CN_INSTALL_FIDO2 Installs the FIDO2 API service. true RDBMS_DATABASE RDBMS jans database for MySQL or Postgres. jans RDBMS_USER RDBMS database user for MySQL or Postgres. jans RDBMS_PASSWORD RDBMS database user password for MySQL or Postgres. 1t5Fin3#security RDBMS_HOST RDBMS host for MySQL or Postgres. mysql which is the docker compose service name TEST_CLIENT_ID ID of test client in UUID which has all available scopes to access any jans API 9876baac-de39-4c23-8a78-674b59df8c09 TEST_CLIENT_SECRET Secret for test client 1t5Fin3#security TEST_CLIENT_TRUSTED Trust test client true TEST_CLIENT_REDIRECT_URI Not Implemented yet Redirect URI for test client. Multiple uri's with comma may be provided, if not provided redirect uris will be same as the config-api-client ``", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#how-to-run", "text": "Download the compose file of your chosen persistence from mysql or postgres wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-mysql-compose.yml wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-postgres-compose.yml Download the script files wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/up.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/down.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/clean.sh Give execute permission to the scripts chmod u+x up.sh down.sh clean.sh This docker compose file runs two containers, the janssen monolith container and mysql container. To start the containers. ./up.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. To view the containers running docker compose -f jans-mysql-compose.yml ps To stop the containers. ./down.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "How to run"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#configure-janssen-server", "text": "Access the Docker container shell using: docker compose -f jans-mysql-compose.yml exec jans /bin/bash #This opens a bash terminal in the running container You can grab client_id and client_pw (secret) pairs and other values from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Gluu flex as needed. For example you can run the TUI : python3 /opt/jans/jans-cli/config-cli-tui.py", "title": "Configure Janssen Server"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#access-endpoints-externally", "text": "Add to your /etc/hosts file the ip domain record which should be the ip of the instance docker is installed at and the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record you can hit endpoints such as https://demoexample.jans.io/.well-known/openid-configuration", "title": "Access endpoints externally"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#clean-up", "text": "Remove setup and volumes ./clean.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "Clean up"}, {"location": "janssen-server/reference/kubernetes/docker-jans-persistence-loader/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Persistence is a special container to load initial data for supported persistence. Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_OXTRUST_CONFIG_GENERATION : Whether to generate oxShibboleth configuration or not (default to true ). CN_CACHE_TYPE : Supported values are IN_MEMORY , REDIS , MEMCACHED , and NATIVE_PERSISTENCE (default to NATIVE_PERSISTENCE ). CN_EXT_SIGNING_JWKS_URI : URI of external signing JWKS (default is \"\"). CN_REDIS_URL : URL of Redis server, format is host:port (optional; default to localhost:6379 ). CN_REDIS_TYPE : Redis service type, either STANDALONE or CLUSTER (optional; default to STANDALONE ). CN_MEMCACHED_URL : URL of Memcache server, format is host:port (optional; default to localhost:11211 ). CN_PERSISTENCE_TYPE : Persistence backend being used ( sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_PERSISTENCE_SKIP_INITIALIZED : skip initialization if backend already initialized (default to false ). CN_PERSISTENCE_UPDATE_AUTH_DYNAMIC_CONFIG : Whether to allow automatic updates of jans-auth configuration (default to true ). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_ADMIN_ID_FILE : Absolute path to file contains ID for admin user (default to /etc/jans/conf/jackrabbit_admin_id ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/gluu/conf/jackrabbit_admin_password ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_MESSAGE_TYPE : Message provider type (one of DISABLED , POSTGRES , and REDIS ; default to DISABLED ). Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Persistence"}, {"location": "janssen-server/reference/kubernetes/docker-jans-persistence-loader/#overview", "text": "Persistence is a special container to load initial data for supported persistence.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-persistence-loader/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-persistence-loader/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_OXTRUST_CONFIG_GENERATION : Whether to generate oxShibboleth configuration or not (default to true ). CN_CACHE_TYPE : Supported values are IN_MEMORY , REDIS , MEMCACHED , and NATIVE_PERSISTENCE (default to NATIVE_PERSISTENCE ). CN_EXT_SIGNING_JWKS_URI : URI of external signing JWKS (default is \"\"). CN_REDIS_URL : URL of Redis server, format is host:port (optional; default to localhost:6379 ). CN_REDIS_TYPE : Redis service type, either STANDALONE or CLUSTER (optional; default to STANDALONE ). CN_MEMCACHED_URL : URL of Memcache server, format is host:port (optional; default to localhost:11211 ). CN_PERSISTENCE_TYPE : Persistence backend being used ( sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_PERSISTENCE_SKIP_INITIALIZED : skip initialization if backend already initialized (default to false ). CN_PERSISTENCE_UPDATE_AUTH_DYNAMIC_CONFIG : Whether to allow automatic updates of jans-auth configuration (default to true ). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_ADMIN_ID_FILE : Absolute path to file contains ID for admin user (default to /etc/jans/conf/jackrabbit_admin_id ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/gluu/conf/jackrabbit_admin_password ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_MESSAGE_TYPE : Message provider type (one of DISABLED , POSTGRES , and REDIS ; default to DISABLED ).", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-persistence-loader/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Docker image packaging for SCIM. Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_SCIM_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SCIM_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file. Configure app loggers # App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"scim_log_target\" : \"STDOUT\" , \"scim_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"scim_log_target\":\"STDOUT\",\"persistence_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", } Exposing metrics # As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "SCIM"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#overview", "text": "Docker image packaging for SCIM.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_SCIM_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SCIM_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#configure-app-loggers", "text": "App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"scim_log_target\" : \"STDOUT\" , \"scim_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"scim_log_target\":\"STDOUT\",\"persistence_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure app loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#exposing-metrics", "text": "As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Exposing metrics"}, {"location": "janssen-server/reference/kubernetes/helm-chart/", "tags": ["administration", "reference", "kubernetes"], "text": "janssen # Janssen Access and Identity Management Microservices Chart. This chart deploys each janssen microservice as a separate deployment. Homepage: https://jans.io Maintainers # Name Email Url moabu support@jans.io Source Code # https://jans.io https://github.com/JanssenProject/jans/charts/janssen Requirements # Kubernetes: >=v1.22.0-0 Repository Name Version auth-server 0.0.0-nightly auth-server-key-rotation 0.0.0-nightly casa 0.0.0-nightly cn-istio-ingress 0.0.0-nightly config 0.0.0-nightly config-api 0.0.0-nightly fido2 0.0.0-nightly kc-scheduler 0.0.0-nightly link 0.0.0-nightly nginx-ingress 0.0.0-nightly persistence 0.0.0-nightly saml 0.0.0-nightly scim 0.0.0-nightly Values # Key Type Default Description auth-server object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/auth-server\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"},\"requests\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} OAuth Authorization Server, the OpenID Connect Provider, the UMA Authorization Server--this is the main Internet facing component of Janssen. It's the service that returns tokens, JWT's and identity assertions. This service must be Internet facing. auth-server-key-rotation object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/certmanager\",\"tag\":\"0.0.0-nightly\"},\"keysLife\":48,\"keysPushDelay\":0,\"keysPushStrategy\":\"NEWER\",\"keysStrategy\":\"NEWER\",\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Responsible for regenerating auth-keys per x hours auth-server-key-rotation.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of auth-server-key-rotation.additionalLabels object {} Additional labels that will be added across the gateway in the format of auth-server-key-rotation.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. auth-server-key-rotation.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh auth-server-key-rotation.dnsConfig object {} Add custom dns config auth-server-key-rotation.dnsPolicy string \"\" Add custom dns policy auth-server-key-rotation.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. auth-server-key-rotation.image.pullSecrets list [] Image Pull Secrets auth-server-key-rotation.image.repository string \"ghcr.io/janssenproject/jans/certmanager\" Image to use for deploying. auth-server-key-rotation.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. auth-server-key-rotation.keysLife int 48 Auth server key rotation keys life in hours auth-server-key-rotation.keysPushDelay int 0 Delay (in seconds) before pushing private keys to Auth server auth-server-key-rotation.keysPushStrategy string \"NEWER\" Set key selection strategy after pushing private keys to Auth server (only takes effect when keysPushDelay value is greater than 0) auth-server-key-rotation.keysStrategy string \"NEWER\" Set key selection strategy used by Auth server auth-server-key-rotation.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. auth-server-key-rotation.resources.limits.cpu string \"300m\" CPU limit. auth-server-key-rotation.resources.limits.memory string \"300Mi\" Memory limit. auth-server-key-rotation.resources.requests.cpu string \"300m\" CPU request. auth-server-key-rotation.resources.requests.memory string \"300Mi\" Memory request. auth-server-key-rotation.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service auth-server-key-rotation.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 auth-server-key-rotation.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 auth-server-key-rotation.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers auth-server-key-rotation.volumes list [] Configure any additional volumes that need to be attached to the pod auth-server.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of auth-server.additionalLabels object {} Additional labels that will be added across the gateway in the format of auth-server.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. auth-server.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh auth-server.dnsConfig object {} Add custom dns config auth-server.dnsPolicy string \"\" Add custom dns policy auth-server.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler auth-server.hpa.behavior object {} Scaling Policies auth-server.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set auth-server.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. auth-server.image.pullSecrets list [] Image Pull Secrets auth-server.image.repository string \"ghcr.io/janssenproject/jans/auth-server\" Image to use for deploying. auth-server.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. auth-server.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. auth-server.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} Executes the python3 healthcheck. https://github.com/JanssenProject/docker-jans-auth-server/blob/master/scripts/healthcheck.py auth-server.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget auth-server.readinessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the readiness healthcheck for the auth server if needed. https://github.com/JanssenProject/docker-jans-auth-server/blob/master/scripts/healthcheck.py auth-server.replicas int 1 Service replica number. auth-server.resources object {\"limits\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"},\"requests\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"}} Resource specs. auth-server.resources.limits.cpu string \"2500m\" CPU limit. auth-server.resources.limits.memory string \"2500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. auth-server.resources.requests.cpu string \"2500m\" CPU request. auth-server.resources.requests.memory string \"2500Mi\" Memory request. auth-server.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ auth-server.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service auth-server.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 auth-server.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 auth-server.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers auth-server.volumes list [] Configure any additional volumes that need to be attached to the pod casa object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/casa\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Janssen Casa (\"Casa\") is a self-service web portal for end-users to manage authentication and authorization preferences for their account in a Janssen Auth Server. casa.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of casa.additionalLabels object {} Additional labels that will be added across the gateway in the format of casa.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. casa.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh casa.dnsConfig object {} Add custom dns config casa.dnsPolicy string \"\" Add custom dns policy casa.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler casa.hpa.behavior object {} Scaling Policies casa.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set casa.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. casa.image.pullSecrets list [] Image Pull Secrets casa.image.repository string \"ghcr.io/janssenproject/jans/casa\" Image to use for deploying. casa.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. casa.livenessProbe object {\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the liveness healthcheck for casa if needed. casa.livenessProbe.httpGet.path string \"/jans-casa/health-check\" http liveness probe endpoint casa.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget casa.readinessProbe object {\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the readiness healthcheck for the casa if needed. casa.readinessProbe.httpGet.path string \"/jans-casa/health-check\" http readiness probe endpoint casa.replicas int 1 Service replica number. casa.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}} Resource specs. casa.resources.limits.cpu string \"500m\" CPU limit. casa.resources.limits.memory string \"500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. casa.resources.requests.cpu string \"500m\" CPU request. casa.resources.requests.memory string \"500Mi\" Memory request. casa.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ casa.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service casa.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 casa.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 casa.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers casa.volumes list [] Configure any additional volumes that need to be attached to the pod config object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"adminPassword\":\"Test1234#\",\"city\":\"Austin\",\"configmap\":{\"cnAwsAccessKeyId\":\"\",\"cnAwsDefaultRegion\":\"us-west-1\",\"cnAwsProfile\":\"janssen\",\"cnAwsSecretAccessKey\":\"\",\"cnAwsSecretsEndpointUrl\":\"\",\"cnAwsSecretsNamePrefix\":\"janssen\",\"cnAwsSecretsReplicaRegions\":[],\"cnCacheType\":\"NATIVE_PERSISTENCE\",\"cnConfigKubernetesConfigMap\":\"cn\",\"cnGoogleProjectId\":\"google-project-to-save-config-and-secrets-to\",\"cnGoogleSecretManagerServiceAccount\":\"SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo=\",\"cnGoogleSecretNamePrefix\":\"janssen\",\"cnGoogleSecretVersionId\":\"latest\",\"cnJettyRequestHeaderSize\":8192,\"cnMaxRamPercent\":\"75.0\",\"cnMessageType\":\"DISABLED\",\"cnOpaUrl\":\"http://opa.opa.svc.cluster.cluster.local:8181/v1\",\"cnPersistenceHybridMapping\":\"{}\",\"cnRedisSentinelGroup\":\"\",\"cnRedisSslTruststore\":\"\",\"cnRedisType\":\"STANDALONE\",\"cnRedisUrl\":\"redis.redis.svc.cluster.local:6379\",\"cnRedisUseSsl\":false,\"cnScimProtectionMode\":\"OAUTH\",\"cnSecretKubernetesSecret\":\"cn\",\"cnSqlDbDialect\":\"mysql\",\"cnSqlDbHost\":\"my-release-mysql.default.svc.cluster.local\",\"cnSqlDbName\":\"jans\",\"cnSqlDbPort\":3306,\"cnSqlDbSchema\":\"\",\"cnSqlDbTimezone\":\"UTC\",\"cnSqlDbUser\":\"jans\",\"cnSqldbUserPassword\":\"Test1234#\",\"cnVaultAddr\":\"http://localhost:8200\",\"cnVaultAppRolePath\":\"approle\",\"cnVaultKvPath\":\"secret\",\"cnVaultNamespace\":\"\",\"cnVaultPrefix\":\"jans\",\"cnVaultRoleId\":\"\",\"cnVaultRoleIdFile\":\"/etc/certs/vault_role_id\",\"cnVaultSecretId\":\"\",\"cnVaultSecretIdFile\":\"/etc/certs/vault_secret_id\",\"cnVaultVerify\":false,\"kcAdminPassword\":\"Test1234#\",\"kcAdminUsername\":\"admin\",\"kcDbPassword\":\"Test1234#\",\"kcDbSchema\":\"keycloak\",\"kcDbUrlDatabase\":\"keycloak\",\"kcDbUrlHost\":\"mysql.kc.svc.cluster.local\",\"kcDbUrlPort\":3306,\"kcDbUrlProperties\":\"?useUnicode=true&characterEncoding=UTF-8&character_set_server=utf8mb4\",\"kcDbUsername\":\"keycloak\",\"kcDbVendor\":\"mysql\",\"kcLogLevel\":\"INFO\",\"lbAddr\":\"\",\"quarkusTransactionEnableRecovery\":true},\"countryCode\":\"US\",\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"email\":\"support@jans.io\",\"image\":{\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/configurator\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"orgName\":\"Janssen\",\"redisPassword\":\"P@assw0rd\",\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"salt\":\"\",\"state\":\"TX\",\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Configuration parameters for setup and initial configuration secret and config layers used by Janssen services. config-api object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/config-api\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"jans-config-api/api/v1/health/ready\",\"port\":8074},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Config Api endpoints can be used to configure the auth-server, which is an open-source OpenID Connect Provider (OP) and UMA Authorization Server (AS). config-api.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of config-api.additionalLabels object {} Additional labels that will be added across the gateway in the format of config-api.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. config-api.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh config-api.dnsConfig object {} Add custom dns config config-api.dnsPolicy string \"\" Add custom dns policy config-api.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler config-api.hpa.behavior object {} Scaling Policies config-api.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set config-api.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. config-api.image.pullSecrets list [] Image Pull Secrets config-api.image.repository string \"ghcr.io/janssenproject/jans/config-api\" Image to use for deploying. config-api.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. config-api.livenessProbe object {\"httpGet\":{\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. config-api.livenessProbe.httpGet object {\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074} http liveness probe endpoint config-api.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget config-api.readinessProbe.httpGet object {\"path\":\"jans-config-api/api/v1/health/ready\",\"port\":8074} http readiness probe endpoint config-api.replicas int 1 Service replica number. config-api.resources object {\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}} Resource specs. config-api.resources.limits.cpu string \"1000m\" CPU limit. config-api.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. config-api.resources.requests.cpu string \"1000m\" CPU request. config-api.resources.requests.memory string \"1200Mi\" Memory request. config-api.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ config-api.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service config-api.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 config-api.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 config-api.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers config-api.volumes list [] Configure any additional volumes that need to be attached to the pod config.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of config.adminPassword string \"Test1234#\" Admin password to log in to the UI. config.city string \"Austin\" City. Used for certificate creation. config.configmap.cnCacheType string \"NATIVE_PERSISTENCE\" Cache type. NATIVE_PERSISTENCE , REDIS . or IN_MEMORY . Defaults to NATIVE_PERSISTENCE . config.configmap.cnConfigKubernetesConfigMap string \"cn\" The name of the Kubernetes ConfigMap that will hold the configuration layer config.configmap.cnGoogleProjectId string \"google-project-to-save-config-and-secrets-to\" Project id of the Google project the secret manager belongs to. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretManagerServiceAccount string \"SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo=\" Service account with roles roles/secretmanager.admin base64 encoded string. This is used often inside the services to reach the configuration layer. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretNamePrefix string \"janssen\" Prefix for Janssen secret in Google Secret Manager. Defaults to janssen. If left janssen-secret secret will be created. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretVersionId string \"latest\" Secret version to be used for secret configuration. Defaults to latest and should normally always stay that way. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnJettyRequestHeaderSize int 8192 Jetty header size in bytes in the auth server config.configmap.cnMaxRamPercent string \"75.0\" Value passed to Java option -XX:MaxRAMPercentage config.configmap.cnMessageType string \"DISABLED\" Message type (one of POSTGRES, REDIS, or DISABLED) config.configmap.cnOpaUrl string \"http://opa.opa.svc.cluster.cluster.local:8181/v1\" URL of OPA API config.configmap.cnPersistenceHybridMapping string \"{}\" Specify data that should be saved in persistence (one of default, user, cache, site, token, or session; default to default). Note this environment only takes effect when global.cnPersistenceType is set to hybrid . config.configmap.cnRedisSentinelGroup string \"\" Redis Sentinel Group. Often set when config.configmap.cnRedisType is set to SENTINEL . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisSslTruststore string \"\" Redis SSL truststore. Optional. Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisType string \"STANDALONE\" Redis service type. STANDALONE or CLUSTER . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisUrl string \"redis.redis.svc.cluster.local:6379\" Redis URL and port number : . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisUseSsl bool false Boolean to use SSL in Redis. Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnScimProtectionMode string \"OAUTH\" SCIM protection mode OAUTH config.configmap.cnSecretKubernetesSecret string \"cn\" Kubernetes secret name holding configuration keys. Used when global.configSecretAdapter is set to kubernetes which is the default. config.configmap.cnSqlDbDialect string \"mysql\" SQL database dialect. mysql or pgsql config.configmap.cnSqlDbHost string \"my-release-mysql.default.svc.cluster.local\" SQL database host uri. config.configmap.cnSqlDbName string \"jans\" SQL database name. config.configmap.cnSqlDbPort int 3306 SQL database port. config.configmap.cnSqlDbSchema string \"\" Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). config.configmap.cnSqlDbTimezone string \"UTC\" SQL database timezone. config.configmap.cnSqlDbUser string \"jans\" SQL database username. config.configmap.cnSqldbUserPassword string \"Test1234#\" SQL password injected the secrets . config.configmap.cnVaultAddr string \"http://localhost:8200\" Base URL of Vault. config.configmap.cnVaultAppRolePath string \"approle\" Path to Vault AppRole. config.configmap.cnVaultKvPath string \"secret\" Path to Vault KV secrets engine. config.configmap.cnVaultNamespace string \"\" Vault namespace used to access the secrets. config.configmap.cnVaultPrefix string \"jans\" Base prefix name used to access secrets. config.configmap.cnVaultRoleId string \"\" Vault AppRole RoleID. config.configmap.cnVaultRoleIdFile string \"/etc/certs/vault_role_id\" Path to file contains Vault AppRole role ID. config.configmap.cnVaultSecretId string \"\" Vault AppRole SecretID. config.configmap.cnVaultSecretIdFile string \"/etc/certs/vault_secret_id\" Path to file contains Vault AppRole secret ID. config.configmap.cnVaultVerify bool false Verify connection to Vault. config.configmap.kcAdminPassword string \"Test1234#\" Keycloak admin UI password config.configmap.kcAdminUsername string \"admin\" Keycloak admin UI username config.configmap.kcDbPassword string \"Test1234#\" Password for Keycloak database access config.configmap.kcDbSchema string \"keycloak\" Keycloak database schema name (note that PostgreSQL may be using \"public\" schema). config.configmap.kcDbUrlDatabase string \"keycloak\" Keycloak database name. config.configmap.kcDbUrlHost string \"mysql.kc.svc.cluster.local\" Keycloak database host uri config.configmap.kcDbUrlPort int 3306 Keycloak database port (default to port 3306 for mysql). config.configmap.kcDbUrlProperties string \"?useUnicode=true&characterEncoding=UTF-8&character_set_server=utf8mb4\" Keycloak database connection properties. If using postgresql, the value can be set to empty string. config.configmap.kcDbUsername string \"keycloak\" Keycloak database username config.configmap.kcDbVendor string \"mysql\" Keycloak database vendor name (default to MySQL server). To use PostgreSQL server, change the value to postgres. config.configmap.kcLogLevel string \"INFO\" Keycloak logging level config.configmap.lbAddr string \"\" Load balancer address for AWS if the FQDN is not registered. config.configmap.quarkusTransactionEnableRecovery bool true Quarkus transaction recovery. When using MySQL, there could be issue regarding XA_RECOVER_ADMIN; refer to https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_xa-recover-admin for details. config.countryCode string \"US\" Country code. Used for certificate creation. config.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. config.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh config.dnsConfig object {} Add custom dns config config.dnsPolicy string \"\" Add custom dns policy config.email string \"support@jans.io\" Email address of the administrator usually. Used for certificate creation. config.image.pullSecrets list [] Image Pull Secrets config.image.repository string \"ghcr.io/janssenproject/jans/configurator\" Image to use for deploying. config.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. config.orgName string \"Janssen\" Organization name. Used for certificate creation. config.redisPassword string \"P@assw0rd\" Redis admin password if config.configmap.cnCacheType is set to REDIS . config.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. config.resources.limits.cpu string \"300m\" CPU limit. config.resources.limits.memory string \"300Mi\" Memory limit. config.resources.requests.cpu string \"300m\" CPU request. config.resources.requests.memory string \"300Mi\" Memory request. config.salt string \"\" Salt. Used for encoding/decoding sensitive data. If omitted or set to empty string, the value will be self-generated. Otherwise, a 24 alphanumeric characters are allowed as its value. config.state string \"TX\" State code. Used for certificate creation. config.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service. config.usrEnvs.normal object {} Add custom normal envs to the service. variable1: value1 config.usrEnvs.secret object {} Add custom secret envs to the service. variable1: value1 config.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers config.volumes list [] Configure any additional volumes that need to be attached to the pod fido2 object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/fido2\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}},\"service\":{\"name\":\"http-fido2\",\"port\":8080},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} FIDO 2.0 (FIDO2) is an open authentication standard that enables leveraging common devices to authenticate to online services in both mobile and desktop environments. fido2.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of fido2.additionalLabels object {} Additional labels that will be added across the gateway in the format of fido2.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. fido2.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh fido2.dnsConfig object {} Add custom dns config fido2.dnsPolicy string \"\" Add custom dns policy fido2.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler fido2.hpa.behavior object {} Scaling Policies fido2.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set fido2.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. fido2.image.pullSecrets list [] Image Pull Secrets fido2.image.repository string \"ghcr.io/janssenproject/jans/fido2\" Image to use for deploying. fido2.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. fido2.livenessProbe object {\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the liveness healthcheck for the fido2 if needed. fido2.livenessProbe.httpGet object {\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"} http liveness probe endpoint fido2.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget fido2.readinessProbe object {\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the readiness healthcheck for the fido2 if needed. fido2.replicas int 1 Service replica number. fido2.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}} Resource specs. fido2.resources.limits.cpu string \"500m\" CPU limit. fido2.resources.limits.memory string \"500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. fido2.resources.requests.cpu string \"500m\" CPU request. fido2.resources.requests.memory string \"500Mi\" Memory request. fido2.service.name string \"http-fido2\" The name of the fido2 port within the fido2 service. Please keep it as default. fido2.service.port int 8080 Port of the fido2 service. Please keep it as default. fido2.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ fido2.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service fido2.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 fido2.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 fido2.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers fido2.volumes list [] Configure any additional volumes that need to be attached to the pod global object {\"alb\":{\"ingress\":false},\"auth-server\":{\"appLoggers\":{\"auditStatsLogLevel\":\"INFO\",\"auditStatsLogTarget\":\"FILE\",\"authLogLevel\":\"INFO\",\"authLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"httpLogLevel\":\"INFO\",\"httpLogTarget\":\"FILE\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"authEncKeys\":\"RSA1_5 RSA-OAEP\",\"authServerServiceName\":\"auth-server\",\"authSigKeys\":\"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\",\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"authServerAdditionalAnnotations\":{},\"authServerEnabled\":true,\"authServerLabels\":{},\"deviceCodeAdditionalAnnotations\":{},\"deviceCodeEnabled\":true,\"deviceCodeLabels\":{},\"firebaseMessagingAdditionalAnnotations\":{},\"firebaseMessagingEnabled\":true,\"firebaseMessagingLabels\":{},\"lockAdditionalAnnotations\":{},\"lockConfigAdditionalAnnotations\":{},\"lockConfigEnabled\":false,\"lockConfigLabels\":{},\"lockEnabled\":false,\"lockLabels\":{},\"openidAdditionalAnnotations\":{},\"openidConfigEnabled\":true,\"openidConfigLabels\":{},\"u2fAdditionalAnnotations\":{},\"u2fConfigEnabled\":true,\"u2fConfigLabels\":{},\"uma2AdditionalAnnotations\":{},\"uma2ConfigEnabled\":true,\"uma2ConfigLabels\":{},\"webdiscoveryAdditionalAnnotations\":{},\"webdiscoveryEnabled\":true,\"webdiscoveryLabels\":{},\"webfingerAdditionalAnnotations\":{},\"webfingerEnabled\":true,\"webfingerLabels\":{}},\"lockEnabled\":false},\"auth-server-key-rotation\":{\"customAnnotations\":{\"cronjob\":{},\"secret\":{},\"service\":{}},\"enabled\":true,\"initKeysLife\":48},\"awsStorageType\":\"io1\",\"azureStorageAccountType\":\"Standard_LRS\",\"azureStorageKind\":\"Managed\",\"casa\":{\"appLoggers\":{\"casaLogLevel\":\"INFO\",\"casaLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"timerLogLevel\":\"INFO\",\"timerLogTarget\":\"FILE\"},\"casaServiceName\":\"casa\",\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"casaAdditionalAnnotations\":{},\"casaEnabled\":false,\"casaLabels\":{}}},\"cloud\":{\"testEnviroment\":false},\"cnAwsConfigFile\":\"/etc/jans/conf/aws_config_file\",\"cnAwsSecretsReplicaRegionsFile\":\"/etc/jans/conf/aws_secrets_replica_regions\",\"cnAwsSharedCredentialsFile\":\"/etc/jans/conf/aws_shared_credential_file\",\"cnConfiguratorConfigurationFile\":\"/etc/jans/conf/configuration.json\",\"cnConfiguratorCustomSchema\":{\"secretName\":\"\"},\"cnConfiguratorDumpFile\":\"/etc/jans/conf/configuration.out.json\",\"cnDocumentStoreType\":\"DB\",\"cnGoogleApplicationCredentials\":\"/etc/jans/conf/google-credentials.json\",\"cnPersistenceType\":\"sql\",\"cnPrometheusPort\":\"\",\"cnSqlPasswordFile\":\"/etc/jans/conf/sql_password\",\"config\":{\"customAnnotations\":{\"clusterRoleBinding\":{},\"configMap\":{},\"job\":{},\"role\":{},\"roleBinding\":{},\"secret\":{},\"service\":{},\"serviceAccount\":{}},\"enabled\":true},\"config-api\":{\"appLoggers\":{\"configApiLogLevel\":\"INFO\",\"configApiLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"configApiServerServiceName\":\"config-api\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"configApiAdditionalAnnotations\":{},\"configApiEnabled\":true,\"configApiLabels\":{}},\"plugins\":\"fido2,scim,user-mgt\"},\"configAdapterName\":\"kubernetes\",\"configSecretAdapter\":\"kubernetes\",\"fido2\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"fido2LogLevel\":\"INFO\",\"fido2LogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"fido2ServiceName\":\"fido2\",\"ingress\":{\"fido2AdditionalAnnotations\":{},\"fido2ConfigAdditionalAnnotations\":{},\"fido2ConfigEnabled\":false,\"fido2ConfigLabels\":{},\"fido2Enabled\":false,\"fido2Labels\":{}}},\"fqdn\":\"demoexample.jans.io\",\"gcePdStorageType\":\"pd-standard\",\"isFqdnRegistered\":false,\"istio\":{\"additionalAnnotations\":{},\"additionalLabels\":{},\"enabled\":false,\"gateways\":[],\"ingress\":false,\"namespace\":\"istio-system\"},\"jobTtlSecondsAfterFinished\":300,\"kc-scheduler\":{\"enabled\":false},\"lbIp\":\"22.22.22.22\",\"link\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"linkLogLevel\":\"INFO\",\"linkLogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"service\":{},\"virtualService\":{}},\"enabled\":false,\"ingress\":{\"linkEnabled\":true},\"linkServiceName\":\"link\"},\"nginx-ingress\":{\"enabled\":true},\"persistence\":{\"customAnnotations\":{\"job\":{},\"secret\":{},\"service\":{}},\"enabled\":true},\"saml\":{\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":false,\"ingress\":{\"samlAdditionalAnnotations\":{},\"samlEnabled\":false,\"samlLabels\":{}},\"samlServiceName\":\"saml\"},\"scim\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scimLogLevel\":\"INFO\",\"scimLogTarget\":\"STDOUT\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"scimAdditionalAnnotations\":{},\"scimConfigAdditionalAnnotations\":{},\"scimConfigEnabled\":false,\"scimConfigLabels\":{},\"scimEnabled\":false,\"scimLabels\":{}},\"scimServiceName\":\"scim\"},\"serviceAccountName\":\"default\",\"storageClass\":{\"allowVolumeExpansion\":true,\"allowedTopologies\":[],\"mountOptions\":[\"debug\"],\"parameters\":{},\"provisioner\":\"microk8s.io/hostpath\",\"reclaimPolicy\":\"Retain\",\"volumeBindingMode\":\"WaitForFirstConsumer\"},\"usrEnvs\":{\"normal\":{},\"secret\":{}}} Parameters used globally across all services helm charts. global.alb.ingress bool false Activates ALB ingress global.auth-server-key-rotation.enabled bool true Boolean flag to enable/disable the auth-server-key rotation cronjob chart. global.auth-server-key-rotation.initKeysLife int 48 The initial auth server key rotation keys life in hours global.auth-server.appLoggers object {\"auditStatsLogLevel\":\"INFO\",\"auditStatsLogTarget\":\"FILE\",\"authLogLevel\":\"INFO\",\"authLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"httpLogLevel\":\"INFO\",\"httpLogTarget\":\"FILE\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.auth-server.appLoggers.auditStatsLogLevel string \"INFO\" jans-auth_audit.log level global.auth-server.appLoggers.auditStatsLogTarget string \"FILE\" jans-auth_script.log target global.auth-server.appLoggers.authLogLevel string \"INFO\" jans-auth.log level global.auth-server.appLoggers.authLogTarget string \"STDOUT\" jans-auth.log target global.auth-server.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e auth-server-script ===> 2022-12-20 17:49:55,744 INFO global.auth-server.appLoggers.httpLogLevel string \"INFO\" http_request_response.log level global.auth-server.appLoggers.httpLogTarget string \"FILE\" http_request_response.log target global.auth-server.appLoggers.persistenceDurationLogLevel string \"INFO\" jans-auth_persistence_duration.log level global.auth-server.appLoggers.persistenceDurationLogTarget string \"FILE\" jans-auth_persistence_duration.log target global.auth-server.appLoggers.persistenceLogLevel string \"INFO\" jans-auth_persistence.log level global.auth-server.appLoggers.persistenceLogTarget string \"FILE\" jans-auth_persistence.log target global.auth-server.appLoggers.scriptLogLevel string \"INFO\" jans-auth_script.log level global.auth-server.appLoggers.scriptLogTarget string \"FILE\" jans-auth_script.log target global.auth-server.authEncKeys string \"RSA1_5 RSA-OAEP\" space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) global.auth-server.authServerServiceName string \"auth-server\" Name of the auth-server service. Please keep it as default. global.auth-server.authSigKeys string \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) global.auth-server.cnCustomJavaOptions string \"\" passing custom java options to auth-server. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.auth-server.enabled bool true Boolean flag to enable/disable auth-server chart. You should never set this to false. global.auth-server.ingress object {\"authServerAdditionalAnnotations\":{},\"authServerEnabled\":true,\"authServerLabels\":{},\"deviceCodeAdditionalAnnotations\":{},\"deviceCodeEnabled\":true,\"deviceCodeLabels\":{},\"firebaseMessagingAdditionalAnnotations\":{},\"firebaseMessagingEnabled\":true,\"firebaseMessagingLabels\":{},\"lockAdditionalAnnotations\":{},\"lockConfigAdditionalAnnotations\":{},\"lockConfigEnabled\":false,\"lockConfigLabels\":{},\"lockEnabled\":false,\"lockLabels\":{},\"openidAdditionalAnnotations\":{},\"openidConfigEnabled\":true,\"openidConfigLabels\":{},\"u2fAdditionalAnnotations\":{},\"u2fConfigEnabled\":true,\"u2fConfigLabels\":{},\"uma2AdditionalAnnotations\":{},\"uma2ConfigEnabled\":true,\"uma2ConfigLabels\":{},\"webdiscoveryAdditionalAnnotations\":{},\"webdiscoveryEnabled\":true,\"webdiscoveryLabels\":{},\"webfingerAdditionalAnnotations\":{},\"webfingerEnabled\":true,\"webfingerLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.auth-server.ingress.authServerAdditionalAnnotations object {} Auth server ingress resource additional annotations. global.auth-server.ingress.authServerEnabled bool true Enable Auth server endpoints /jans-auth global.auth-server.ingress.authServerLabels object {} Auth server ingress resource labels. key app is taken global.auth-server.ingress.deviceCodeAdditionalAnnotations object {} device-code ingress resource additional annotations. global.auth-server.ingress.deviceCodeEnabled bool true Enable endpoint /device-code global.auth-server.ingress.deviceCodeLabels object {} device-code ingress resource labels. key app is taken global.auth-server.ingress.firebaseMessagingAdditionalAnnotations object {} Firebase Messaging ingress resource additional annotations. global.auth-server.ingress.firebaseMessagingEnabled bool true Enable endpoint /firebase-messaging-sw.js global.auth-server.ingress.firebaseMessagingLabels object {} Firebase Messaging ingress resource labels. key app is taken global.auth-server.ingress.lockAdditionalAnnotations object {} Lock ingress resource additional annotations. global.auth-server.ingress.lockConfigAdditionalAnnotations object {} Lock config ingress resource additional annotations. global.auth-server.ingress.lockConfigEnabled bool false Enable endpoint /.well-known/lock-server-configuration global.auth-server.ingress.lockConfigLabels object {} Lock config ingress resource labels. key app is taken global.auth-server.ingress.lockEnabled bool false Enable endpoint /jans-lock global.auth-server.ingress.lockLabels object {} Lock ingress resource labels. key app is taken global.auth-server.ingress.openidAdditionalAnnotations object {} openid-configuration ingress resource additional annotations. global.auth-server.ingress.openidConfigEnabled bool true Enable endpoint /.well-known/openid-configuration global.auth-server.ingress.openidConfigLabels object {} openid-configuration ingress resource labels. key app is taken global.auth-server.ingress.u2fAdditionalAnnotations object {} u2f config ingress resource additional annotations. global.auth-server.ingress.u2fConfigEnabled bool true Enable endpoint /.well-known/fido-configuration global.auth-server.ingress.u2fConfigLabels object {} u2f config ingress resource labels. key app is taken global.auth-server.ingress.uma2AdditionalAnnotations object {} uma2 config ingress resource additional annotations. global.auth-server.ingress.uma2ConfigEnabled bool true Enable endpoint /.well-known/uma2-configuration global.auth-server.ingress.uma2ConfigLabels object {} uma2 config ingress resource labels. key app is taken global.auth-server.ingress.webdiscoveryAdditionalAnnotations object {} webdiscovery ingress resource additional annotations. global.auth-server.ingress.webdiscoveryEnabled bool true Enable endpoint /.well-known/simple-web-discovery global.auth-server.ingress.webdiscoveryLabels object {} webdiscovery ingress resource labels. key app is taken global.auth-server.ingress.webfingerAdditionalAnnotations object {} webfinger ingress resource additional annotations. global.auth-server.ingress.webfingerEnabled bool true Enable endpoint /.well-known/webfinger global.auth-server.ingress.webfingerLabels object {} webfinger ingress resource labels. key app is taken global.auth-server.lockEnabled bool false Enable jans-lock as service running inside auth-server global.awsStorageType string \"io1\" Volume storage type if using AWS volumes. global.azureStorageAccountType string \"Standard_LRS\" Volume storage type if using Azure disks. global.azureStorageKind string \"Managed\" Azure storage kind if using Azure disks global.casa.appLoggers object {\"casaLogLevel\":\"INFO\",\"casaLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"timerLogLevel\":\"INFO\",\"timerLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.casa.appLoggers.casaLogLevel string \"INFO\" casa.log level global.casa.appLoggers.casaLogTarget string \"STDOUT\" casa.log target global.casa.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e casa ===> 2022-12-20 17:49:55,744 INFO global.casa.appLoggers.timerLogLevel string \"INFO\" casa timer log level global.casa.appLoggers.timerLogTarget string \"FILE\" casa timer log target global.casa.casaServiceName string \"casa\" Name of the casa service. Please keep it as default. global.casa.cnCustomJavaOptions string \"\" passing custom java options to casa. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.casa.enabled bool true Boolean flag to enable/disable the casa chart. global.casa.ingress object {\"casaAdditionalAnnotations\":{},\"casaEnabled\":false,\"casaLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.casa.ingress.casaAdditionalAnnotations object {} Casa ingress resource additional annotations. global.casa.ingress.casaEnabled bool false Enable casa endpoints /casa global.casa.ingress.casaLabels object {} Casa ingress resource labels. key app is taken global.cloud.testEnviroment bool false Boolean flag if enabled will strip resources requests and limits from all services. global.cnConfiguratorConfigurationFile string \"/etc/jans/conf/configuration.json\" Path to configuration schema file global.cnConfiguratorCustomSchema object {\"secretName\":\"\"} Use custom configuration schema in existing secrets. Note, the secrets has to contain the key configuration.json or any basename as specified in cnConfiguratorConfigurationFile. global.cnConfiguratorCustomSchema.secretName string \"\" The name of the secrets used for storing custom configuration schema. global.cnConfiguratorDumpFile string \"/etc/jans/conf/configuration.out.json\" Path to dumped configuration schema file global.cnDocumentStoreType string \"DB\" Document store type to use for shibboleth files DB. global.cnGoogleApplicationCredentials string \"/etc/jans/conf/google-credentials.json\" Base64 encoded service account. The sa must have roles/secretmanager.admin to use Google secrets. Leave as this is a sensible default. global.cnPersistenceType string \"sql\" Persistence backend to run Janssen with hybrid global.cnPrometheusPort string \"\" Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. global.cnSqlPasswordFile string \"/etc/jans/conf/sql_password\" Path to SQL password file global.config-api.appLoggers object {\"configApiLogLevel\":\"INFO\",\"configApiLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.config-api.appLoggers.configApiLogLevel string \"INFO\" configapi.log level global.config-api.appLoggers.configApiLogTarget string \"STDOUT\" configapi.log target global.config-api.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e config-api_persistence ===> 2022-12-20 17:49:55,744 INFO global.config-api.appLoggers.persistenceDurationLogLevel string \"INFO\" config-api_persistence_duration.log level global.config-api.appLoggers.persistenceDurationLogTarget string \"FILE\" config-api_persistence_duration.log target global.config-api.appLoggers.persistenceLogLevel string \"INFO\" config-api_persistence.log level global.config-api.appLoggers.persistenceLogTarget string \"FILE\" config-api_persistence.log target global.config-api.appLoggers.scriptLogLevel string \"INFO\" config-api_script.log level global.config-api.appLoggers.scriptLogTarget string \"FILE\" config-api_script.log target global.config-api.cnCustomJavaOptions string \"\" passing custom java options to config-api. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.config-api.configApiServerServiceName string \"config-api\" Name of the config-api service. Please keep it as default. global.config-api.enabled bool true Boolean flag to enable/disable the config-api chart. global.config-api.ingress object {\"configApiAdditionalAnnotations\":{},\"configApiEnabled\":true,\"configApiLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.config-api.ingress.configApiAdditionalAnnotations object {} ConfigAPI ingress resource additional annotations. global.config-api.ingress.configApiLabels object {} configAPI ingress resource labels. key app is taken global.config-api.plugins string \"fido2,scim,user-mgt\" Comma-separated values of enabled plugins (supported plugins are \"admin-ui\",\"fido2\",\"scim\",\"user-mgt\",\"jans-link\",\"kc-saml\") global.config.enabled bool true Boolean flag to enable/disable the configuration chart. This normally should never be false global.configAdapterName string \"kubernetes\" The config backend adapter that will hold Janssen configuration layer. aws global.configSecretAdapter string \"kubernetes\" The config backend adapter that will hold Janssen secret layer. vault global.fido2.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"fido2LogLevel\":\"INFO\",\"fido2LogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.fido2.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e fido2 ===> 2022-12-20 17:49:55,744 INFO global.fido2.appLoggers.fido2LogLevel string \"INFO\" fido2.log level global.fido2.appLoggers.fido2LogTarget string \"STDOUT\" fido2.log target global.fido2.appLoggers.persistenceDurationLogLevel string \"INFO\" fido2_persistence_duration.log level global.fido2.appLoggers.persistenceDurationLogTarget string \"FILE\" fido2_persistence_duration.log target global.fido2.appLoggers.persistenceLogLevel string \"INFO\" fido2_persistence.log level global.fido2.appLoggers.persistenceLogTarget string \"FILE\" fido2_persistence.log target global.fido2.appLoggers.scriptLogLevel string \"INFO\" fido2_script.log level global.fido2.appLoggers.scriptLogTarget string \"FILE\" fido2_script.log target global.fido2.cnCustomJavaOptions string \"\" passing custom java options to fido2. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.fido2.enabled bool true Boolean flag to enable/disable the fido2 chart. global.fido2.fido2ServiceName string \"fido2\" Name of the fido2 service. Please keep it as default. global.fido2.ingress object {\"fido2AdditionalAnnotations\":{},\"fido2ConfigAdditionalAnnotations\":{},\"fido2ConfigEnabled\":false,\"fido2ConfigLabels\":{},\"fido2Enabled\":false,\"fido2Labels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.fido2.ingress.fido2AdditionalAnnotations object {} fido2 ingress resource additional annotations. global.fido2.ingress.fido2ConfigAdditionalAnnotations object {} fido2 config ingress resource additional annotations. global.fido2.ingress.fido2ConfigEnabled bool false Enable endpoint /.well-known/fido2-configuration global.fido2.ingress.fido2ConfigLabels object {} fido2 config ingress resource labels. key app is taken global.fido2.ingress.fido2Enabled bool false Enable endpoint /jans-fido2 global.fido2.ingress.fido2Labels object {} fido2 ingress resource labels. key app is taken global.fqdn string \"demoexample.jans.io\" Fully qualified domain name to be used for Janssen installation. This address will be used to reach Janssen services. global.gcePdStorageType string \"pd-standard\" GCE storage kind if using Google disks global.isFqdnRegistered bool false Boolean flag to enable mapping global.lbIp to global.fqdn inside pods on clouds that provide static ip for load balancers. On cloud that provide only addresses to the LB this flag will enable a script to actively scan config.configmap.lbAddr and update the hosts file inside the pods automatically. global.istio.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of global.istio.additionalLabels object {} Additional labels that will be added across the gateway in the format of global.istio.enabled bool false Boolean flag that enables using istio side-cars with Janssen services. global.istio.gateways list [] Override the gateway that can be created by default. This is used when istio ingress has already been setup and the gateway exists. global.istio.ingress bool false Boolean flag that enables using istio gateway for Janssen. This assumes istio ingress is installed and hence the LB is available. global.istio.namespace string \"istio-system\" The namespace istio is deployed in. The is normally istio-system. global.jobTtlSecondsAfterFinished int 300 https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/ global.kc-scheduler.enabled bool false Boolean flag to enable/disable the kc-scheduler cronjob chart. global.lbIp string \"22.22.22.22\" The Loadbalancer IP created by nginx or istio on clouds that provide static IPs. This is not needed if global.fqdn is globally resolvable. global.link.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"linkLogLevel\":\"INFO\",\"linkLogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.link.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e link-persistence ===> 2022-12-20 17:49:55,744 INFO global.link.appLoggers.linkLogLevel string \"INFO\" cacherefresh.log level global.link.appLoggers.linkLogTarget string \"STDOUT\" cacherefresh.log target global.link.appLoggers.persistenceDurationLogLevel string \"INFO\" cacherefresh_persistence_duration.log level global.link.appLoggers.persistenceDurationLogTarget string \"FILE\" cacherefresh_persistence_duration.log target global.link.appLoggers.persistenceLogLevel string \"INFO\" cacherefresh_persistence.log level global.link.appLoggers.persistenceLogTarget string \"FILE\" cacherefresh_persistence.log target global.link.appLoggers.scriptLogLevel string \"INFO\" cacherefresh_script.log level global.link.appLoggers.scriptLogTarget string \"FILE\" cacherefresh_script.log target global.link.cnCustomJavaOptions string \"\" passing custom java options to link. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.link.enabled bool false Boolean flag to enable/disable the link chart. global.link.ingress object {\"linkEnabled\":true} Enable endpoints in either istio or nginx ingress depending on users choice global.link.linkServiceName string \"link\" Name of the link service. Please keep it as default. global.nginx-ingress.enabled bool true Boolean flag to enable/disable the nginx-ingress definitions chart. global.persistence.enabled bool true Boolean flag to enable/disable the persistence chart. global.saml.cnCustomJavaOptions string \"\" passing custom java options to saml. DO NOT PASS JAVA_OPTIONS in envs. global.saml.enabled bool false Boolean flag to enable/disable the saml chart. global.saml.ingress object {\"samlAdditionalAnnotations\":{},\"samlEnabled\":false,\"samlLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.saml.ingress.samlAdditionalAnnotations object {} SAML ingress resource additional annotations. global.saml.ingress.samlLabels object {} SAML config ingress resource labels. key app is taken global.saml.samlServiceName string \"saml\" Name of the saml service. Please keep it as default. global.scim.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scimLogLevel\":\"INFO\",\"scimLogTarget\":\"STDOUT\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.scim.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e jans-scim ===> 2022-12-20 17:49:55,744 INFO global.scim.appLoggers.persistenceDurationLogLevel string \"INFO\" jans-scim_persistence_duration.log level global.scim.appLoggers.persistenceDurationLogTarget string \"FILE\" jans-scim_persistence_duration.log target global.scim.appLoggers.persistenceLogLevel string \"INFO\" jans-scim_persistence.log level global.scim.appLoggers.persistenceLogTarget string \"FILE\" jans-scim_persistence.log target global.scim.appLoggers.scimLogLevel string \"INFO\" jans-scim.log level global.scim.appLoggers.scimLogTarget string \"STDOUT\" jans-scim.log target global.scim.appLoggers.scriptLogLevel string \"INFO\" jans-scim_script.log level global.scim.appLoggers.scriptLogTarget string \"FILE\" jans-scim_script.log target global.scim.cnCustomJavaOptions string \"\" passing custom java options to scim. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.scim.enabled bool true Boolean flag to enable/disable the SCIM chart. global.scim.ingress object {\"scimAdditionalAnnotations\":{},\"scimConfigAdditionalAnnotations\":{},\"scimConfigEnabled\":false,\"scimConfigLabels\":{},\"scimEnabled\":false,\"scimLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.scim.ingress.scimAdditionalAnnotations object {} SCIM ingress resource additional annotations. global.scim.ingress.scimConfigAdditionalAnnotations object {} SCIM config ingress resource additional annotations. global.scim.ingress.scimConfigEnabled bool false Enable endpoint /.well-known/scim-configuration global.scim.ingress.scimConfigLabels object {} SCIM config ingress resource labels. key app is taken global.scim.ingress.scimEnabled bool false Enable SCIM endpoints /jans-scim global.scim.ingress.scimLabels object {} SCIM config ingress resource labels. key app is taken global.scim.scimServiceName string \"scim\" Name of the scim service. Please keep it as default. global.serviceAccountName string \"default\" service account used by Kubernetes resources global.storageClass object {\"allowVolumeExpansion\":true,\"allowedTopologies\":[],\"mountOptions\":[\"debug\"],\"parameters\":{},\"provisioner\":\"microk8s.io/hostpath\",\"reclaimPolicy\":\"Retain\",\"volumeBindingMode\":\"WaitForFirstConsumer\"} StorageClass section. This is not currently used by the openbanking distribution. You may specify custom parameters as needed. global.storageClass.parameters object {} parameters: fsType: \"\" kind: \"\" pool: \"\" storageAccountType: \"\" type: \"\" global.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service. Envs defined in global.userEnvs will be globally available to all services global.usrEnvs.normal object {} Add custom normal envs to the service. variable1: value1 global.usrEnvs.secret object {} Add custom secret envs to the service. variable1: value1 kc-scheduler object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/kc-scheduler\",\"tag\":\"0.0.0-nightly\"},\"interval\":10,\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Responsible for synchronizing Keycloak SAML clients kc-scheduler.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of kc-scheduler.additionalLabels object {} Additional labels that will be added across the gateway in the format of kc-scheduler.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. kc-scheduler.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh kc-scheduler.dnsConfig object {} Add custom dns config kc-scheduler.dnsPolicy string \"\" Add custom dns policy kc-scheduler.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. kc-scheduler.image.pullSecrets list [] Image Pull Secrets kc-scheduler.image.repository string \"ghcr.io/janssenproject/jans/kc-scheduler\" Image to use for deploying. kc-scheduler.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. kc-scheduler.interval int 10 Interval of running the scheduler (in minutes) kc-scheduler.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. kc-scheduler.resources.limits.cpu string \"300m\" CPU limit. kc-scheduler.resources.limits.memory string \"300Mi\" Memory limit. kc-scheduler.resources.requests.cpu string \"300m\" CPU request. kc-scheduler.resources.requests.memory string \"300Mi\" Memory request. kc-scheduler.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service kc-scheduler.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 kc-scheduler.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 kc-scheduler.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers kc-scheduler.volumes list [] Configure any additional volumes that need to be attached to the pod link object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/link\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Link. link.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of link.additionalLabels object {} Additional labels that will be added across the gateway in the format of link.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. link.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh link.dnsConfig object {} Add custom dns config link.dnsPolicy string \"\" Add custom dns policy link.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler link.hpa.behavior object {} Scaling Policies link.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set link.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. link.image.pullSecrets list [] Image Pull Secrets link.image.repository string \"ghcr.io/janssenproject/jans/link\" Image to use for deploying. link.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. link.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. link.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http liveness probe endpoint link.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget link.readinessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http readiness probe endpoint link.replicas int 1 Service replica number. link.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}} Resource specs. link.resources.limits.cpu string \"500m\" CPU limit. link.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. link.resources.requests.cpu string \"500m\" CPU request. link.resources.requests.memory string \"1200Mi\" Memory request. link.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ link.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service link.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 link.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 link.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers link.volumes list [] Configure any additional volumes that need to be attached to the pod nginx-ingress object {\"ingress\":{\"additionalAnnotations\":{},\"additionalLabels\":{},\"hosts\":[\"demoexample.jans.io\"],\"ingressClassName\":\"nginx\",\"path\":\"/\",\"tls\":[{\"hosts\":[\"demoexample.jans.io\"],\"secretName\":\"tls-certificate\"}]}} Nginx ingress definitions chart nginx-ingress.ingress.additionalAnnotations object {} Additional annotations that will be added across all ingress definitions in the format of {cert-manager.io/issuer: \"letsencrypt-prod\"} Enable client certificate authentication nginx.ingress.kubernetes.io/auth-tls-verify-client: \"optional\" Create the secret containing the trusted ca certificates nginx.ingress.kubernetes.io/auth-tls-secret: \"janssen/tls-certificate\" Specify the verification depth in the client certificates chain nginx.ingress.kubernetes.io/auth-tls-verify-depth: \"1\" Specify if certificates are passed to upstream server nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: \"true\" nginx-ingress.ingress.additionalLabels object {} Additional labels that will be added across all ingress definitions in the format of nginx-ingress.ingress.tls list [{\"hosts\":[\"demoexample.jans.io\"],\"secretName\":\"tls-certificate\"}] Secrets holding HTTPS CA cert and key. persistence object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/persistence-loader\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Job to generate data and initial config for Janssen Server persistence layer. persistence.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of persistence.additionalLabels object {} Additional labels that will be added across the gateway in the format of persistence.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. persistence.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh persistence.dnsConfig object {} Add custom dns config persistence.dnsPolicy string \"\" Add custom dns policy persistence.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. persistence.image.pullSecrets list [] Image Pull Secrets persistence.image.repository string \"ghcr.io/janssenproject/jans/persistence-loader\" Image to use for deploying. persistence.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. persistence.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. persistence.resources.limits.cpu string \"300m\" CPU limit persistence.resources.limits.memory string \"300Mi\" Memory limit. persistence.resources.requests.cpu string \"300m\" CPU request. persistence.resources.requests.memory string \"300Mi\" Memory request. persistence.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service persistence.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 persistence.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 persistence.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers persistence.volumes list [] Configure any additional volumes that need to be attached to the pod saml object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/saml\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} SAML. saml.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of saml.additionalLabels object {} Additional labels that will be added across the gateway in the format of saml.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. saml.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh saml.dnsConfig object {} Add custom dns config saml.dnsPolicy string \"\" Add custom dns policy saml.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler saml.hpa.behavior object {} Scaling Policies saml.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set saml.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. saml.image.pullSecrets list [] Image Pull Secrets saml.image.repository string \"ghcr.io/janssenproject/jans/saml\" Image to use for deploying. saml.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. saml.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. saml.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http liveness probe endpoint saml.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget saml.readinessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http readiness probe endpoint saml.replicas int 1 Service replica number. saml.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}} Resource specs. saml.resources.limits.cpu string \"500m\" CPU limit. saml.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. saml.resources.requests.cpu string \"500m\" CPU request. saml.resources.requests.memory string \"1200Mi\" Memory request. saml.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ saml.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service saml.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 saml.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 saml.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers saml.volumes list [] Configure any additional volumes that need to be attached to the pod scim object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/scim\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}},\"service\":{\"name\":\"http-scim\",\"port\":8080},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} System for Cross-domain Identity Management (SCIM) version 2.0 scim.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of scim.additionalLabels object {} Additional labels that will be added across the gateway in the format of scim.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. scim.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh scim.dnsConfig object {} Add custom dns config scim.dnsPolicy string \"\" Add custom dns policy scim.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler scim.hpa.behavior object {} Scaling Policies scim.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set scim.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. scim.image.pullSecrets list [] Image Pull Secrets scim.image.repository string \"ghcr.io/janssenproject/jans/scim\" Image to use for deploying. scim.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. scim.livenessProbe object {\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for SCIM if needed. scim.livenessProbe.httpGet.path string \"/jans-scim/sys/health-check\" http liveness probe endpoint scim.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget scim.readinessProbe object {\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the readiness healthcheck for the SCIM if needed. scim.readinessProbe.httpGet.path string \"/jans-scim/sys/health-check\" http readiness probe endpoint scim.replicas int 1 Service replica number. scim.resources.limits.cpu string \"1000m\" CPU limit. scim.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. scim.resources.requests.cpu string \"1000m\" CPU request. scim.resources.requests.memory string \"1200Mi\" Memory request. scim.service.name string \"http-scim\" The name of the scim port within the scim service. Please keep it as default. scim.service.port int 8080 Port of the scim service. Please keep it as default. scim.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ scim.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service scim.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 scim.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 scim.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers scim.volumes list [] Configure any additional volumes that need to be attached to the pod Autogenerated from chart metadata using helm-docs v1.14.2", "title": "Helm Chart"}, {"location": "janssen-server/reference/kubernetes/helm-chart/#janssen", "text": "Janssen Access and Identity Management Microservices Chart. This chart deploys each janssen microservice as a separate deployment. Homepage: https://jans.io", "title": "janssen"}, {"location": "janssen-server/reference/kubernetes/helm-chart/#maintainers", "text": "Name Email Url moabu support@jans.io", "title": "Maintainers"}, {"location": "janssen-server/reference/kubernetes/helm-chart/#source-code", "text": "https://jans.io https://github.com/JanssenProject/jans/charts/janssen", "title": "Source Code"}, {"location": "janssen-server/reference/kubernetes/helm-chart/#requirements", "text": "Kubernetes: >=v1.22.0-0 Repository Name Version auth-server 0.0.0-nightly auth-server-key-rotation 0.0.0-nightly casa 0.0.0-nightly cn-istio-ingress 0.0.0-nightly config 0.0.0-nightly config-api 0.0.0-nightly fido2 0.0.0-nightly kc-scheduler 0.0.0-nightly link 0.0.0-nightly nginx-ingress 0.0.0-nightly persistence 0.0.0-nightly saml 0.0.0-nightly scim 0.0.0-nightly", "title": "Requirements"}, {"location": "janssen-server/reference/kubernetes/helm-chart/#values", "text": "Key Type Default Description auth-server object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/auth-server\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"},\"requests\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} OAuth Authorization Server, the OpenID Connect Provider, the UMA Authorization Server--this is the main Internet facing component of Janssen. It's the service that returns tokens, JWT's and identity assertions. This service must be Internet facing. auth-server-key-rotation object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/certmanager\",\"tag\":\"0.0.0-nightly\"},\"keysLife\":48,\"keysPushDelay\":0,\"keysPushStrategy\":\"NEWER\",\"keysStrategy\":\"NEWER\",\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Responsible for regenerating auth-keys per x hours auth-server-key-rotation.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of auth-server-key-rotation.additionalLabels object {} Additional labels that will be added across the gateway in the format of auth-server-key-rotation.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. auth-server-key-rotation.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh auth-server-key-rotation.dnsConfig object {} Add custom dns config auth-server-key-rotation.dnsPolicy string \"\" Add custom dns policy auth-server-key-rotation.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. auth-server-key-rotation.image.pullSecrets list [] Image Pull Secrets auth-server-key-rotation.image.repository string \"ghcr.io/janssenproject/jans/certmanager\" Image to use for deploying. auth-server-key-rotation.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. auth-server-key-rotation.keysLife int 48 Auth server key rotation keys life in hours auth-server-key-rotation.keysPushDelay int 0 Delay (in seconds) before pushing private keys to Auth server auth-server-key-rotation.keysPushStrategy string \"NEWER\" Set key selection strategy after pushing private keys to Auth server (only takes effect when keysPushDelay value is greater than 0) auth-server-key-rotation.keysStrategy string \"NEWER\" Set key selection strategy used by Auth server auth-server-key-rotation.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. auth-server-key-rotation.resources.limits.cpu string \"300m\" CPU limit. auth-server-key-rotation.resources.limits.memory string \"300Mi\" Memory limit. auth-server-key-rotation.resources.requests.cpu string \"300m\" CPU request. auth-server-key-rotation.resources.requests.memory string \"300Mi\" Memory request. auth-server-key-rotation.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service auth-server-key-rotation.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 auth-server-key-rotation.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 auth-server-key-rotation.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers auth-server-key-rotation.volumes list [] Configure any additional volumes that need to be attached to the pod auth-server.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of auth-server.additionalLabels object {} Additional labels that will be added across the gateway in the format of auth-server.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. auth-server.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh auth-server.dnsConfig object {} Add custom dns config auth-server.dnsPolicy string \"\" Add custom dns policy auth-server.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler auth-server.hpa.behavior object {} Scaling Policies auth-server.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set auth-server.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. auth-server.image.pullSecrets list [] Image Pull Secrets auth-server.image.repository string \"ghcr.io/janssenproject/jans/auth-server\" Image to use for deploying. auth-server.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. auth-server.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. auth-server.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} Executes the python3 healthcheck. https://github.com/JanssenProject/docker-jans-auth-server/blob/master/scripts/healthcheck.py auth-server.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget auth-server.readinessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the readiness healthcheck for the auth server if needed. https://github.com/JanssenProject/docker-jans-auth-server/blob/master/scripts/healthcheck.py auth-server.replicas int 1 Service replica number. auth-server.resources object {\"limits\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"},\"requests\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"}} Resource specs. auth-server.resources.limits.cpu string \"2500m\" CPU limit. auth-server.resources.limits.memory string \"2500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. auth-server.resources.requests.cpu string \"2500m\" CPU request. auth-server.resources.requests.memory string \"2500Mi\" Memory request. auth-server.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ auth-server.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service auth-server.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 auth-server.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 auth-server.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers auth-server.volumes list [] Configure any additional volumes that need to be attached to the pod casa object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/casa\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Janssen Casa (\"Casa\") is a self-service web portal for end-users to manage authentication and authorization preferences for their account in a Janssen Auth Server. casa.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of casa.additionalLabels object {} Additional labels that will be added across the gateway in the format of casa.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. casa.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh casa.dnsConfig object {} Add custom dns config casa.dnsPolicy string \"\" Add custom dns policy casa.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler casa.hpa.behavior object {} Scaling Policies casa.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set casa.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. casa.image.pullSecrets list [] Image Pull Secrets casa.image.repository string \"ghcr.io/janssenproject/jans/casa\" Image to use for deploying. casa.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. casa.livenessProbe object {\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the liveness healthcheck for casa if needed. casa.livenessProbe.httpGet.path string \"/jans-casa/health-check\" http liveness probe endpoint casa.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget casa.readinessProbe object {\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the readiness healthcheck for the casa if needed. casa.readinessProbe.httpGet.path string \"/jans-casa/health-check\" http readiness probe endpoint casa.replicas int 1 Service replica number. casa.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}} Resource specs. casa.resources.limits.cpu string \"500m\" CPU limit. casa.resources.limits.memory string \"500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. casa.resources.requests.cpu string \"500m\" CPU request. casa.resources.requests.memory string \"500Mi\" Memory request. casa.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ casa.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service casa.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 casa.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 casa.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers casa.volumes list [] Configure any additional volumes that need to be attached to the pod config object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"adminPassword\":\"Test1234#\",\"city\":\"Austin\",\"configmap\":{\"cnAwsAccessKeyId\":\"\",\"cnAwsDefaultRegion\":\"us-west-1\",\"cnAwsProfile\":\"janssen\",\"cnAwsSecretAccessKey\":\"\",\"cnAwsSecretsEndpointUrl\":\"\",\"cnAwsSecretsNamePrefix\":\"janssen\",\"cnAwsSecretsReplicaRegions\":[],\"cnCacheType\":\"NATIVE_PERSISTENCE\",\"cnConfigKubernetesConfigMap\":\"cn\",\"cnGoogleProjectId\":\"google-project-to-save-config-and-secrets-to\",\"cnGoogleSecretManagerServiceAccount\":\"SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo=\",\"cnGoogleSecretNamePrefix\":\"janssen\",\"cnGoogleSecretVersionId\":\"latest\",\"cnJettyRequestHeaderSize\":8192,\"cnMaxRamPercent\":\"75.0\",\"cnMessageType\":\"DISABLED\",\"cnOpaUrl\":\"http://opa.opa.svc.cluster.cluster.local:8181/v1\",\"cnPersistenceHybridMapping\":\"{}\",\"cnRedisSentinelGroup\":\"\",\"cnRedisSslTruststore\":\"\",\"cnRedisType\":\"STANDALONE\",\"cnRedisUrl\":\"redis.redis.svc.cluster.local:6379\",\"cnRedisUseSsl\":false,\"cnScimProtectionMode\":\"OAUTH\",\"cnSecretKubernetesSecret\":\"cn\",\"cnSqlDbDialect\":\"mysql\",\"cnSqlDbHost\":\"my-release-mysql.default.svc.cluster.local\",\"cnSqlDbName\":\"jans\",\"cnSqlDbPort\":3306,\"cnSqlDbSchema\":\"\",\"cnSqlDbTimezone\":\"UTC\",\"cnSqlDbUser\":\"jans\",\"cnSqldbUserPassword\":\"Test1234#\",\"cnVaultAddr\":\"http://localhost:8200\",\"cnVaultAppRolePath\":\"approle\",\"cnVaultKvPath\":\"secret\",\"cnVaultNamespace\":\"\",\"cnVaultPrefix\":\"jans\",\"cnVaultRoleId\":\"\",\"cnVaultRoleIdFile\":\"/etc/certs/vault_role_id\",\"cnVaultSecretId\":\"\",\"cnVaultSecretIdFile\":\"/etc/certs/vault_secret_id\",\"cnVaultVerify\":false,\"kcAdminPassword\":\"Test1234#\",\"kcAdminUsername\":\"admin\",\"kcDbPassword\":\"Test1234#\",\"kcDbSchema\":\"keycloak\",\"kcDbUrlDatabase\":\"keycloak\",\"kcDbUrlHost\":\"mysql.kc.svc.cluster.local\",\"kcDbUrlPort\":3306,\"kcDbUrlProperties\":\"?useUnicode=true&characterEncoding=UTF-8&character_set_server=utf8mb4\",\"kcDbUsername\":\"keycloak\",\"kcDbVendor\":\"mysql\",\"kcLogLevel\":\"INFO\",\"lbAddr\":\"\",\"quarkusTransactionEnableRecovery\":true},\"countryCode\":\"US\",\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"email\":\"support@jans.io\",\"image\":{\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/configurator\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"orgName\":\"Janssen\",\"redisPassword\":\"P@assw0rd\",\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"salt\":\"\",\"state\":\"TX\",\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Configuration parameters for setup and initial configuration secret and config layers used by Janssen services. config-api object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/config-api\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"jans-config-api/api/v1/health/ready\",\"port\":8074},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Config Api endpoints can be used to configure the auth-server, which is an open-source OpenID Connect Provider (OP) and UMA Authorization Server (AS). config-api.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of config-api.additionalLabels object {} Additional labels that will be added across the gateway in the format of config-api.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. config-api.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh config-api.dnsConfig object {} Add custom dns config config-api.dnsPolicy string \"\" Add custom dns policy config-api.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler config-api.hpa.behavior object {} Scaling Policies config-api.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set config-api.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. config-api.image.pullSecrets list [] Image Pull Secrets config-api.image.repository string \"ghcr.io/janssenproject/jans/config-api\" Image to use for deploying. config-api.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. config-api.livenessProbe object {\"httpGet\":{\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. config-api.livenessProbe.httpGet object {\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074} http liveness probe endpoint config-api.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget config-api.readinessProbe.httpGet object {\"path\":\"jans-config-api/api/v1/health/ready\",\"port\":8074} http readiness probe endpoint config-api.replicas int 1 Service replica number. config-api.resources object {\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}} Resource specs. config-api.resources.limits.cpu string \"1000m\" CPU limit. config-api.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. config-api.resources.requests.cpu string \"1000m\" CPU request. config-api.resources.requests.memory string \"1200Mi\" Memory request. config-api.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ config-api.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service config-api.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 config-api.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 config-api.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers config-api.volumes list [] Configure any additional volumes that need to be attached to the pod config.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of config.adminPassword string \"Test1234#\" Admin password to log in to the UI. config.city string \"Austin\" City. Used for certificate creation. config.configmap.cnCacheType string \"NATIVE_PERSISTENCE\" Cache type. NATIVE_PERSISTENCE , REDIS . or IN_MEMORY . Defaults to NATIVE_PERSISTENCE . config.configmap.cnConfigKubernetesConfigMap string \"cn\" The name of the Kubernetes ConfigMap that will hold the configuration layer config.configmap.cnGoogleProjectId string \"google-project-to-save-config-and-secrets-to\" Project id of the Google project the secret manager belongs to. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretManagerServiceAccount string \"SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo=\" Service account with roles roles/secretmanager.admin base64 encoded string. This is used often inside the services to reach the configuration layer. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretNamePrefix string \"janssen\" Prefix for Janssen secret in Google Secret Manager. Defaults to janssen. If left janssen-secret secret will be created. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretVersionId string \"latest\" Secret version to be used for secret configuration. Defaults to latest and should normally always stay that way. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnJettyRequestHeaderSize int 8192 Jetty header size in bytes in the auth server config.configmap.cnMaxRamPercent string \"75.0\" Value passed to Java option -XX:MaxRAMPercentage config.configmap.cnMessageType string \"DISABLED\" Message type (one of POSTGRES, REDIS, or DISABLED) config.configmap.cnOpaUrl string \"http://opa.opa.svc.cluster.cluster.local:8181/v1\" URL of OPA API config.configmap.cnPersistenceHybridMapping string \"{}\" Specify data that should be saved in persistence (one of default, user, cache, site, token, or session; default to default). Note this environment only takes effect when global.cnPersistenceType is set to hybrid . config.configmap.cnRedisSentinelGroup string \"\" Redis Sentinel Group. Often set when config.configmap.cnRedisType is set to SENTINEL . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisSslTruststore string \"\" Redis SSL truststore. Optional. Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisType string \"STANDALONE\" Redis service type. STANDALONE or CLUSTER . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisUrl string \"redis.redis.svc.cluster.local:6379\" Redis URL and port number : . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisUseSsl bool false Boolean to use SSL in Redis. Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnScimProtectionMode string \"OAUTH\" SCIM protection mode OAUTH config.configmap.cnSecretKubernetesSecret string \"cn\" Kubernetes secret name holding configuration keys. Used when global.configSecretAdapter is set to kubernetes which is the default. config.configmap.cnSqlDbDialect string \"mysql\" SQL database dialect. mysql or pgsql config.configmap.cnSqlDbHost string \"my-release-mysql.default.svc.cluster.local\" SQL database host uri. config.configmap.cnSqlDbName string \"jans\" SQL database name. config.configmap.cnSqlDbPort int 3306 SQL database port. config.configmap.cnSqlDbSchema string \"\" Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). config.configmap.cnSqlDbTimezone string \"UTC\" SQL database timezone. config.configmap.cnSqlDbUser string \"jans\" SQL database username. config.configmap.cnSqldbUserPassword string \"Test1234#\" SQL password injected the secrets . config.configmap.cnVaultAddr string \"http://localhost:8200\" Base URL of Vault. config.configmap.cnVaultAppRolePath string \"approle\" Path to Vault AppRole. config.configmap.cnVaultKvPath string \"secret\" Path to Vault KV secrets engine. config.configmap.cnVaultNamespace string \"\" Vault namespace used to access the secrets. config.configmap.cnVaultPrefix string \"jans\" Base prefix name used to access secrets. config.configmap.cnVaultRoleId string \"\" Vault AppRole RoleID. config.configmap.cnVaultRoleIdFile string \"/etc/certs/vault_role_id\" Path to file contains Vault AppRole role ID. config.configmap.cnVaultSecretId string \"\" Vault AppRole SecretID. config.configmap.cnVaultSecretIdFile string \"/etc/certs/vault_secret_id\" Path to file contains Vault AppRole secret ID. config.configmap.cnVaultVerify bool false Verify connection to Vault. config.configmap.kcAdminPassword string \"Test1234#\" Keycloak admin UI password config.configmap.kcAdminUsername string \"admin\" Keycloak admin UI username config.configmap.kcDbPassword string \"Test1234#\" Password for Keycloak database access config.configmap.kcDbSchema string \"keycloak\" Keycloak database schema name (note that PostgreSQL may be using \"public\" schema). config.configmap.kcDbUrlDatabase string \"keycloak\" Keycloak database name. config.configmap.kcDbUrlHost string \"mysql.kc.svc.cluster.local\" Keycloak database host uri config.configmap.kcDbUrlPort int 3306 Keycloak database port (default to port 3306 for mysql). config.configmap.kcDbUrlProperties string \"?useUnicode=true&characterEncoding=UTF-8&character_set_server=utf8mb4\" Keycloak database connection properties. If using postgresql, the value can be set to empty string. config.configmap.kcDbUsername string \"keycloak\" Keycloak database username config.configmap.kcDbVendor string \"mysql\" Keycloak database vendor name (default to MySQL server). To use PostgreSQL server, change the value to postgres. config.configmap.kcLogLevel string \"INFO\" Keycloak logging level config.configmap.lbAddr string \"\" Load balancer address for AWS if the FQDN is not registered. config.configmap.quarkusTransactionEnableRecovery bool true Quarkus transaction recovery. When using MySQL, there could be issue regarding XA_RECOVER_ADMIN; refer to https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_xa-recover-admin for details. config.countryCode string \"US\" Country code. Used for certificate creation. config.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. config.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh config.dnsConfig object {} Add custom dns config config.dnsPolicy string \"\" Add custom dns policy config.email string \"support@jans.io\" Email address of the administrator usually. Used for certificate creation. config.image.pullSecrets list [] Image Pull Secrets config.image.repository string \"ghcr.io/janssenproject/jans/configurator\" Image to use for deploying. config.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. config.orgName string \"Janssen\" Organization name. Used for certificate creation. config.redisPassword string \"P@assw0rd\" Redis admin password if config.configmap.cnCacheType is set to REDIS . config.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. config.resources.limits.cpu string \"300m\" CPU limit. config.resources.limits.memory string \"300Mi\" Memory limit. config.resources.requests.cpu string \"300m\" CPU request. config.resources.requests.memory string \"300Mi\" Memory request. config.salt string \"\" Salt. Used for encoding/decoding sensitive data. If omitted or set to empty string, the value will be self-generated. Otherwise, a 24 alphanumeric characters are allowed as its value. config.state string \"TX\" State code. Used for certificate creation. config.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service. config.usrEnvs.normal object {} Add custom normal envs to the service. variable1: value1 config.usrEnvs.secret object {} Add custom secret envs to the service. variable1: value1 config.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers config.volumes list [] Configure any additional volumes that need to be attached to the pod fido2 object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/fido2\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}},\"service\":{\"name\":\"http-fido2\",\"port\":8080},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} FIDO 2.0 (FIDO2) is an open authentication standard that enables leveraging common devices to authenticate to online services in both mobile and desktop environments. fido2.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of fido2.additionalLabels object {} Additional labels that will be added across the gateway in the format of fido2.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. fido2.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh fido2.dnsConfig object {} Add custom dns config fido2.dnsPolicy string \"\" Add custom dns policy fido2.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler fido2.hpa.behavior object {} Scaling Policies fido2.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set fido2.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. fido2.image.pullSecrets list [] Image Pull Secrets fido2.image.repository string \"ghcr.io/janssenproject/jans/fido2\" Image to use for deploying. fido2.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. fido2.livenessProbe object {\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the liveness healthcheck for the fido2 if needed. fido2.livenessProbe.httpGet object {\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"} http liveness probe endpoint fido2.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget fido2.readinessProbe object {\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the readiness healthcheck for the fido2 if needed. fido2.replicas int 1 Service replica number. fido2.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}} Resource specs. fido2.resources.limits.cpu string \"500m\" CPU limit. fido2.resources.limits.memory string \"500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. fido2.resources.requests.cpu string \"500m\" CPU request. fido2.resources.requests.memory string \"500Mi\" Memory request. fido2.service.name string \"http-fido2\" The name of the fido2 port within the fido2 service. Please keep it as default. fido2.service.port int 8080 Port of the fido2 service. Please keep it as default. fido2.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ fido2.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service fido2.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 fido2.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 fido2.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers fido2.volumes list [] Configure any additional volumes that need to be attached to the pod global object {\"alb\":{\"ingress\":false},\"auth-server\":{\"appLoggers\":{\"auditStatsLogLevel\":\"INFO\",\"auditStatsLogTarget\":\"FILE\",\"authLogLevel\":\"INFO\",\"authLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"httpLogLevel\":\"INFO\",\"httpLogTarget\":\"FILE\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"authEncKeys\":\"RSA1_5 RSA-OAEP\",\"authServerServiceName\":\"auth-server\",\"authSigKeys\":\"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\",\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"authServerAdditionalAnnotations\":{},\"authServerEnabled\":true,\"authServerLabels\":{},\"deviceCodeAdditionalAnnotations\":{},\"deviceCodeEnabled\":true,\"deviceCodeLabels\":{},\"firebaseMessagingAdditionalAnnotations\":{},\"firebaseMessagingEnabled\":true,\"firebaseMessagingLabels\":{},\"lockAdditionalAnnotations\":{},\"lockConfigAdditionalAnnotations\":{},\"lockConfigEnabled\":false,\"lockConfigLabels\":{},\"lockEnabled\":false,\"lockLabels\":{},\"openidAdditionalAnnotations\":{},\"openidConfigEnabled\":true,\"openidConfigLabels\":{},\"u2fAdditionalAnnotations\":{},\"u2fConfigEnabled\":true,\"u2fConfigLabels\":{},\"uma2AdditionalAnnotations\":{},\"uma2ConfigEnabled\":true,\"uma2ConfigLabels\":{},\"webdiscoveryAdditionalAnnotations\":{},\"webdiscoveryEnabled\":true,\"webdiscoveryLabels\":{},\"webfingerAdditionalAnnotations\":{},\"webfingerEnabled\":true,\"webfingerLabels\":{}},\"lockEnabled\":false},\"auth-server-key-rotation\":{\"customAnnotations\":{\"cronjob\":{},\"secret\":{},\"service\":{}},\"enabled\":true,\"initKeysLife\":48},\"awsStorageType\":\"io1\",\"azureStorageAccountType\":\"Standard_LRS\",\"azureStorageKind\":\"Managed\",\"casa\":{\"appLoggers\":{\"casaLogLevel\":\"INFO\",\"casaLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"timerLogLevel\":\"INFO\",\"timerLogTarget\":\"FILE\"},\"casaServiceName\":\"casa\",\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"casaAdditionalAnnotations\":{},\"casaEnabled\":false,\"casaLabels\":{}}},\"cloud\":{\"testEnviroment\":false},\"cnAwsConfigFile\":\"/etc/jans/conf/aws_config_file\",\"cnAwsSecretsReplicaRegionsFile\":\"/etc/jans/conf/aws_secrets_replica_regions\",\"cnAwsSharedCredentialsFile\":\"/etc/jans/conf/aws_shared_credential_file\",\"cnConfiguratorConfigurationFile\":\"/etc/jans/conf/configuration.json\",\"cnConfiguratorCustomSchema\":{\"secretName\":\"\"},\"cnConfiguratorDumpFile\":\"/etc/jans/conf/configuration.out.json\",\"cnDocumentStoreType\":\"DB\",\"cnGoogleApplicationCredentials\":\"/etc/jans/conf/google-credentials.json\",\"cnPersistenceType\":\"sql\",\"cnPrometheusPort\":\"\",\"cnSqlPasswordFile\":\"/etc/jans/conf/sql_password\",\"config\":{\"customAnnotations\":{\"clusterRoleBinding\":{},\"configMap\":{},\"job\":{},\"role\":{},\"roleBinding\":{},\"secret\":{},\"service\":{},\"serviceAccount\":{}},\"enabled\":true},\"config-api\":{\"appLoggers\":{\"configApiLogLevel\":\"INFO\",\"configApiLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"configApiServerServiceName\":\"config-api\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"configApiAdditionalAnnotations\":{},\"configApiEnabled\":true,\"configApiLabels\":{}},\"plugins\":\"fido2,scim,user-mgt\"},\"configAdapterName\":\"kubernetes\",\"configSecretAdapter\":\"kubernetes\",\"fido2\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"fido2LogLevel\":\"INFO\",\"fido2LogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"fido2ServiceName\":\"fido2\",\"ingress\":{\"fido2AdditionalAnnotations\":{},\"fido2ConfigAdditionalAnnotations\":{},\"fido2ConfigEnabled\":false,\"fido2ConfigLabels\":{},\"fido2Enabled\":false,\"fido2Labels\":{}}},\"fqdn\":\"demoexample.jans.io\",\"gcePdStorageType\":\"pd-standard\",\"isFqdnRegistered\":false,\"istio\":{\"additionalAnnotations\":{},\"additionalLabels\":{},\"enabled\":false,\"gateways\":[],\"ingress\":false,\"namespace\":\"istio-system\"},\"jobTtlSecondsAfterFinished\":300,\"kc-scheduler\":{\"enabled\":false},\"lbIp\":\"22.22.22.22\",\"link\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"linkLogLevel\":\"INFO\",\"linkLogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"service\":{},\"virtualService\":{}},\"enabled\":false,\"ingress\":{\"linkEnabled\":true},\"linkServiceName\":\"link\"},\"nginx-ingress\":{\"enabled\":true},\"persistence\":{\"customAnnotations\":{\"job\":{},\"secret\":{},\"service\":{}},\"enabled\":true},\"saml\":{\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":false,\"ingress\":{\"samlAdditionalAnnotations\":{},\"samlEnabled\":false,\"samlLabels\":{}},\"samlServiceName\":\"saml\"},\"scim\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scimLogLevel\":\"INFO\",\"scimLogTarget\":\"STDOUT\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"scimAdditionalAnnotations\":{},\"scimConfigAdditionalAnnotations\":{},\"scimConfigEnabled\":false,\"scimConfigLabels\":{},\"scimEnabled\":false,\"scimLabels\":{}},\"scimServiceName\":\"scim\"},\"serviceAccountName\":\"default\",\"storageClass\":{\"allowVolumeExpansion\":true,\"allowedTopologies\":[],\"mountOptions\":[\"debug\"],\"parameters\":{},\"provisioner\":\"microk8s.io/hostpath\",\"reclaimPolicy\":\"Retain\",\"volumeBindingMode\":\"WaitForFirstConsumer\"},\"usrEnvs\":{\"normal\":{},\"secret\":{}}} Parameters used globally across all services helm charts. global.alb.ingress bool false Activates ALB ingress global.auth-server-key-rotation.enabled bool true Boolean flag to enable/disable the auth-server-key rotation cronjob chart. global.auth-server-key-rotation.initKeysLife int 48 The initial auth server key rotation keys life in hours global.auth-server.appLoggers object {\"auditStatsLogLevel\":\"INFO\",\"auditStatsLogTarget\":\"FILE\",\"authLogLevel\":\"INFO\",\"authLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"httpLogLevel\":\"INFO\",\"httpLogTarget\":\"FILE\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.auth-server.appLoggers.auditStatsLogLevel string \"INFO\" jans-auth_audit.log level global.auth-server.appLoggers.auditStatsLogTarget string \"FILE\" jans-auth_script.log target global.auth-server.appLoggers.authLogLevel string \"INFO\" jans-auth.log level global.auth-server.appLoggers.authLogTarget string \"STDOUT\" jans-auth.log target global.auth-server.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e auth-server-script ===> 2022-12-20 17:49:55,744 INFO global.auth-server.appLoggers.httpLogLevel string \"INFO\" http_request_response.log level global.auth-server.appLoggers.httpLogTarget string \"FILE\" http_request_response.log target global.auth-server.appLoggers.persistenceDurationLogLevel string \"INFO\" jans-auth_persistence_duration.log level global.auth-server.appLoggers.persistenceDurationLogTarget string \"FILE\" jans-auth_persistence_duration.log target global.auth-server.appLoggers.persistenceLogLevel string \"INFO\" jans-auth_persistence.log level global.auth-server.appLoggers.persistenceLogTarget string \"FILE\" jans-auth_persistence.log target global.auth-server.appLoggers.scriptLogLevel string \"INFO\" jans-auth_script.log level global.auth-server.appLoggers.scriptLogTarget string \"FILE\" jans-auth_script.log target global.auth-server.authEncKeys string \"RSA1_5 RSA-OAEP\" space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) global.auth-server.authServerServiceName string \"auth-server\" Name of the auth-server service. Please keep it as default. global.auth-server.authSigKeys string \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) global.auth-server.cnCustomJavaOptions string \"\" passing custom java options to auth-server. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.auth-server.enabled bool true Boolean flag to enable/disable auth-server chart. You should never set this to false. global.auth-server.ingress object {\"authServerAdditionalAnnotations\":{},\"authServerEnabled\":true,\"authServerLabels\":{},\"deviceCodeAdditionalAnnotations\":{},\"deviceCodeEnabled\":true,\"deviceCodeLabels\":{},\"firebaseMessagingAdditionalAnnotations\":{},\"firebaseMessagingEnabled\":true,\"firebaseMessagingLabels\":{},\"lockAdditionalAnnotations\":{},\"lockConfigAdditionalAnnotations\":{},\"lockConfigEnabled\":false,\"lockConfigLabels\":{},\"lockEnabled\":false,\"lockLabels\":{},\"openidAdditionalAnnotations\":{},\"openidConfigEnabled\":true,\"openidConfigLabels\":{},\"u2fAdditionalAnnotations\":{},\"u2fConfigEnabled\":true,\"u2fConfigLabels\":{},\"uma2AdditionalAnnotations\":{},\"uma2ConfigEnabled\":true,\"uma2ConfigLabels\":{},\"webdiscoveryAdditionalAnnotations\":{},\"webdiscoveryEnabled\":true,\"webdiscoveryLabels\":{},\"webfingerAdditionalAnnotations\":{},\"webfingerEnabled\":true,\"webfingerLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.auth-server.ingress.authServerAdditionalAnnotations object {} Auth server ingress resource additional annotations. global.auth-server.ingress.authServerEnabled bool true Enable Auth server endpoints /jans-auth global.auth-server.ingress.authServerLabels object {} Auth server ingress resource labels. key app is taken global.auth-server.ingress.deviceCodeAdditionalAnnotations object {} device-code ingress resource additional annotations. global.auth-server.ingress.deviceCodeEnabled bool true Enable endpoint /device-code global.auth-server.ingress.deviceCodeLabels object {} device-code ingress resource labels. key app is taken global.auth-server.ingress.firebaseMessagingAdditionalAnnotations object {} Firebase Messaging ingress resource additional annotations. global.auth-server.ingress.firebaseMessagingEnabled bool true Enable endpoint /firebase-messaging-sw.js global.auth-server.ingress.firebaseMessagingLabels object {} Firebase Messaging ingress resource labels. key app is taken global.auth-server.ingress.lockAdditionalAnnotations object {} Lock ingress resource additional annotations. global.auth-server.ingress.lockConfigAdditionalAnnotations object {} Lock config ingress resource additional annotations. global.auth-server.ingress.lockConfigEnabled bool false Enable endpoint /.well-known/lock-server-configuration global.auth-server.ingress.lockConfigLabels object {} Lock config ingress resource labels. key app is taken global.auth-server.ingress.lockEnabled bool false Enable endpoint /jans-lock global.auth-server.ingress.lockLabels object {} Lock ingress resource labels. key app is taken global.auth-server.ingress.openidAdditionalAnnotations object {} openid-configuration ingress resource additional annotations. global.auth-server.ingress.openidConfigEnabled bool true Enable endpoint /.well-known/openid-configuration global.auth-server.ingress.openidConfigLabels object {} openid-configuration ingress resource labels. key app is taken global.auth-server.ingress.u2fAdditionalAnnotations object {} u2f config ingress resource additional annotations. global.auth-server.ingress.u2fConfigEnabled bool true Enable endpoint /.well-known/fido-configuration global.auth-server.ingress.u2fConfigLabels object {} u2f config ingress resource labels. key app is taken global.auth-server.ingress.uma2AdditionalAnnotations object {} uma2 config ingress resource additional annotations. global.auth-server.ingress.uma2ConfigEnabled bool true Enable endpoint /.well-known/uma2-configuration global.auth-server.ingress.uma2ConfigLabels object {} uma2 config ingress resource labels. key app is taken global.auth-server.ingress.webdiscoveryAdditionalAnnotations object {} webdiscovery ingress resource additional annotations. global.auth-server.ingress.webdiscoveryEnabled bool true Enable endpoint /.well-known/simple-web-discovery global.auth-server.ingress.webdiscoveryLabels object {} webdiscovery ingress resource labels. key app is taken global.auth-server.ingress.webfingerAdditionalAnnotations object {} webfinger ingress resource additional annotations. global.auth-server.ingress.webfingerEnabled bool true Enable endpoint /.well-known/webfinger global.auth-server.ingress.webfingerLabels object {} webfinger ingress resource labels. key app is taken global.auth-server.lockEnabled bool false Enable jans-lock as service running inside auth-server global.awsStorageType string \"io1\" Volume storage type if using AWS volumes. global.azureStorageAccountType string \"Standard_LRS\" Volume storage type if using Azure disks. global.azureStorageKind string \"Managed\" Azure storage kind if using Azure disks global.casa.appLoggers object {\"casaLogLevel\":\"INFO\",\"casaLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"timerLogLevel\":\"INFO\",\"timerLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.casa.appLoggers.casaLogLevel string \"INFO\" casa.log level global.casa.appLoggers.casaLogTarget string \"STDOUT\" casa.log target global.casa.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e casa ===> 2022-12-20 17:49:55,744 INFO global.casa.appLoggers.timerLogLevel string \"INFO\" casa timer log level global.casa.appLoggers.timerLogTarget string \"FILE\" casa timer log target global.casa.casaServiceName string \"casa\" Name of the casa service. Please keep it as default. global.casa.cnCustomJavaOptions string \"\" passing custom java options to casa. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.casa.enabled bool true Boolean flag to enable/disable the casa chart. global.casa.ingress object {\"casaAdditionalAnnotations\":{},\"casaEnabled\":false,\"casaLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.casa.ingress.casaAdditionalAnnotations object {} Casa ingress resource additional annotations. global.casa.ingress.casaEnabled bool false Enable casa endpoints /casa global.casa.ingress.casaLabels object {} Casa ingress resource labels. key app is taken global.cloud.testEnviroment bool false Boolean flag if enabled will strip resources requests and limits from all services. global.cnConfiguratorConfigurationFile string \"/etc/jans/conf/configuration.json\" Path to configuration schema file global.cnConfiguratorCustomSchema object {\"secretName\":\"\"} Use custom configuration schema in existing secrets. Note, the secrets has to contain the key configuration.json or any basename as specified in cnConfiguratorConfigurationFile. global.cnConfiguratorCustomSchema.secretName string \"\" The name of the secrets used for storing custom configuration schema. global.cnConfiguratorDumpFile string \"/etc/jans/conf/configuration.out.json\" Path to dumped configuration schema file global.cnDocumentStoreType string \"DB\" Document store type to use for shibboleth files DB. global.cnGoogleApplicationCredentials string \"/etc/jans/conf/google-credentials.json\" Base64 encoded service account. The sa must have roles/secretmanager.admin to use Google secrets. Leave as this is a sensible default. global.cnPersistenceType string \"sql\" Persistence backend to run Janssen with hybrid global.cnPrometheusPort string \"\" Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. global.cnSqlPasswordFile string \"/etc/jans/conf/sql_password\" Path to SQL password file global.config-api.appLoggers object {\"configApiLogLevel\":\"INFO\",\"configApiLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.config-api.appLoggers.configApiLogLevel string \"INFO\" configapi.log level global.config-api.appLoggers.configApiLogTarget string \"STDOUT\" configapi.log target global.config-api.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e config-api_persistence ===> 2022-12-20 17:49:55,744 INFO global.config-api.appLoggers.persistenceDurationLogLevel string \"INFO\" config-api_persistence_duration.log level global.config-api.appLoggers.persistenceDurationLogTarget string \"FILE\" config-api_persistence_duration.log target global.config-api.appLoggers.persistenceLogLevel string \"INFO\" config-api_persistence.log level global.config-api.appLoggers.persistenceLogTarget string \"FILE\" config-api_persistence.log target global.config-api.appLoggers.scriptLogLevel string \"INFO\" config-api_script.log level global.config-api.appLoggers.scriptLogTarget string \"FILE\" config-api_script.log target global.config-api.cnCustomJavaOptions string \"\" passing custom java options to config-api. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.config-api.configApiServerServiceName string \"config-api\" Name of the config-api service. Please keep it as default. global.config-api.enabled bool true Boolean flag to enable/disable the config-api chart. global.config-api.ingress object {\"configApiAdditionalAnnotations\":{},\"configApiEnabled\":true,\"configApiLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.config-api.ingress.configApiAdditionalAnnotations object {} ConfigAPI ingress resource additional annotations. global.config-api.ingress.configApiLabels object {} configAPI ingress resource labels. key app is taken global.config-api.plugins string \"fido2,scim,user-mgt\" Comma-separated values of enabled plugins (supported plugins are \"admin-ui\",\"fido2\",\"scim\",\"user-mgt\",\"jans-link\",\"kc-saml\") global.config.enabled bool true Boolean flag to enable/disable the configuration chart. This normally should never be false global.configAdapterName string \"kubernetes\" The config backend adapter that will hold Janssen configuration layer. aws global.configSecretAdapter string \"kubernetes\" The config backend adapter that will hold Janssen secret layer. vault global.fido2.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"fido2LogLevel\":\"INFO\",\"fido2LogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.fido2.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e fido2 ===> 2022-12-20 17:49:55,744 INFO global.fido2.appLoggers.fido2LogLevel string \"INFO\" fido2.log level global.fido2.appLoggers.fido2LogTarget string \"STDOUT\" fido2.log target global.fido2.appLoggers.persistenceDurationLogLevel string \"INFO\" fido2_persistence_duration.log level global.fido2.appLoggers.persistenceDurationLogTarget string \"FILE\" fido2_persistence_duration.log target global.fido2.appLoggers.persistenceLogLevel string \"INFO\" fido2_persistence.log level global.fido2.appLoggers.persistenceLogTarget string \"FILE\" fido2_persistence.log target global.fido2.appLoggers.scriptLogLevel string \"INFO\" fido2_script.log level global.fido2.appLoggers.scriptLogTarget string \"FILE\" fido2_script.log target global.fido2.cnCustomJavaOptions string \"\" passing custom java options to fido2. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.fido2.enabled bool true Boolean flag to enable/disable the fido2 chart. global.fido2.fido2ServiceName string \"fido2\" Name of the fido2 service. Please keep it as default. global.fido2.ingress object {\"fido2AdditionalAnnotations\":{},\"fido2ConfigAdditionalAnnotations\":{},\"fido2ConfigEnabled\":false,\"fido2ConfigLabels\":{},\"fido2Enabled\":false,\"fido2Labels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.fido2.ingress.fido2AdditionalAnnotations object {} fido2 ingress resource additional annotations. global.fido2.ingress.fido2ConfigAdditionalAnnotations object {} fido2 config ingress resource additional annotations. global.fido2.ingress.fido2ConfigEnabled bool false Enable endpoint /.well-known/fido2-configuration global.fido2.ingress.fido2ConfigLabels object {} fido2 config ingress resource labels. key app is taken global.fido2.ingress.fido2Enabled bool false Enable endpoint /jans-fido2 global.fido2.ingress.fido2Labels object {} fido2 ingress resource labels. key app is taken global.fqdn string \"demoexample.jans.io\" Fully qualified domain name to be used for Janssen installation. This address will be used to reach Janssen services. global.gcePdStorageType string \"pd-standard\" GCE storage kind if using Google disks global.isFqdnRegistered bool false Boolean flag to enable mapping global.lbIp to global.fqdn inside pods on clouds that provide static ip for load balancers. On cloud that provide only addresses to the LB this flag will enable a script to actively scan config.configmap.lbAddr and update the hosts file inside the pods automatically. global.istio.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of global.istio.additionalLabels object {} Additional labels that will be added across the gateway in the format of global.istio.enabled bool false Boolean flag that enables using istio side-cars with Janssen services. global.istio.gateways list [] Override the gateway that can be created by default. This is used when istio ingress has already been setup and the gateway exists. global.istio.ingress bool false Boolean flag that enables using istio gateway for Janssen. This assumes istio ingress is installed and hence the LB is available. global.istio.namespace string \"istio-system\" The namespace istio is deployed in. The is normally istio-system. global.jobTtlSecondsAfterFinished int 300 https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/ global.kc-scheduler.enabled bool false Boolean flag to enable/disable the kc-scheduler cronjob chart. global.lbIp string \"22.22.22.22\" The Loadbalancer IP created by nginx or istio on clouds that provide static IPs. This is not needed if global.fqdn is globally resolvable. global.link.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"linkLogLevel\":\"INFO\",\"linkLogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.link.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e link-persistence ===> 2022-12-20 17:49:55,744 INFO global.link.appLoggers.linkLogLevel string \"INFO\" cacherefresh.log level global.link.appLoggers.linkLogTarget string \"STDOUT\" cacherefresh.log target global.link.appLoggers.persistenceDurationLogLevel string \"INFO\" cacherefresh_persistence_duration.log level global.link.appLoggers.persistenceDurationLogTarget string \"FILE\" cacherefresh_persistence_duration.log target global.link.appLoggers.persistenceLogLevel string \"INFO\" cacherefresh_persistence.log level global.link.appLoggers.persistenceLogTarget string \"FILE\" cacherefresh_persistence.log target global.link.appLoggers.scriptLogLevel string \"INFO\" cacherefresh_script.log level global.link.appLoggers.scriptLogTarget string \"FILE\" cacherefresh_script.log target global.link.cnCustomJavaOptions string \"\" passing custom java options to link. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.link.enabled bool false Boolean flag to enable/disable the link chart. global.link.ingress object {\"linkEnabled\":true} Enable endpoints in either istio or nginx ingress depending on users choice global.link.linkServiceName string \"link\" Name of the link service. Please keep it as default. global.nginx-ingress.enabled bool true Boolean flag to enable/disable the nginx-ingress definitions chart. global.persistence.enabled bool true Boolean flag to enable/disable the persistence chart. global.saml.cnCustomJavaOptions string \"\" passing custom java options to saml. DO NOT PASS JAVA_OPTIONS in envs. global.saml.enabled bool false Boolean flag to enable/disable the saml chart. global.saml.ingress object {\"samlAdditionalAnnotations\":{},\"samlEnabled\":false,\"samlLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.saml.ingress.samlAdditionalAnnotations object {} SAML ingress resource additional annotations. global.saml.ingress.samlLabels object {} SAML config ingress resource labels. key app is taken global.saml.samlServiceName string \"saml\" Name of the saml service. Please keep it as default. global.scim.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scimLogLevel\":\"INFO\",\"scimLogTarget\":\"STDOUT\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.scim.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e jans-scim ===> 2022-12-20 17:49:55,744 INFO global.scim.appLoggers.persistenceDurationLogLevel string \"INFO\" jans-scim_persistence_duration.log level global.scim.appLoggers.persistenceDurationLogTarget string \"FILE\" jans-scim_persistence_duration.log target global.scim.appLoggers.persistenceLogLevel string \"INFO\" jans-scim_persistence.log level global.scim.appLoggers.persistenceLogTarget string \"FILE\" jans-scim_persistence.log target global.scim.appLoggers.scimLogLevel string \"INFO\" jans-scim.log level global.scim.appLoggers.scimLogTarget string \"STDOUT\" jans-scim.log target global.scim.appLoggers.scriptLogLevel string \"INFO\" jans-scim_script.log level global.scim.appLoggers.scriptLogTarget string \"FILE\" jans-scim_script.log target global.scim.cnCustomJavaOptions string \"\" passing custom java options to scim. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.scim.enabled bool true Boolean flag to enable/disable the SCIM chart. global.scim.ingress object {\"scimAdditionalAnnotations\":{},\"scimConfigAdditionalAnnotations\":{},\"scimConfigEnabled\":false,\"scimConfigLabels\":{},\"scimEnabled\":false,\"scimLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.scim.ingress.scimAdditionalAnnotations object {} SCIM ingress resource additional annotations. global.scim.ingress.scimConfigAdditionalAnnotations object {} SCIM config ingress resource additional annotations. global.scim.ingress.scimConfigEnabled bool false Enable endpoint /.well-known/scim-configuration global.scim.ingress.scimConfigLabels object {} SCIM config ingress resource labels. key app is taken global.scim.ingress.scimEnabled bool false Enable SCIM endpoints /jans-scim global.scim.ingress.scimLabels object {} SCIM config ingress resource labels. key app is taken global.scim.scimServiceName string \"scim\" Name of the scim service. Please keep it as default. global.serviceAccountName string \"default\" service account used by Kubernetes resources global.storageClass object {\"allowVolumeExpansion\":true,\"allowedTopologies\":[],\"mountOptions\":[\"debug\"],\"parameters\":{},\"provisioner\":\"microk8s.io/hostpath\",\"reclaimPolicy\":\"Retain\",\"volumeBindingMode\":\"WaitForFirstConsumer\"} StorageClass section. This is not currently used by the openbanking distribution. You may specify custom parameters as needed. global.storageClass.parameters object {} parameters: fsType: \"\" kind: \"\" pool: \"\" storageAccountType: \"\" type: \"\" global.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service. Envs defined in global.userEnvs will be globally available to all services global.usrEnvs.normal object {} Add custom normal envs to the service. variable1: value1 global.usrEnvs.secret object {} Add custom secret envs to the service. variable1: value1 kc-scheduler object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/kc-scheduler\",\"tag\":\"0.0.0-nightly\"},\"interval\":10,\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Responsible for synchronizing Keycloak SAML clients kc-scheduler.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of kc-scheduler.additionalLabels object {} Additional labels that will be added across the gateway in the format of kc-scheduler.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. kc-scheduler.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh kc-scheduler.dnsConfig object {} Add custom dns config kc-scheduler.dnsPolicy string \"\" Add custom dns policy kc-scheduler.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. kc-scheduler.image.pullSecrets list [] Image Pull Secrets kc-scheduler.image.repository string \"ghcr.io/janssenproject/jans/kc-scheduler\" Image to use for deploying. kc-scheduler.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. kc-scheduler.interval int 10 Interval of running the scheduler (in minutes) kc-scheduler.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. kc-scheduler.resources.limits.cpu string \"300m\" CPU limit. kc-scheduler.resources.limits.memory string \"300Mi\" Memory limit. kc-scheduler.resources.requests.cpu string \"300m\" CPU request. kc-scheduler.resources.requests.memory string \"300Mi\" Memory request. kc-scheduler.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service kc-scheduler.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 kc-scheduler.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 kc-scheduler.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers kc-scheduler.volumes list [] Configure any additional volumes that need to be attached to the pod link object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/link\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Link. link.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of link.additionalLabels object {} Additional labels that will be added across the gateway in the format of link.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. link.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh link.dnsConfig object {} Add custom dns config link.dnsPolicy string \"\" Add custom dns policy link.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler link.hpa.behavior object {} Scaling Policies link.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set link.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. link.image.pullSecrets list [] Image Pull Secrets link.image.repository string \"ghcr.io/janssenproject/jans/link\" Image to use for deploying. link.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. link.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. link.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http liveness probe endpoint link.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget link.readinessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http readiness probe endpoint link.replicas int 1 Service replica number. link.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}} Resource specs. link.resources.limits.cpu string \"500m\" CPU limit. link.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. link.resources.requests.cpu string \"500m\" CPU request. link.resources.requests.memory string \"1200Mi\" Memory request. link.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ link.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service link.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 link.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 link.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers link.volumes list [] Configure any additional volumes that need to be attached to the pod nginx-ingress object {\"ingress\":{\"additionalAnnotations\":{},\"additionalLabels\":{},\"hosts\":[\"demoexample.jans.io\"],\"ingressClassName\":\"nginx\",\"path\":\"/\",\"tls\":[{\"hosts\":[\"demoexample.jans.io\"],\"secretName\":\"tls-certificate\"}]}} Nginx ingress definitions chart nginx-ingress.ingress.additionalAnnotations object {} Additional annotations that will be added across all ingress definitions in the format of {cert-manager.io/issuer: \"letsencrypt-prod\"} Enable client certificate authentication nginx.ingress.kubernetes.io/auth-tls-verify-client: \"optional\" Create the secret containing the trusted ca certificates nginx.ingress.kubernetes.io/auth-tls-secret: \"janssen/tls-certificate\" Specify the verification depth in the client certificates chain nginx.ingress.kubernetes.io/auth-tls-verify-depth: \"1\" Specify if certificates are passed to upstream server nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: \"true\" nginx-ingress.ingress.additionalLabels object {} Additional labels that will be added across all ingress definitions in the format of nginx-ingress.ingress.tls list [{\"hosts\":[\"demoexample.jans.io\"],\"secretName\":\"tls-certificate\"}] Secrets holding HTTPS CA cert and key. persistence object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/persistence-loader\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Job to generate data and initial config for Janssen Server persistence layer. persistence.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of persistence.additionalLabels object {} Additional labels that will be added across the gateway in the format of persistence.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. persistence.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh persistence.dnsConfig object {} Add custom dns config persistence.dnsPolicy string \"\" Add custom dns policy persistence.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. persistence.image.pullSecrets list [] Image Pull Secrets persistence.image.repository string \"ghcr.io/janssenproject/jans/persistence-loader\" Image to use for deploying. persistence.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. persistence.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. persistence.resources.limits.cpu string \"300m\" CPU limit persistence.resources.limits.memory string \"300Mi\" Memory limit. persistence.resources.requests.cpu string \"300m\" CPU request. persistence.resources.requests.memory string \"300Mi\" Memory request. persistence.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service persistence.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 persistence.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 persistence.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers persistence.volumes list [] Configure any additional volumes that need to be attached to the pod saml object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/saml\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} SAML. saml.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of saml.additionalLabels object {} Additional labels that will be added across the gateway in the format of saml.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. saml.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh saml.dnsConfig object {} Add custom dns config saml.dnsPolicy string \"\" Add custom dns policy saml.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler saml.hpa.behavior object {} Scaling Policies saml.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set saml.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. saml.image.pullSecrets list [] Image Pull Secrets saml.image.repository string \"ghcr.io/janssenproject/jans/saml\" Image to use for deploying. saml.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. saml.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. saml.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http liveness probe endpoint saml.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget saml.readinessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http readiness probe endpoint saml.replicas int 1 Service replica number. saml.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}} Resource specs. saml.resources.limits.cpu string \"500m\" CPU limit. saml.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. saml.resources.requests.cpu string \"500m\" CPU request. saml.resources.requests.memory string \"1200Mi\" Memory request. saml.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ saml.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service saml.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 saml.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 saml.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers saml.volumes list [] Configure any additional volumes that need to be attached to the pod scim object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/scim\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}},\"service\":{\"name\":\"http-scim\",\"port\":8080},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} System for Cross-domain Identity Management (SCIM) version 2.0 scim.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of scim.additionalLabels object {} Additional labels that will be added across the gateway in the format of scim.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. scim.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh scim.dnsConfig object {} Add custom dns config scim.dnsPolicy string \"\" Add custom dns policy scim.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler scim.hpa.behavior object {} Scaling Policies scim.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set scim.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. scim.image.pullSecrets list [] Image Pull Secrets scim.image.repository string \"ghcr.io/janssenproject/jans/scim\" Image to use for deploying. scim.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. scim.livenessProbe object {\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for SCIM if needed. scim.livenessProbe.httpGet.path string \"/jans-scim/sys/health-check\" http liveness probe endpoint scim.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget scim.readinessProbe object {\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the readiness healthcheck for the SCIM if needed. scim.readinessProbe.httpGet.path string \"/jans-scim/sys/health-check\" http readiness probe endpoint scim.replicas int 1 Service replica number. scim.resources.limits.cpu string \"1000m\" CPU limit. scim.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. scim.resources.requests.cpu string \"1000m\" CPU request. scim.resources.requests.memory string \"1200Mi\" Memory request. scim.service.name string \"http-scim\" The name of the scim port within the scim service. Please keep it as default. scim.service.port int 8080 Port of the scim service. Please keep it as default. scim.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ scim.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service scim.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 scim.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 scim.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers scim.volumes list [] Configure any additional volumes that need to be attached to the pod Autogenerated from chart metadata using helm-docs v1.14.2", "title": "Values"}, {"location": "janssen-server/scim/bulk-users/", "tags": ["administration", "scim", "bulk-users"], "text": "Adding user in bulk # SCIM supports a bulk operation allowing consumers of the service to send multiple resource operations in a single request. This means the body of a bulk operation may contain one or more operations belonging to any of the supported HTTP verbs, e.g., POST, PUT, DELETE, etc. This feature is useful, for instance, to create several users at once as we'll see below. Endpoint # The bulk endpoint is accessible at https://<your-server-mame>/jans-scim/restv1/v2/Bulk . Requests must be sent with a bearer token having scope https://jans.io/scim/bulk Bulk payload # A bulk is structured as a JSON document with two required properties: schemas : A list with the single string value urn:ietf:params:scim:api:messages:2.0:BulkRequest Operations : A JSON array describing every operation to perform in the order provided An operation is a JSON document with the following: method : The HTTP verb of the operation to perform path : The path of the actual endpoint to hit relative to the SCIM root. For instance, to create a user, it will be /Users data : The payload of the actual operation. This is required only for POST, PUT, or PATCH Payload example for adding users # { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:BulkRequest\" ], \"Operations\": [ { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"alanis\" } }, { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"sheryl\", \"active\": true, \"password\": \"top-secret\", \"roles\": [{ \"value\" : \"Master of puppets\" }] } }, { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"becca\", \"externalId\":\"becca_ponx_1234\", \"name\":{ \"familyName\": \"Cadalzo\", \"givenName\": \"Rebecca\" } } } ] } The above payload illustrates how to insert three users with different details each. Bulk response # The result of a bulk operation is likewise retrieved in JSON object format: schemas : A list with the single string value urn:ietf:params:scim:api:messages:2.0:BulkResponse Operations : A JSON array describing the response of every operation performed whether failed or successful An operation is a JSON document with the following: method : The HTTP verb of the operation performed location : The resource endpoint URL. For example, in the case of user creation, this will be the URL where the user's details can be retrieved status : A string value reporting the HTTP response code obtained for the given operation response : A JSON object only present when the status does not belong to the 2XX (success) family. It contains details of the error that occurred Response example # The following contains a potential response obtained for the bulk request mentioned earlier: { \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:BulkResponse\"], \"Operations\": [ { \"method\": \"POST\", \"location\": \"https://acme.co/jans-scim/restv1/v2/Users/92b725cd\", \"status\": \"201\" }, { \"method\": \"POST\", \"location\": \"https://acme.co/jans-scim/restv1/v2/Users/a27725cf\", \"status\": \"201\" }, { \"method\": \"POST\", \"status\": \"409\", \"response\":{ \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:Error\"], \"scimType\": \"uniqueness\" \"detail\": \"User 'becca' already exists\" } } ] } Bulk operation configuration # SCIM Jans server has a couple of configuration properties related to bulk operations: bulkMaxOperations : The maximum number of operations per bulk request. Default is 30 bulkMaxPayloadSize : The maximum payload size in bytes. Default value is 3072000", "title": "Bulk Adding Users"}, {"location": "janssen-server/scim/bulk-users/#adding-user-in-bulk", "text": "SCIM supports a bulk operation allowing consumers of the service to send multiple resource operations in a single request. This means the body of a bulk operation may contain one or more operations belonging to any of the supported HTTP verbs, e.g., POST, PUT, DELETE, etc. This feature is useful, for instance, to create several users at once as we'll see below.", "title": "Adding user in bulk"}, {"location": "janssen-server/scim/bulk-users/#endpoint", "text": "The bulk endpoint is accessible at https://<your-server-mame>/jans-scim/restv1/v2/Bulk . Requests must be sent with a bearer token having scope https://jans.io/scim/bulk", "title": "Endpoint"}, {"location": "janssen-server/scim/bulk-users/#bulk-payload", "text": "A bulk is structured as a JSON document with two required properties: schemas : A list with the single string value urn:ietf:params:scim:api:messages:2.0:BulkRequest Operations : A JSON array describing every operation to perform in the order provided An operation is a JSON document with the following: method : The HTTP verb of the operation to perform path : The path of the actual endpoint to hit relative to the SCIM root. For instance, to create a user, it will be /Users data : The payload of the actual operation. This is required only for POST, PUT, or PATCH", "title": "Bulk payload"}, {"location": "janssen-server/scim/bulk-users/#payload-example-for-adding-users", "text": "{ \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:BulkRequest\" ], \"Operations\": [ { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"alanis\" } }, { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"sheryl\", \"active\": true, \"password\": \"top-secret\", \"roles\": [{ \"value\" : \"Master of puppets\" }] } }, { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"becca\", \"externalId\":\"becca_ponx_1234\", \"name\":{ \"familyName\": \"Cadalzo\", \"givenName\": \"Rebecca\" } } } ] } The above payload illustrates how to insert three users with different details each.", "title": "Payload example for adding users"}, {"location": "janssen-server/scim/bulk-users/#bulk-response", "text": "The result of a bulk operation is likewise retrieved in JSON object format: schemas : A list with the single string value urn:ietf:params:scim:api:messages:2.0:BulkResponse Operations : A JSON array describing the response of every operation performed whether failed or successful An operation is a JSON document with the following: method : The HTTP verb of the operation performed location : The resource endpoint URL. For example, in the case of user creation, this will be the URL where the user's details can be retrieved status : A string value reporting the HTTP response code obtained for the given operation response : A JSON object only present when the status does not belong to the 2XX (success) family. It contains details of the error that occurred", "title": "Bulk response"}, {"location": "janssen-server/scim/bulk-users/#response-example", "text": "The following contains a potential response obtained for the bulk request mentioned earlier: { \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:BulkResponse\"], \"Operations\": [ { \"method\": \"POST\", \"location\": \"https://acme.co/jans-scim/restv1/v2/Users/92b725cd\", \"status\": \"201\" }, { \"method\": \"POST\", \"location\": \"https://acme.co/jans-scim/restv1/v2/Users/a27725cf\", \"status\": \"201\" }, { \"method\": \"POST\", \"status\": \"409\", \"response\":{ \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:Error\"], \"scimType\": \"uniqueness\" \"detail\": \"User 'becca' already exists\" } } ] }", "title": "Response example"}, {"location": "janssen-server/scim/bulk-users/#bulk-operation-configuration", "text": "SCIM Jans server has a couple of configuration properties related to bulk operations: bulkMaxOperations : The maximum number of operations per bulk request. Default is 30 bulkMaxPayloadSize : The maximum payload size in bytes. Default value is 3072000", "title": "Bulk operation configuration"}, {"location": "janssen-server/scim/config/", "tags": ["administration", "scim", "configuration"], "text": "SCIM configuration # Relevant configuration properties of the Jans SCIM server are summarized in the table below: Property Default value Description maxCount 200 Maximum number of results per page in search endpoints bulkMaxOperations 30 Maximum number of operations admitted in a single bulk request bulkMaxPayloadSize 3072000 Maximum payload size in bytes admitted in a single bulk request userExtensionSchemaURI urn:ietf:params:scim:schemas:extension:gluu:2.0:User URI schema associated to the User Extension skipDefinedPasswordValidation false Whether the validation rules defined for the password attribute in the server should be bypassed when a user is created/updated loggingLevel INFO The logging level Configuration management using CLI # To retrieve the current server configuration run the command python3 jans cli --operation-id get-scim-config To modify some aspect of the retrieved configuration prepare a PATCH request in JSON format. For instance: PATCH [ { \"op\" : \"replace\" , \"path\" : \"bulkMaxOperations\" , \"value\" : 100 }, { \"op\" : \"replace\" , \"path\" : \"loggingLevel\" , \"value\" : \"DEBUG\" } ] These contents should be then passed to the patch-scim-config operation, e.g. python3 jans cli --operation-id patch-scim-config --data <path-to-JSON-file> Configuration management using TUI # To retrieve the current server configuration using TUI proceed as below: Launch TUI, e.g. by running jans tui , and follow the prompts Highlight the SCIM tab using your keyboard's left/right arrow key Highlight the \"Get Scim Configuration\" button using the tab key Press enter You can modify the configuration in place by editing the fields of your interest. To persist the changes, highlight the \"Save\" button at the bottom and press enter. SCIM Operations Guide using CLI, TUI and API # SCIM operations support mutiple options. Please check out this documentation for guidelines of scim operations. When will changes take effect? # Any configuration update will take effect one minute after it has been applied whether via CLI or TUI.", "title": "Configuration"}, {"location": "janssen-server/scim/config/#scim-configuration", "text": "Relevant configuration properties of the Jans SCIM server are summarized in the table below: Property Default value Description maxCount 200 Maximum number of results per page in search endpoints bulkMaxOperations 30 Maximum number of operations admitted in a single bulk request bulkMaxPayloadSize 3072000 Maximum payload size in bytes admitted in a single bulk request userExtensionSchemaURI urn:ietf:params:scim:schemas:extension:gluu:2.0:User URI schema associated to the User Extension skipDefinedPasswordValidation false Whether the validation rules defined for the password attribute in the server should be bypassed when a user is created/updated loggingLevel INFO The logging level", "title": "SCIM configuration"}, {"location": "janssen-server/scim/config/#configuration-management-using-cli", "text": "To retrieve the current server configuration run the command python3 jans cli --operation-id get-scim-config To modify some aspect of the retrieved configuration prepare a PATCH request in JSON format. For instance: PATCH [ { \"op\" : \"replace\" , \"path\" : \"bulkMaxOperations\" , \"value\" : 100 }, { \"op\" : \"replace\" , \"path\" : \"loggingLevel\" , \"value\" : \"DEBUG\" } ] These contents should be then passed to the patch-scim-config operation, e.g. python3 jans cli --operation-id patch-scim-config --data <path-to-JSON-file>", "title": "Configuration management using CLI"}, {"location": "janssen-server/scim/config/#configuration-management-using-tui", "text": "To retrieve the current server configuration using TUI proceed as below: Launch TUI, e.g. by running jans tui , and follow the prompts Highlight the SCIM tab using your keyboard's left/right arrow key Highlight the \"Get Scim Configuration\" button using the tab key Press enter You can modify the configuration in place by editing the fields of your interest. To persist the changes, highlight the \"Save\" button at the bottom and press enter.", "title": "Configuration management using TUI"}, {"location": "janssen-server/scim/config/#scim-operations-guide-using-cli-tui-and-api", "text": "SCIM operations support mutiple options. Please check out this documentation for guidelines of scim operations.", "title": "SCIM Operations Guide using CLI, TUI and API"}, {"location": "janssen-server/scim/config/#when-will-changes-take-effect", "text": "Any configuration update will take effect one minute after it has been applied whether via CLI or TUI.", "title": "When will changes take effect?"}, {"location": "janssen-server/scim/custom-attributes/", "tags": ["administration", "scim", "custom-attributes"], "text": "Custom Attributes # RFC 7643 defines the schema for resource types in SCIM (see section 3.3). In other words, it defines structures in terms of attributes to represent users and groups as well as attribute types, mutability, cardinality, and so on. Although the schema covers many attributes one might think of, at times you will need to add your own attributes for specific needs. This is where user extensions pitch in, they allow you to create custom attributes for SCIM. To do so, you will have to: Add an attribute to Database schema Include the new attribute in an object class such as jansPerson Register and activate your new attribute through Jans TUI . Please visit this page for a more detailed explanation. When registering the attribute in the TUI , please ensure you have set the Include in SCIM Extension parameter to true . Once you submit this form, your attribute will be part of the User Extension . You can verify this by inspecting the Schema endpoint: Command https://<host-name>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:extension:gluu:2.0:User In the JSON response, your new added attribute will appear. To customize the URI associated to the extension (whose default value is urn:ietf:params:scim:schemas:extension:gluu:2.0:User ), you can use TUI: Navigate to SCIM using Jans TUI jans tui Locate the Scim properties section Set a value in the field User Extension Schema URI Save the changes", "title": "Adding Custom Attributes"}, {"location": "janssen-server/scim/custom-attributes/#custom-attributes", "text": "RFC 7643 defines the schema for resource types in SCIM (see section 3.3). In other words, it defines structures in terms of attributes to represent users and groups as well as attribute types, mutability, cardinality, and so on. Although the schema covers many attributes one might think of, at times you will need to add your own attributes for specific needs. This is where user extensions pitch in, they allow you to create custom attributes for SCIM. To do so, you will have to: Add an attribute to Database schema Include the new attribute in an object class such as jansPerson Register and activate your new attribute through Jans TUI . Please visit this page for a more detailed explanation. When registering the attribute in the TUI , please ensure you have set the Include in SCIM Extension parameter to true . Once you submit this form, your attribute will be part of the User Extension . You can verify this by inspecting the Schema endpoint: Command https://<host-name>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:extension:gluu:2.0:User In the JSON response, your new added attribute will appear. To customize the URI associated to the extension (whose default value is urn:ietf:params:scim:schemas:extension:gluu:2.0:User ), you can use TUI: Navigate to SCIM using Jans TUI jans tui Locate the Scim properties section Set a value in the field User Extension Schema URI Save the changes", "title": "Custom Attributes"}, {"location": "janssen-server/scim/logs/", "tags": ["administration", "scim"], "text": "SCIM Logs # Logs can be found under /opt/jans/jetty/jans-scim/logs in your Janssen Server. The default logging level is INFO but this can be changed to any of TRACE , DEBUG , WARN , OR ERROR via TUI. To do so launch TUI, e.g. jans tui , and navigate to SCIM tab. Then in \"Logging Level\" select the desired option. Finally hit \"Save\".", "title": "Logs"}, {"location": "janssen-server/scim/logs/#scim-logs", "text": "Logs can be found under /opt/jans/jetty/jans-scim/logs in your Janssen Server. The default logging level is INFO but this can be changed to any of TRACE , DEBUG , WARN , OR ERROR via TUI. To do so launch TUI, e.g. jans tui , and navigate to SCIM tab. Then in \"Logging Level\" select the desired option. Finally hit \"Save\".", "title": "SCIM Logs"}, {"location": "janssen-server/scim/monitoring/", "tags": ["administration", "scim"], "text": "How is SCIM data stored? # SCIM schema spec does not use LDAP attribute names but a different naming convention for resource attributes (note this is not the case of custom attributes where the SCIM name used is that of the LDAP attribute). It is possible to determine if a given LDAP attribute is being mapped to a SCIM attribute. For that you need to check in Jans TUI Auth-Server >> Attributes and click on any attributes. Check Include in SCIM Extension: is true or false . Whenever you try to map any LDAP attribute to a SCIM attribute keep it's value true . Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Monitoring"}, {"location": "janssen-server/scim/monitoring/#how-is-scim-data-stored", "text": "SCIM schema spec does not use LDAP attribute names but a different naming convention for resource attributes (note this is not the case of custom attributes where the SCIM name used is that of the LDAP attribute). It is possible to determine if a given LDAP attribute is being mapped to a SCIM attribute. For that you need to check in Jans TUI Auth-Server >> Attributes and click on any attributes. Check Include in SCIM Extension: is true or false . Whenever you try to map any LDAP attribute to a SCIM attribute keep it's value true .", "title": "How is SCIM data stored?"}, {"location": "janssen-server/scim/monitoring/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/scim/monitoring/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/scim/oauth-protection/", "tags": ["administration", "scim"], "text": "OAuth protection # The SCIM API endpoints are by default protected by (Bearer) OAuth 2.0 tokens. Depending on the operation, these tokens must have certain scopes for the operations to be authorized. The table below summarizes this fact: Scope Description https://jans.io/scim/users.read Query/Search user resources https://jans.io/scim/users.write Modify user resources https://jans.io/scim/groups.read Query group resources https://jans.io/scim/groups.write Modify group resources https://jans.io/scim/fido.read Query fido resources https://jans.io/scim/fido.write Modify fido resources https://jans.io/scim/fido2.read Query fido 2 resources https://jans.io/scim/fido2.write Modify fido 2 resources https://jans.io/scim/bulk Send requests to the bulk endpoint https://jans.io/scim/all-resources.search Access the root .search endpoint Correspondence of endpoints vs. scopes can be found in the SCIM OpenAPI descriptor you can find here . Client details # To obtain valid tokens, you would normally have to register a client (in the server) capable of obtaining tokens with the scopes needed. Registration is out of the scope of this document, however you can leverage the client that is already bundled in your server for SCIM interaction. With this client you can issue tokens with any SCIM-related scope. Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE . Getting a token # This is a curl example of how to get a token valid for retrieving and modifying users (line breaks added for readability). Note the use of white space to separate scope names. Command curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type = client_credentials -d scope = 'https://jans.io/scim/users.read https://jans.io/scim/users.write' https://your-jans-server/jans-auth/restv1/token Grab the \"access_token\" from the obtained response. Issue a request to the service # The below is a curl example of how to call an operation by passing the previously obtained token (line breaks added for readability): Command curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://your-jans-server/jans-scim/restv1/v2/Users The output should show valid SCIM (JSON) output. Account the access token is short-lived: once it expires you will get a status response of 401 and need to re-request the token as in the previous step. Deactivating OAuth mode # OAuth tokens usage is a safe, standardized approach for controlling access to resources. If for some reason you want to turn off protection you can do so by activating bypass mode: in TUI, navigate to SCIM tab and under \"Protection Mode\" select \"BYPASS\". Finally press \"Save\". Caution: keep in mind that with \"BYPASS\" you should add some sort of protection to your endpoints, say, at the network level to avoid anyone to mess with your user base among other resources.", "title": "OAuth Protection"}, {"location": "janssen-server/scim/oauth-protection/#oauth-protection", "text": "The SCIM API endpoints are by default protected by (Bearer) OAuth 2.0 tokens. Depending on the operation, these tokens must have certain scopes for the operations to be authorized. The table below summarizes this fact: Scope Description https://jans.io/scim/users.read Query/Search user resources https://jans.io/scim/users.write Modify user resources https://jans.io/scim/groups.read Query group resources https://jans.io/scim/groups.write Modify group resources https://jans.io/scim/fido.read Query fido resources https://jans.io/scim/fido.write Modify fido resources https://jans.io/scim/fido2.read Query fido 2 resources https://jans.io/scim/fido2.write Modify fido 2 resources https://jans.io/scim/bulk Send requests to the bulk endpoint https://jans.io/scim/all-resources.search Access the root .search endpoint Correspondence of endpoints vs. scopes can be found in the SCIM OpenAPI descriptor you can find here .", "title": "OAuth protection"}, {"location": "janssen-server/scim/oauth-protection/#client-details", "text": "To obtain valid tokens, you would normally have to register a client (in the server) capable of obtaining tokens with the scopes needed. Registration is out of the scope of this document, however you can leverage the client that is already bundled in your server for SCIM interaction. With this client you can issue tokens with any SCIM-related scope. Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE .", "title": "Client details"}, {"location": "janssen-server/scim/oauth-protection/#getting-a-token", "text": "This is a curl example of how to get a token valid for retrieving and modifying users (line breaks added for readability). Note the use of white space to separate scope names. Command curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type = client_credentials -d scope = 'https://jans.io/scim/users.read https://jans.io/scim/users.write' https://your-jans-server/jans-auth/restv1/token Grab the \"access_token\" from the obtained response.", "title": "Getting a token"}, {"location": "janssen-server/scim/oauth-protection/#issue-a-request-to-the-service", "text": "The below is a curl example of how to call an operation by passing the previously obtained token (line breaks added for readability): Command curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://your-jans-server/jans-scim/restv1/v2/Users The output should show valid SCIM (JSON) output. Account the access token is short-lived: once it expires you will get a status response of 401 and need to re-request the token as in the previous step.", "title": "Issue a request to the service"}, {"location": "janssen-server/scim/oauth-protection/#deactivating-oauth-mode", "text": "OAuth tokens usage is a safe, standardized approach for controlling access to resources. If for some reason you want to turn off protection you can do so by activating bypass mode: in TUI, navigate to SCIM tab and under \"Protection Mode\" select \"BYPASS\". Finally press \"Save\". Caution: keep in mind that with \"BYPASS\" you should add some sort of protection to your endpoints, say, at the network level to avoid anyone to mess with your user base among other resources.", "title": "Deactivating OAuth mode"}, {"location": "janssen-server/scim/security/", "tags": ["administration", "scim"], "text": "Security considerations # SCIM API allows administrators and developers manage a key asset in an IAM deployment, namely users. Additionally, other resources like groups and registered fido devices can be managed in Janssen Server via SCIM. Clearly, this kind of API must not be anonymously accessible. However, the SCIM standard does not define a specific mechanism to prevent unauthorized requests to endpoints. There are just a few guidelines in section 2 of RFC 7644 concerned with authentication and authorization. Currently, the Janssen server supports an OAuth-based mechanism to protect these endpoints; you can find more information in this regard here . Nonetheless, it is recommended not to expose this API outside the organization's network. Ideally administrators should block any external attempt to access URLs under the path https://your-jans-server/jans-scim .", "title": "Security Considerations"}, {"location": "janssen-server/scim/security/#security-considerations", "text": "SCIM API allows administrators and developers manage a key asset in an IAM deployment, namely users. Additionally, other resources like groups and registered fido devices can be managed in Janssen Server via SCIM. Clearly, this kind of API must not be anonymously accessible. However, the SCIM standard does not define a specific mechanism to prevent unauthorized requests to endpoints. There are just a few guidelines in section 2 of RFC 7644 concerned with authentication and authorization. Currently, the Janssen server supports an OAuth-based mechanism to protect these endpoints; you can find more information in this regard here . Nonetheless, it is recommended not to expose this API outside the organization's network. Ideally administrators should block any external attempt to access URLs under the path https://your-jans-server/jans-scim .", "title": "Security considerations"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/", "tags": ["administration", "user management", "cli", "tui"], "text": "Local User Management # In this document we will cover managing people in the Jans Server's Jans CLI and Jans TUI. Manage data in Jans TUI # We can easily add a user using Jans TUI. To do that, run the TUI using jans tui for example, and click on the Users tab. Let's see at a glance user attributes. Attributes Description Username ... Password ... First Name ... Middle Name ... Last Name ... Display Name ... Email ... Active ... Nickname ... CIBA Device Registration Token ... CIBA User code ... Locale ... Website URL ... IMAP Data ... jansAdminUIRole ... Enrollment code ... User Permission ... Preferred Language ... Profile URL ... Secret Question ... Email Verified ... Birthdate ... Time zone info ... Phone Number verified ... Preferred Username ... TransientId ... PersistentId ... Country ... Secret Answer ... OpenID Connect JSON formatted address ... User certificate ... Organization ... Picture URL ... Let's add an user by selecting Add Users tab. Initially we can provide bellow attributes value, We can add extra claims simple by slecting Add Claim Finally save and exit. We will get an unique inum Change User Password # No chance to recover user password, but you can change. To change password of a user navigate/or search user and press key p when the target user is higlighted. In the figure below, passowrd of user sakamura is being changed. Once you write new password (it will be displayed while you type), go to button < Save > and press Enter. Manage User FIDO Devices # To view and manage users registered FIDO devices, first navigate/or search user and press key f on the keyboard. If user has any registered FIDO device, a popup will appears as in image below: You can veiw details of a device by pressing Enter. To delete a device press key d , you will be prompted for confirmation. This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Using CLI/TUI"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#local-user-management", "text": "In this document we will cover managing people in the Jans Server's Jans CLI and Jans TUI.", "title": "Local User Management"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#manage-data-in-jans-tui", "text": "We can easily add a user using Jans TUI. To do that, run the TUI using jans tui for example, and click on the Users tab. Let's see at a glance user attributes. Attributes Description Username ... Password ... First Name ... Middle Name ... Last Name ... Display Name ... Email ... Active ... Nickname ... CIBA Device Registration Token ... CIBA User code ... Locale ... Website URL ... IMAP Data ... jansAdminUIRole ... Enrollment code ... User Permission ... Preferred Language ... Profile URL ... Secret Question ... Email Verified ... Birthdate ... Time zone info ... Phone Number verified ... Preferred Username ... TransientId ... PersistentId ... Country ... Secret Answer ... OpenID Connect JSON formatted address ... User certificate ... Organization ... Picture URL ... Let's add an user by selecting Add Users tab. Initially we can provide bellow attributes value, We can add extra claims simple by slecting Add Claim Finally save and exit. We will get an unique inum", "title": "Manage data in Jans TUI"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#change-user-password", "text": "No chance to recover user password, but you can change. To change password of a user navigate/or search user and press key p when the target user is higlighted. In the figure below, passowrd of user sakamura is being changed. Once you write new password (it will be displayed while you type), go to button < Save > and press Enter.", "title": "Change User Password"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#manage-user-fido-devices", "text": "To view and manage users registered FIDO devices, first navigate/or search user and press key f on the keyboard. If user has any registered FIDO device, a popup will appears as in image below: You can veiw details of a device by pressing Enter. To delete a device press key d , you will be prompted for confirmation.", "title": "Manage User FIDO Devices"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/usermgmt/usermgmt-jans-link/", "tags": ["administration", "user management", "jans-link"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Using jans-link"}, {"location": "janssen-server/usermgmt/usermgmt-jans-link/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/usermgmt/usermgmt-jans-link/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/usermgmt/usermgmt-jans-link/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/usermgmt/usermgmt-scim/", "tags": ["administration", "user management", "scim"], "text": "SCIM User Management # SCIM is a specification designed to reduce the complexity of user management operations by providing a common user schema and the patterns for exchanging such schema using HTTP in a platform-neutral fashion. The aim of SCIM is achieving interoperability, security, and scalability in the context of identity management. For your reference, the current version of the standard is governed by the following documents: RFC 7642 , RFC 7643 , and RFC 7644 . Installation # The API is available as a component of Jans Server. Upon installation you can select if you want SCIM included in your environment. To add SCIM post-install do the following: Run python3 /opt/jans/jans-setup/setup.py --install-scim About API endpoints # Throughout this document, you will notice endpoints are prefixed with path: /jans-scim/restv1/v2 API Protection # Clearly, this API must not be anonymously accessed. However, the basic SCIM standard does not define a specific mechanism to prevent unauthorized requests to endpoints. There are just a few guidelines in section 2 of RFC 7644 concerned with authentication and authorization. OAUTH, This is the default and recommended mechanism BYPASS Depending on the scopes associated to a token, you will be granted (or denied) access to perform certain operations. The following lists the available scopes: Scope Actions allowed https://jans.io/scim/users.read Query user resources https://jans.io/scim/users.write Modify user resources https://jans.io/scim/groups.read Query group resources https://jans.io/scim/groups.write Modify group resources https://jans.io/scim/fido.read Query fido resources https://jans.io/scim/fido.write Modify fido resources https://jans.io/scim/fido2.read Query fido 2 resources https://jans.io/scim/fido2.write Modify fido 2 resources https://jans.io/scim/all-resources.search Access the root .search endpoint https://jans.io/scim/bulk Send requests to the bulk endpoint In order to facilitate the process of getting an access token, your Janssen installation already bundles an OAuth client named \"SCIM client\" with support for all the scopes above. This client uses the client_credentials grant type and client_secret_basic mechanism to authenticate to the token endpoint. Where to locate SCIM-related logs # Please see here besides SCIM log is located at /opt/jans/jetty/jans-scim/logs/scim.log If you use SCIM custom script aslo see /opt/jans/jetty/jans-scim/logs/scim_script.log API documentation at a glance # SCIM API doc page describes about our implementation of SCIM. The API has also been documented using OpenAPI (swagger) specification for the interested. Find yaml files here . Working in OAuth mode # To know more about OAuth protection mode please visit here . The SCIM API endpoints are by default protected by (Bearer) OAuth 2.0 tokens. Depending on the operation, these tokens must have certain scopes for the operations to be authorized. We need a client to get Bearer token. Get SCIM Client # Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. To see in JSON formate please press d . From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE . Get Access token # Let's get a token, curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type=client_credentials -d scope='https://jans.io/scim/users.read https://jans.io/scim/users write' https://<jans-server>/jans-auth/restv1/token > /tmp/token.json In response token.json we will get access_token { \"access_token\":\"11a76589-7955-4247-9ca5-f3ad7884305...\", \"scope\":\"https://jans.io/scim/users.read\", \"token_type\":\"Bearer\", \"expires_in\":299 } Retrive existing User # To get an existing user curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://<jans-server>/jans-scim/restv1/v2/Users > /tmp/user.json In response user.json we will get { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\": 1, \"startIndex\": 1, \"itemsPerPage\": 1, \"Resources\": [ { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"5fdbb720-a1fd-477f-af92-b7c054f02c98\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-12T14:54:09.531Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/5fdbb720-a1fd-477f-af92-b7c054f02c98\" }, \"userName\": \"admin\", \"name\": { \"familyName\": \"...\", \"givenName\": \"...\", \"middleName\": \"...\", \"formatted\": \"...\" }, \"displayName\": \"Admin\", \"active\": true, \"emails\": [ { \"value\": \"example@gluu.org\", \"primary\": false } ], \"groups\": [ { \"value\": \"60B7\", \"display\": \"Jannsen Manager Group\", \"type\": \"direct\", \"$ref\": \"https://raju.jans13.me/jans-scim/restv1/v2/Groups/60B7\" } ] } ] } Creating Resource # Create an User # Let's start creating a dummy user. A client sends a POST request containing a \"User\" to the \"/Users\" endpoint. POST /Users HTTP/1.1 Host: example.com Accept: application/scim+json Content-Type: application/scim+json Authorization: Bearer h480djs93hd8.. Content-Length: ... { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" } } Open a text editor and copy paste the json body, name as input.json . Hit on your terminal with bellow command. curl -k -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users response looks like { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T19:43:32.945Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Barbara\", \"formatted\": \"Ms. Barbara J Jensen III\" } } This new user has been given an id . If possible, inspect your ou=people branch and find the entry whose inum matches the id given. An easier option would be to via Jans TUI and go to Users and search \"bjensen\" to see the recently created user. Updating a User(PUT) # Overwrite your input.json with the following. Replace content in angle brackets accordingly: { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" }, \"displayName\": \"Jensen Barbara\", \"emails\": [ { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": true } ] } PUT with curl: curl -k -X PUT -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Response (output.json) will show the same contents of a full retrieval. Please verify changes were applied whether by inspecting LDAP or issuing a GET. If you have followed the steps properly, you should notice a new e-mail added and the change in displayName attribute Updating a User (PATCH) # With patching, you can be very precise about the modifications you want to apply. Patching syntax follows JSON Patch spec (RFC 6902) closely. While it's not a must to read the RFC to learn how patch works, see section 3.5.2 of SCIM protocol (RFC 7644) to get the grasp. If you prefer reading code, patch test cases found in the Java scim-client project are worth to look at. The following is a simple example that illustrates the kind of modifications developers can achieve via PATCH . Overwrite your input.json with the following: { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"value\": { \"name\": { \"givenName\": \"Joey\" } } }, { \"op\": \"replace\", \"path\": \"emails[type eq \\\"work\\\" or primary eq false].value\", \"value\": \"jensen@example.com\" }, { \"op\": \"add\", \"value\": { \"name\": { \"middleName\": \"Jhon\" } } }, { \"op\": \"add\", \"value\": { \"emails\": [ { \"primary\": true, \"value\": \"my@own.mail\" } ], \"phoneNumbers\": [ { \"type\": \"home\", \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } }, { \"op\": \"remove\", \"path\": \"name.middleName\" }, { \"op\": \"remove\", \"path\": \"phoneNumbers[value ew \\\"01\\\"].type\" } ] } A collection of modification are provided under \"Operations\". They are processed in order of appearance. Also, every operation has a type; patching supports add, remove and replace. The first operations states the following: replace the value of givenName subattribute (that belongs to complex attribute name ) with the string \"Joey\". Operations are easier to understand when using a \"path\". The second operation replaces the value subattribute inside the complex multi-valued attribute emails. Inside the square brackets, we find a filter expression, so the replacement does not apply to all emails in the list but only to those matching the criterion. So the second operation can be read as \"set the value of value subattribute to string jensen@example.com where the type subattribute of the email equals to string \"work\" or if primary attribute is false\". The third operation is similar to the first. It sets the value of a subattribute which was unassigned (null). You could have used \"replace\" operation in this case and results would have been identical. The fourth operation is more interesting. It adds to the current list of emails a new one. It supplies a couple of subattributes for the email to include: primary and value. Additionally, we set the value of (previously unassigned) phoneNumbers multi-valued attribute passing a list of elements. In the fifth operation, we remove the middleName attribute that was set in operation three. Note how we make explicit the path of data to nullify: \"name.middleName\". The sixth operation allows us to remove a specific subattribute of phoneNumbers . The aim is to nullify the \"type\" of the item whose phone number value ends with \"01\". The remove operation can also be used to remove a complete item from a list, or empty the whole list by providing a suitable value for \"path\". Now let's see it in action: curl -k -X PATCH -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> So far our resource look like this { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T22:34:27.465Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Joey\", \"formatted\": \"Ms. Barbara J Jensen III\" }, \"displayName\": \"Jensen Barbara\", \"active\": false, \"emails\": [ { \"value\": \"my@own.mail\", \"primary\": true }, { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": false } ], \"phoneNumbers\": [ { \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } Note the primary subattribute accompanying email \"my@own.mail\" is false but when inserted we provided true . This is because the SCIM specification states that after modifications are applied to resources (PUT or PATCH) , there cannot be more than one item in a multi-valued attribute with primary value set as true . To see more sample JSON payloads, check the .json files used by the scim-client test cases referenced above. Deleting Users # For deleting, the DELETE method of HTTP is used. No input file is used in this case. A delete request could be the following: curl -k -X DELETE -H 'Authorization: Bearer ACCESS_TOKEN' https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Use the inum of our dummy user, Jensen Barbara . Check your LDAP or via Jans TUI to see that Bjensen is gone. How is SCIM data stored? # SCIM schema spec does not use LDAP attribute names but a different naming convention for resource attributes (note this is not the case of custom attributes where the SCIM name used is that of the LDAP attribute). It is possible to determine if a given LDAP attribute is being mapped to a SCIM attribute. For that you need to check in Jans TUI Auth-Server >> Attributes and click on any attributes. Check Include in SCIM Extension: is true or false . Whenever you try to map any LDAP attribute to a SCIM attribute keep it's value true . FIDO Devices # A FIDO device represents a user credential stored in the Jans Server database that is compliant with the FIDO standard. These devices are used as a second factor in a setting of strong authentication. FIDO devices were superseded by FIDO 2 devices in Jans Server. FIDO 2 devices # FIDO 2 devices are credentials that adhere to the more current Fido 2.0 initiative (WebAuthn + CTAP). Examples of FIDO 2 devices are USB security keys and Super Gluu devices. The SCIM endpoints for FIDO 2 allow application developers to query, update and delete already existing devices. Addition of devices do not take place through the service since this process requires direct end-user interaction, ie. device enrolling. The schema attributes for a device of this kind can be found by hitting the URL https://<jans-server>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:Fido2Device To distinguish between regular FIDO2 and SuperGluu devices, note only SuperGluu entries have the attribute deviceData populated (i.e. not null) Example: Querying Enrolled Devices # Say we are interested in having a list of Super Gluu devices users have enrolled and whose operating system is iOS. We may issue a query like this: curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=deviceData co \"ios\"' -d count=10 https://<jans-server>/jans-scim/restv1/v2/Fido2Devices The response will be like: { \"totalResults\": ..., \"itemsPerPage\": ..., \"startIndex\": 1, \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"Resources\": [ { \"id\": \"...\", \"meta\": {...}, \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:Fido2Device\"], \"userId\": \"...\", ... \"deviceData\": \"{...}\", \"displayName\": ..., }, ... ] } Potential performance issues with Group endpoints # In SCIM a group resource basically consists of an identifier, a display name, and a collection of members associated to it. Also, every member is made up of a user identifier, his display name, and other attributes. As a consequence, retrieving group information requires making a correlation with existing user data. Since Gluu database model does not follow a relational database pattern this may entail a considerable amount of user queries when groups contain thousands of members. While this could have been workarounded by storing members' display names inside group entries, this brings additional problems to deal with. Another source of potential overhead stems from creation and modification of groups where many new users are associated to a given group: by default checks are made to guarantee only existing users are attached to groups, thus requiring continuous database queries. Currently there are two ways to lower the amount of database lookups required for SCIM group operations: Explicitly excluding display names from responses Pass the overhead bypass flag to skip members validations The first approach consists of using the query parameter excludedAttributes (see RFC 7644 ) so that display names are neither retrieved from database nor sent in responses. A value like members.display does the job. Note the query parameter attributes can also be used for this purpose, for example with a value like members.value that will output only members' identifiers and ignore other non-required attributes. This approach is particularly useful in search and retrievals when users' display names are not needed. The second is a stronger approach that turns off validation of incoming members data: if the usage of a POST/PUT/PATCH operation implies adding members, their existence is not verified, they will simply get added. Here, the client application is responsible for sending accurate data. To use this approach add a query or header parameter named Group-Overhead-Bypass with any value. Note under this mode of operation: Display names are never returned regardless of attributes or excludedAttributes parameters values Remove/replace patch operations that involve display names in path filters are ignored, eg: \"path\": \"members[value eq \\\"2819c223\\\" or display eq \\\"Joe\\\"]\" User Registration Process with SCIM # SCIM service has many use cases. One interesting and often arising is that of coding your own user registration process. With your SCIM endpoints you can build a custom application to maintain user entries in your database. Important Considerations # Here, you have some useful tips before you start: Choose a toolset you feel comfortable to work with. Keep in mind that you have to leverage the capabilities of your language/framework to issue complex HTTPS requests. Be sure that: You will be able to use at least the following verbs: GET, POST, PUT, and DELETE You can send headers in your requests as well as reading them from the service response If not supported natively, choose a library to facilitate JSON content manipulation. As you have already noticed we have been dealing with JSON for requests as well as for responses. Experience shows that being able to map from objects (or data structures) of your language to Json and viceversa helps saving hours of coding. Shape your data model early. List the attributes your application will operate upon and correlate with those found in the SCIM user schema. You can learn about the schema in RFC 7644 . At least, take a look at the JSON-formatted schema that your Jans Server shows: visit https://<host-name>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:User You will have to manipulate database contents very often as you develop and run tests, thus, find a suitable tool for the task. In the case of LDAP, a TUI client is a good choice. Always check your logs . In this user management guide with SCIM, we have already touched upon the fundamentals of SCIM in Jans Server and shown a good amount of sample requests for manipulation of user information. However, keep in mind the SCIM spec documents are definitely the key reference to build working request messages, specially RFC 7643 , and RFC 7644 .", "title": "Using SCIM"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#scim-user-management", "text": "SCIM is a specification designed to reduce the complexity of user management operations by providing a common user schema and the patterns for exchanging such schema using HTTP in a platform-neutral fashion. The aim of SCIM is achieving interoperability, security, and scalability in the context of identity management. For your reference, the current version of the standard is governed by the following documents: RFC 7642 , RFC 7643 , and RFC 7644 .", "title": "SCIM User Management"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#installation", "text": "The API is available as a component of Jans Server. Upon installation you can select if you want SCIM included in your environment. To add SCIM post-install do the following: Run python3 /opt/jans/jans-setup/setup.py --install-scim", "title": "Installation"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#about-api-endpoints", "text": "Throughout this document, you will notice endpoints are prefixed with path: /jans-scim/restv1/v2", "title": "About API endpoints"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#api-protection", "text": "Clearly, this API must not be anonymously accessed. However, the basic SCIM standard does not define a specific mechanism to prevent unauthorized requests to endpoints. There are just a few guidelines in section 2 of RFC 7644 concerned with authentication and authorization. OAUTH, This is the default and recommended mechanism BYPASS Depending on the scopes associated to a token, you will be granted (or denied) access to perform certain operations. The following lists the available scopes: Scope Actions allowed https://jans.io/scim/users.read Query user resources https://jans.io/scim/users.write Modify user resources https://jans.io/scim/groups.read Query group resources https://jans.io/scim/groups.write Modify group resources https://jans.io/scim/fido.read Query fido resources https://jans.io/scim/fido.write Modify fido resources https://jans.io/scim/fido2.read Query fido 2 resources https://jans.io/scim/fido2.write Modify fido 2 resources https://jans.io/scim/all-resources.search Access the root .search endpoint https://jans.io/scim/bulk Send requests to the bulk endpoint In order to facilitate the process of getting an access token, your Janssen installation already bundles an OAuth client named \"SCIM client\" with support for all the scopes above. This client uses the client_credentials grant type and client_secret_basic mechanism to authenticate to the token endpoint.", "title": "API Protection"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#where-to-locate-scim-related-logs", "text": "Please see here besides SCIM log is located at /opt/jans/jetty/jans-scim/logs/scim.log If you use SCIM custom script aslo see /opt/jans/jetty/jans-scim/logs/scim_script.log", "title": "Where to locate SCIM-related logs"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#api-documentation-at-a-glance", "text": "SCIM API doc page describes about our implementation of SCIM. The API has also been documented using OpenAPI (swagger) specification for the interested. Find yaml files here .", "title": "API documentation at a glance"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#working-in-oauth-mode", "text": "To know more about OAuth protection mode please visit here . The SCIM API endpoints are by default protected by (Bearer) OAuth 2.0 tokens. Depending on the operation, these tokens must have certain scopes for the operations to be authorized. We need a client to get Bearer token.", "title": "Working in OAuth mode"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#get-scim-client", "text": "Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. To see in JSON formate please press d . From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE .", "title": "Get SCIM Client"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#get-access-token", "text": "Let's get a token, curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type=client_credentials -d scope='https://jans.io/scim/users.read https://jans.io/scim/users write' https://<jans-server>/jans-auth/restv1/token > /tmp/token.json In response token.json we will get access_token { \"access_token\":\"11a76589-7955-4247-9ca5-f3ad7884305...\", \"scope\":\"https://jans.io/scim/users.read\", \"token_type\":\"Bearer\", \"expires_in\":299 }", "title": "Get Access token"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#retrive-existing-user", "text": "To get an existing user curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://<jans-server>/jans-scim/restv1/v2/Users > /tmp/user.json In response user.json we will get { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\": 1, \"startIndex\": 1, \"itemsPerPage\": 1, \"Resources\": [ { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"5fdbb720-a1fd-477f-af92-b7c054f02c98\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-12T14:54:09.531Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/5fdbb720-a1fd-477f-af92-b7c054f02c98\" }, \"userName\": \"admin\", \"name\": { \"familyName\": \"...\", \"givenName\": \"...\", \"middleName\": \"...\", \"formatted\": \"...\" }, \"displayName\": \"Admin\", \"active\": true, \"emails\": [ { \"value\": \"example@gluu.org\", \"primary\": false } ], \"groups\": [ { \"value\": \"60B7\", \"display\": \"Jannsen Manager Group\", \"type\": \"direct\", \"$ref\": \"https://raju.jans13.me/jans-scim/restv1/v2/Groups/60B7\" } ] } ] }", "title": "Retrive existing User"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#creating-resource", "text": "", "title": "Creating Resource"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#create-an-user", "text": "Let's start creating a dummy user. A client sends a POST request containing a \"User\" to the \"/Users\" endpoint. POST /Users HTTP/1.1 Host: example.com Accept: application/scim+json Content-Type: application/scim+json Authorization: Bearer h480djs93hd8.. Content-Length: ... { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" } } Open a text editor and copy paste the json body, name as input.json . Hit on your terminal with bellow command. curl -k -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users response looks like { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T19:43:32.945Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Barbara\", \"formatted\": \"Ms. Barbara J Jensen III\" } } This new user has been given an id . If possible, inspect your ou=people branch and find the entry whose inum matches the id given. An easier option would be to via Jans TUI and go to Users and search \"bjensen\" to see the recently created user.", "title": "Create an User"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#updating-a-userput", "text": "Overwrite your input.json with the following. Replace content in angle brackets accordingly: { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" }, \"displayName\": \"Jensen Barbara\", \"emails\": [ { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": true } ] } PUT with curl: curl -k -X PUT -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Response (output.json) will show the same contents of a full retrieval. Please verify changes were applied whether by inspecting LDAP or issuing a GET. If you have followed the steps properly, you should notice a new e-mail added and the change in displayName attribute", "title": "Updating a User(PUT)"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#updating-a-user-patch", "text": "With patching, you can be very precise about the modifications you want to apply. Patching syntax follows JSON Patch spec (RFC 6902) closely. While it's not a must to read the RFC to learn how patch works, see section 3.5.2 of SCIM protocol (RFC 7644) to get the grasp. If you prefer reading code, patch test cases found in the Java scim-client project are worth to look at. The following is a simple example that illustrates the kind of modifications developers can achieve via PATCH . Overwrite your input.json with the following: { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"value\": { \"name\": { \"givenName\": \"Joey\" } } }, { \"op\": \"replace\", \"path\": \"emails[type eq \\\"work\\\" or primary eq false].value\", \"value\": \"jensen@example.com\" }, { \"op\": \"add\", \"value\": { \"name\": { \"middleName\": \"Jhon\" } } }, { \"op\": \"add\", \"value\": { \"emails\": [ { \"primary\": true, \"value\": \"my@own.mail\" } ], \"phoneNumbers\": [ { \"type\": \"home\", \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } }, { \"op\": \"remove\", \"path\": \"name.middleName\" }, { \"op\": \"remove\", \"path\": \"phoneNumbers[value ew \\\"01\\\"].type\" } ] } A collection of modification are provided under \"Operations\". They are processed in order of appearance. Also, every operation has a type; patching supports add, remove and replace. The first operations states the following: replace the value of givenName subattribute (that belongs to complex attribute name ) with the string \"Joey\". Operations are easier to understand when using a \"path\". The second operation replaces the value subattribute inside the complex multi-valued attribute emails. Inside the square brackets, we find a filter expression, so the replacement does not apply to all emails in the list but only to those matching the criterion. So the second operation can be read as \"set the value of value subattribute to string jensen@example.com where the type subattribute of the email equals to string \"work\" or if primary attribute is false\". The third operation is similar to the first. It sets the value of a subattribute which was unassigned (null). You could have used \"replace\" operation in this case and results would have been identical. The fourth operation is more interesting. It adds to the current list of emails a new one. It supplies a couple of subattributes for the email to include: primary and value. Additionally, we set the value of (previously unassigned) phoneNumbers multi-valued attribute passing a list of elements. In the fifth operation, we remove the middleName attribute that was set in operation three. Note how we make explicit the path of data to nullify: \"name.middleName\". The sixth operation allows us to remove a specific subattribute of phoneNumbers . The aim is to nullify the \"type\" of the item whose phone number value ends with \"01\". The remove operation can also be used to remove a complete item from a list, or empty the whole list by providing a suitable value for \"path\". Now let's see it in action: curl -k -X PATCH -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> So far our resource look like this { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T22:34:27.465Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Joey\", \"formatted\": \"Ms. Barbara J Jensen III\" }, \"displayName\": \"Jensen Barbara\", \"active\": false, \"emails\": [ { \"value\": \"my@own.mail\", \"primary\": true }, { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": false } ], \"phoneNumbers\": [ { \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } Note the primary subattribute accompanying email \"my@own.mail\" is false but when inserted we provided true . This is because the SCIM specification states that after modifications are applied to resources (PUT or PATCH) , there cannot be more than one item in a multi-valued attribute with primary value set as true . To see more sample JSON payloads, check the .json files used by the scim-client test cases referenced above.", "title": "Updating a User (PATCH)"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#deleting-users", "text": "For deleting, the DELETE method of HTTP is used. No input file is used in this case. A delete request could be the following: curl -k -X DELETE -H 'Authorization: Bearer ACCESS_TOKEN' https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Use the inum of our dummy user, Jensen Barbara . Check your LDAP or via Jans TUI to see that Bjensen is gone.", "title": "Deleting Users"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#how-is-scim-data-stored", "text": "SCIM schema spec does not use LDAP attribute names but a different naming convention for resource attributes (note this is not the case of custom attributes where the SCIM name used is that of the LDAP attribute). It is possible to determine if a given LDAP attribute is being mapped to a SCIM attribute. For that you need to check in Jans TUI Auth-Server >> Attributes and click on any attributes. Check Include in SCIM Extension: is true or false . Whenever you try to map any LDAP attribute to a SCIM attribute keep it's value true .", "title": "How is SCIM data stored?"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#fido-devices", "text": "A FIDO device represents a user credential stored in the Jans Server database that is compliant with the FIDO standard. These devices are used as a second factor in a setting of strong authentication. FIDO devices were superseded by FIDO 2 devices in Jans Server.", "title": "FIDO Devices"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#fido-2-devices", "text": "FIDO 2 devices are credentials that adhere to the more current Fido 2.0 initiative (WebAuthn + CTAP). Examples of FIDO 2 devices are USB security keys and Super Gluu devices. The SCIM endpoints for FIDO 2 allow application developers to query, update and delete already existing devices. Addition of devices do not take place through the service since this process requires direct end-user interaction, ie. device enrolling. The schema attributes for a device of this kind can be found by hitting the URL https://<jans-server>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:Fido2Device To distinguish between regular FIDO2 and SuperGluu devices, note only SuperGluu entries have the attribute deviceData populated (i.e. not null)", "title": "FIDO 2 devices"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#example-querying-enrolled-devices", "text": "Say we are interested in having a list of Super Gluu devices users have enrolled and whose operating system is iOS. We may issue a query like this: curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=deviceData co \"ios\"' -d count=10 https://<jans-server>/jans-scim/restv1/v2/Fido2Devices The response will be like: { \"totalResults\": ..., \"itemsPerPage\": ..., \"startIndex\": 1, \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"Resources\": [ { \"id\": \"...\", \"meta\": {...}, \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:Fido2Device\"], \"userId\": \"...\", ... \"deviceData\": \"{...}\", \"displayName\": ..., }, ... ] }", "title": "Example: Querying Enrolled Devices"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#potential-performance-issues-with-group-endpoints", "text": "In SCIM a group resource basically consists of an identifier, a display name, and a collection of members associated to it. Also, every member is made up of a user identifier, his display name, and other attributes. As a consequence, retrieving group information requires making a correlation with existing user data. Since Gluu database model does not follow a relational database pattern this may entail a considerable amount of user queries when groups contain thousands of members. While this could have been workarounded by storing members' display names inside group entries, this brings additional problems to deal with. Another source of potential overhead stems from creation and modification of groups where many new users are associated to a given group: by default checks are made to guarantee only existing users are attached to groups, thus requiring continuous database queries. Currently there are two ways to lower the amount of database lookups required for SCIM group operations: Explicitly excluding display names from responses Pass the overhead bypass flag to skip members validations The first approach consists of using the query parameter excludedAttributes (see RFC 7644 ) so that display names are neither retrieved from database nor sent in responses. A value like members.display does the job. Note the query parameter attributes can also be used for this purpose, for example with a value like members.value that will output only members' identifiers and ignore other non-required attributes. This approach is particularly useful in search and retrievals when users' display names are not needed. The second is a stronger approach that turns off validation of incoming members data: if the usage of a POST/PUT/PATCH operation implies adding members, their existence is not verified, they will simply get added. Here, the client application is responsible for sending accurate data. To use this approach add a query or header parameter named Group-Overhead-Bypass with any value. Note under this mode of operation: Display names are never returned regardless of attributes or excludedAttributes parameters values Remove/replace patch operations that involve display names in path filters are ignored, eg: \"path\": \"members[value eq \\\"2819c223\\\" or display eq \\\"Joe\\\"]\"", "title": "Potential performance issues with Group endpoints"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#user-registration-process-with-scim", "text": "SCIM service has many use cases. One interesting and often arising is that of coding your own user registration process. With your SCIM endpoints you can build a custom application to maintain user entries in your database.", "title": "User Registration Process with SCIM"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#important-considerations", "text": "Here, you have some useful tips before you start: Choose a toolset you feel comfortable to work with. Keep in mind that you have to leverage the capabilities of your language/framework to issue complex HTTPS requests. Be sure that: You will be able to use at least the following verbs: GET, POST, PUT, and DELETE You can send headers in your requests as well as reading them from the service response If not supported natively, choose a library to facilitate JSON content manipulation. As you have already noticed we have been dealing with JSON for requests as well as for responses. Experience shows that being able to map from objects (or data structures) of your language to Json and viceversa helps saving hours of coding. Shape your data model early. List the attributes your application will operate upon and correlate with those found in the SCIM user schema. You can learn about the schema in RFC 7644 . At least, take a look at the JSON-formatted schema that your Jans Server shows: visit https://<host-name>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:User You will have to manipulate database contents very often as you develop and run tests, thus, find a suitable tool for the task. In the case of LDAP, a TUI client is a good choice. Always check your logs . In this user management guide with SCIM, we have already touched upon the fundamentals of SCIM in Jans Server and shown a good amount of sample requests for manipulation of user information. However, keep in mind the SCIM spec documents are definitely the key reference to build working request messages, specially RFC 7643 , and RFC 7644 .", "title": "Important Considerations"}, {"location": "janssen-server/vm-ops/backup/", "tags": ["administration", "vm", "operations", "backup"], "text": "Janssen VM Backup # Best method of Janssen Backup is \"VM Snapshot\" backup. That means, backup / take snapshot of whole virtual machine / droplet / instance which is hosting your Gluu Janssen software. In the event of a production outage, a proper snapshot of the last working condition will help rapidly restore service. Most platform virtualization software and cloud vendors have snapshot backup features. For instance, Digital Ocean has Live Snapshot and Droplet Snapshot; VMWare has Snapshot Manager, etc. The Gluu Server should be backed up frequently-- we recommend at least one daily and one weekly backup of Gluu's data and/or VM . It's also good to have some partial configuration backup as well. Such as: Tarball /opt Tarball /etc/jans Tarball /etc/apache2 Tarball /var/jans Tarball Method # All Jans Server files live in a single folder: /opt. The entire Jans Server folder can be archived using the tar command: Stop the server: systemctl stop list-units --all \"jans*\" Use tar to take a backup: tar cvf jans-backup.tar /opt/jans/ Start the server again: systemctl start list-units --all \"jans*\"", "title": "Backup"}, {"location": "janssen-server/vm-ops/backup/#janssen-vm-backup", "text": "Best method of Janssen Backup is \"VM Snapshot\" backup. That means, backup / take snapshot of whole virtual machine / droplet / instance which is hosting your Gluu Janssen software. In the event of a production outage, a proper snapshot of the last working condition will help rapidly restore service. Most platform virtualization software and cloud vendors have snapshot backup features. For instance, Digital Ocean has Live Snapshot and Droplet Snapshot; VMWare has Snapshot Manager, etc. The Gluu Server should be backed up frequently-- we recommend at least one daily and one weekly backup of Gluu's data and/or VM . It's also good to have some partial configuration backup as well. Such as: Tarball /opt Tarball /etc/jans Tarball /etc/apache2 Tarball /var/jans", "title": "Janssen VM Backup"}, {"location": "janssen-server/vm-ops/backup/#tarball-method", "text": "All Jans Server files live in a single folder: /opt. The entire Jans Server folder can be archived using the tar command: Stop the server: systemctl stop list-units --all \"jans*\" Use tar to take a backup: tar cvf jans-backup.tar /opt/jans/ Start the server again: systemctl start list-units --all \"jans*\"", "title": "Tarball Method"}, {"location": "janssen-server/vm-ops/certificates/", "tags": ["administration", "vm", "operations", "certificates"], "text": "Janssen Certificates # Janssen components have cryptographic keys and X.509 certificates that are stored on the filesystem at the time of installation. Details for certificates associated with each component are provided below. The following certificates are available in the /etc/certs folder. APACHE Jans Auth CA Certificates httpd.crt jans-auth-keys.p12 https.csr httpd.key httpd.key.orig Custom Script JSON Files # Additionally the following json files are available which are used in different custom scripts for multi-factor authentication. cert_creds.json duo_creds.json gplus_client_secrets.json otp_configuration.json super_gluu_creds.json vericloud_jans_creds.json Updating certificates # On a fresh VM installation, Janssen generates self signed certificates. You will want to change these to real certificates. For this documentation we will use certbot using Let's Encrypt certificates. Certbot recommends using snap to install certbot and obtain certificates. The following instructions are for Ubuntu 20; however, any platform supporting snap should work. Backup the /etc/certs folder on your server Install snap sudo snap install core ; sudo snap refresh core Remove any certbot OS packages. This varies across distributions. For Ubuntu: sudo apt remove certbot Install certbot: sudo snap install --classic certbot Issue certificate: certbot --apache -d fqdn_of_Gluu_server Full certificate chain and key are available in: /etc/letsencrypt/live/ location. Reboot your server Installing intermediate certificates # Please follow these steps to install intermediate certificates: Place your intermediate certificate file in /etc/certs Modify /etc/apache2/sites-available/https_jans.conf and add SSLCertificateChainFile /etc/certs/name_of_your_interm_root_cert.crt under the line containing SSLCertificateKeyFile Restart the httpd/apache2 service", "title": "Certificates"}, {"location": "janssen-server/vm-ops/certificates/#janssen-certificates", "text": "Janssen components have cryptographic keys and X.509 certificates that are stored on the filesystem at the time of installation. Details for certificates associated with each component are provided below. The following certificates are available in the /etc/certs folder. APACHE Jans Auth CA Certificates httpd.crt jans-auth-keys.p12 https.csr httpd.key httpd.key.orig", "title": "Janssen Certificates"}, {"location": "janssen-server/vm-ops/certificates/#custom-script-json-files", "text": "Additionally the following json files are available which are used in different custom scripts for multi-factor authentication. cert_creds.json duo_creds.json gplus_client_secrets.json otp_configuration.json super_gluu_creds.json vericloud_jans_creds.json", "title": "Custom Script JSON Files"}, {"location": "janssen-server/vm-ops/certificates/#updating-certificates", "text": "On a fresh VM installation, Janssen generates self signed certificates. You will want to change these to real certificates. For this documentation we will use certbot using Let's Encrypt certificates. Certbot recommends using snap to install certbot and obtain certificates. The following instructions are for Ubuntu 20; however, any platform supporting snap should work. Backup the /etc/certs folder on your server Install snap sudo snap install core ; sudo snap refresh core Remove any certbot OS packages. This varies across distributions. For Ubuntu: sudo apt remove certbot Install certbot: sudo snap install --classic certbot Issue certificate: certbot --apache -d fqdn_of_Gluu_server Full certificate chain and key are available in: /etc/letsencrypt/live/ location. Reboot your server", "title": "Updating certificates"}, {"location": "janssen-server/vm-ops/certificates/#installing-intermediate-certificates", "text": "Please follow these steps to install intermediate certificates: Place your intermediate certificate file in /etc/certs Modify /etc/apache2/sites-available/https_jans.conf and add SSLCertificateChainFile /etc/certs/name_of_your_interm_root_cert.crt under the line containing SSLCertificateKeyFile Restart the httpd/apache2 service", "title": "Installing intermediate certificates"}, {"location": "janssen-server/vm-ops/checking-service-status/", "tags": ["administration", "vm", "operations", "services", "status"], "text": "Janssen System Services # In order to debug issues, checking the Jans services may be necessary. The process to do this differs slightly between operating systems. The following examples are shown on Ubuntu 20.04; however, they should work on any operating system using systemd. Getting list of Jans services # $ sudo systemctl list-units --all \"jans*\" UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed. Other Services # There are more services other than Jans services like Apache. To get the status of those services make sure you use command like sudo systemctl list-units --all \"apache2*\" Note: depending on your OS and the components of Jans installed, the output may be different. Checking status of a service # $ sudo systemctl status jans-auth.service \u25cf jans-auth.service - Janssen OAauth service Loaded: loaded ( /etc/systemd/system/jans-auth.service ; enabled ; vendor preset: enabled ) Active: active ( running ) since Tue 2022 -11-01 15 :03:23 UTC ; 1h 38min ago Process: 44700 ExecStart = /opt/dist/scripts/jans-auth start ( code = exited, status = 0 /SUCCESS ) Main PID: 44727 ( java ) Tasks: 60 ( limit: 4677 ) Memory: 889 .2M CGroup: /system.slice/jans-auth.service \u2514\u250044727 /opt/jre/bin/java -server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base = /etc/jans -Dserver.base = /opt/jans/jetty/jan> In case of an error or a non-functional component, this is where you would find information about the component.", "title": "Checking Service Status"}, {"location": "janssen-server/vm-ops/checking-service-status/#janssen-system-services", "text": "In order to debug issues, checking the Jans services may be necessary. The process to do this differs slightly between operating systems. The following examples are shown on Ubuntu 20.04; however, they should work on any operating system using systemd.", "title": "Janssen System Services"}, {"location": "janssen-server/vm-ops/checking-service-status/#getting-list-of-jans-services", "text": "$ sudo systemctl list-units --all \"jans*\" UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed.", "title": "Getting list of Jans services"}, {"location": "janssen-server/vm-ops/checking-service-status/#other-services", "text": "There are more services other than Jans services like Apache. To get the status of those services make sure you use command like sudo systemctl list-units --all \"apache2*\" Note: depending on your OS and the components of Jans installed, the output may be different.", "title": "Other Services"}, {"location": "janssen-server/vm-ops/checking-service-status/#checking-status-of-a-service", "text": "$ sudo systemctl status jans-auth.service \u25cf jans-auth.service - Janssen OAauth service Loaded: loaded ( /etc/systemd/system/jans-auth.service ; enabled ; vendor preset: enabled ) Active: active ( running ) since Tue 2022 -11-01 15 :03:23 UTC ; 1h 38min ago Process: 44700 ExecStart = /opt/dist/scripts/jans-auth start ( code = exited, status = 0 /SUCCESS ) Main PID: 44727 ( java ) Tasks: 60 ( limit: 4677 ) Memory: 889 .2M CGroup: /system.slice/jans-auth.service \u2514\u250044727 /opt/jre/bin/java -server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base = /etc/jans -Dserver.base = /opt/jans/jetty/jan> In case of an error or a non-functional component, this is where you would find information about the component.", "title": "Checking status of a service"}, {"location": "janssen-server/vm-ops/logs/", "tags": ["administration", "vm", "operations", "log-levels"], "text": "Janssen Log Configuration # The Janssen logs can be viewed via SSH access to the server running the Janssen installation. Log Levels # The following log levels can be configured through the configuration CLI: Log Level Messages Logged Trace All messages Debug Debug level and above Info Informational level and above Warn Warning level and above Error Error level and above Fatal Only fatal errors Off Logging is disabled Configuring Log Levels # Use the following commands to get information on the logging module configuration: To get the logging configuration operation ID: jans cli --info ConfigurationLogging Output would be: # Log configuration operations Operation ID: get-config-logging Description: Returns Jans Authorization Server logging settings. Operation ID: put-config-logging Description: Updates Jans Authorization Server logging settings. Schema: /components/schemas/LoggingConfiguration To get sample schema type jans cli --schema <schma> , for example jans cli --schema /components/schemas/LoggingConfiguration Output: # Generic configuration schema { \"loggingLevel\": \"TRACE\", \"loggingLayout\": \"json\", \"httpLoggingEnabled\": true, \"disableJdkLogger\": false, \"enabledOAuthAuditLogging\": true, \"externalLoggerConfiguration\": null, \"httpLoggingExcludePaths\": [ \"/auth/img\", \"/auth/stylesheet\" ] } Status of current configuration logging: jans cli --operation-id get-config-logging Output: # Current log configuration { \"loggingLevel\": \"INFO\", \"loggingLayout\": \"text\", \"httpLoggingEnabled\": false, \"disableJdkLogger\": true, \"enabledOAuthAuditLogging\": false, \"externalLoggerConfiguration\": null, \"httpLoggingExcludePaths\": null } Let's assume we want to update logging configuration to TRACE . To do this, create a file /tmp/log.json with the following content: { \"loggingLevel\" : \"TRACE\" , \"loggingLayout\" : \"text\" , \"httpLoggingEnabled\" : false , \"disableJdkLogger\" : true , \"enabledOAuthAuditLogging\" : false , \"externalLoggerConfiguration\" : null , \"httpLoggingExcludePaths\" : null } And use the PUT operation with this file as the payload: jans cli --operation-id put-config-logging --data /tmp/log.json The server will now have logs set to TRACE. Setup Logs # The Jans setup logs are available under /opt/jans/jans-setup/logs/ . There are several log files available involving the setup process: mysql.log (Only used if MySQL backend is chosen during setup) os-changes.log setup.log setup_error.log Core Logs # The available logs for Jans server are listed below: Config API logs # /opt/jans/jetty/jans-config-api/logs/ Log File Description configapi.log Config API main log configapi_persistence.log Config API persistence log configapi_persistence_duration.log Config API persistence operation duration log [date].jetty.log Config API Jetty log configapi_script.log Config API custom script log Jans Auth server logs # /opt/jans/jetty/jans-auth/logs/ The most important log files here are described below: jans-auth.log : This log file contains most authentication related information. Generally this is the first log to review for any authentication-related troubleshooting, like authentication failure or missing clients etc. jans-auth_persistence.log : This log file contains information about the Jans Auth server communicating with the persistence backend. jans-auth_script.log : This log file contains debug messages printed from interception scripts . Server Logs # In some cases, it may be necessary to examine the server logs themselves. OS Logs # For Debian based systems: /var/log/syslog For RPM based systems: /var/log/messages Apache2 Server Logs # For Debian based systems: /var/log/apache2/ For RPM based systems: /var/log/httpd/ Apache2 logs are as follows: access_log : This log contains information about requests coming into the Jans Server, success status or requests, execution time for any request etc. error_log : This log shows error messages if the web server encounter any issue while processing incoming requests. other_vhosts_access.log : This log is specific to the Jans Server setup and those links which are being requested by a user from a web browser.", "title": "Logs"}, {"location": "janssen-server/vm-ops/logs/#janssen-log-configuration", "text": "The Janssen logs can be viewed via SSH access to the server running the Janssen installation.", "title": "Janssen Log Configuration"}, {"location": "janssen-server/vm-ops/logs/#log-levels", "text": "The following log levels can be configured through the configuration CLI: Log Level Messages Logged Trace All messages Debug Debug level and above Info Informational level and above Warn Warning level and above Error Error level and above Fatal Only fatal errors Off Logging is disabled", "title": "Log Levels"}, {"location": "janssen-server/vm-ops/logs/#configuring-log-levels", "text": "Use the following commands to get information on the logging module configuration: To get the logging configuration operation ID: jans cli --info ConfigurationLogging Output would be: # Log configuration operations Operation ID: get-config-logging Description: Returns Jans Authorization Server logging settings. Operation ID: put-config-logging Description: Updates Jans Authorization Server logging settings. Schema: /components/schemas/LoggingConfiguration To get sample schema type jans cli --schema <schma> , for example jans cli --schema /components/schemas/LoggingConfiguration Output: # Generic configuration schema { \"loggingLevel\": \"TRACE\", \"loggingLayout\": \"json\", \"httpLoggingEnabled\": true, \"disableJdkLogger\": false, \"enabledOAuthAuditLogging\": true, \"externalLoggerConfiguration\": null, \"httpLoggingExcludePaths\": [ \"/auth/img\", \"/auth/stylesheet\" ] } Status of current configuration logging: jans cli --operation-id get-config-logging Output: # Current log configuration { \"loggingLevel\": \"INFO\", \"loggingLayout\": \"text\", \"httpLoggingEnabled\": false, \"disableJdkLogger\": true, \"enabledOAuthAuditLogging\": false, \"externalLoggerConfiguration\": null, \"httpLoggingExcludePaths\": null } Let's assume we want to update logging configuration to TRACE . To do this, create a file /tmp/log.json with the following content: { \"loggingLevel\" : \"TRACE\" , \"loggingLayout\" : \"text\" , \"httpLoggingEnabled\" : false , \"disableJdkLogger\" : true , \"enabledOAuthAuditLogging\" : false , \"externalLoggerConfiguration\" : null , \"httpLoggingExcludePaths\" : null } And use the PUT operation with this file as the payload: jans cli --operation-id put-config-logging --data /tmp/log.json The server will now have logs set to TRACE.", "title": "Configuring Log Levels"}, {"location": "janssen-server/vm-ops/logs/#setup-logs", "text": "The Jans setup logs are available under /opt/jans/jans-setup/logs/ . There are several log files available involving the setup process: mysql.log (Only used if MySQL backend is chosen during setup) os-changes.log setup.log setup_error.log", "title": "Setup Logs"}, {"location": "janssen-server/vm-ops/logs/#core-logs", "text": "The available logs for Jans server are listed below:", "title": "Core Logs"}, {"location": "janssen-server/vm-ops/logs/#config-api-logs", "text": "/opt/jans/jetty/jans-config-api/logs/ Log File Description configapi.log Config API main log configapi_persistence.log Config API persistence log configapi_persistence_duration.log Config API persistence operation duration log [date].jetty.log Config API Jetty log configapi_script.log Config API custom script log", "title": "Config API logs"}, {"location": "janssen-server/vm-ops/logs/#jans-auth-server-logs", "text": "/opt/jans/jetty/jans-auth/logs/ The most important log files here are described below: jans-auth.log : This log file contains most authentication related information. Generally this is the first log to review for any authentication-related troubleshooting, like authentication failure or missing clients etc. jans-auth_persistence.log : This log file contains information about the Jans Auth server communicating with the persistence backend. jans-auth_script.log : This log file contains debug messages printed from interception scripts .", "title": "Jans Auth server logs"}, {"location": "janssen-server/vm-ops/logs/#server-logs", "text": "In some cases, it may be necessary to examine the server logs themselves.", "title": "Server Logs"}, {"location": "janssen-server/vm-ops/logs/#os-logs", "text": "For Debian based systems: /var/log/syslog For RPM based systems: /var/log/messages", "title": "OS Logs"}, {"location": "janssen-server/vm-ops/logs/#apache2-server-logs", "text": "For Debian based systems: /var/log/apache2/ For RPM based systems: /var/log/httpd/ Apache2 logs are as follows: access_log : This log contains information about requests coming into the Jans Server, success status or requests, execution time for any request etc. error_log : This log shows error messages if the web server encounter any issue while processing incoming requests. other_vhosts_access.log : This log is specific to the Jans Server setup and those links which are being requested by a user from a web browser.", "title": "Apache2 Server Logs"}, {"location": "janssen-server/vm-ops/managing-key-rotation/", "tags": ["administration", "vm", "operations"], "text": "Managing Key Rotation # \"Key-rotation\" is a standard procedure for all OpenID Connect deployment. \"Key-rotation\" means replacing existing signing key with newer cryptographic key. For Janssen server, that specific cryptographic key is jans-auth-keys.pkcs12 . There are two possible ways to manage key rotation: - built-in key rotation - external key rotation For VM by default built-in key rotation is on. Key alias or kid has following format (example connect_76297462-a3f8-498e-afc2-670285292553_sig_rs256 ): <operation_type>_<guid>_<use>_<algorithm> operation_type - specifies operation type of the key, possible values: connect - used for OpenID Connect - usually expirable key ssa - used for SSA - usually with very big expiration date (almost non-expirable) all - key can be use for both connect and ssa guid - unique identifier use - use purpose, possible values are sig for signature and enc for encryption algorithm - algorithm use with given key in signature case it can be RS256 , RS384 , RS512 , ES256 , ES384 , ES512 , PS256 , PS384 , PS512 in encryption case case it can be RSA1_5 , RSA-OAEP Key rotation means that new keys are generated and old one are removed for given algorithm (full replacement). Keys are stored in: - key store file (specified by keyStoreFile ) - on persistence level jwks representation of the key are stored in jansConfWebKeys attribute of jansAppConf entity It's important to note that key inside key store file must have representation in jwks and vice versa. It must be always in sync otherwise AS will throw error. Configuration properties related to key store file: - keyStoreFile - The Key Store File (JKS or PKCS12) - keyStoreSecret - The Key Store password Built-in key rotation # jans-auth-server has KeyGeneratorTimer which is responsible for key rotation. Built-in rotation can be switch on/off via keyRegenerationEnabled AS configuration property (by setting true or false value). graph LR A[Auth Server] --> V(Properties) erDiagram keyRotation { string keyRegenerationEnabled \"True\" string keyRenerationInterval \"48\" string keySelectionStrategy \"OLDER\" string keySignWithSameKeyButDiffAlg \"False\" string keyStoreFile \"/etc/certs/jans-auth-keys.pkcs12\" } Configuration properties relation to built-in rotation: - keyRegenerationEnabled - boolean value specifying whether to turn on ( true value) or off ( false value) built-in key rotation - keyRegenerationInterval - the interval for key regeneration in hours - keyAlgsAllowedForGeneration - List of algorithm allowed to be used for key generation Expiration date during built-in rotation is set as now + keyRegenerationInterval . External key rotation # External rotation means that keys are rotated by script. In this case keyRegenerationEnabled must be set to false value. Script can be scheduled to run periodically. Such script must invoke KeyGenerator class from jans-auth-client-jar-with-dependencies.jar which will keep keys in key store and in AS persistence consistent. See Key Generation page for more details how to generate keys externally. /opt/jre/bin/java -Dlog4j.defaultInitOverride=true -cp /opt/dist/jans/jans-auth-client-jar-with-dependencies.jar io.jans.as.client.util.KeyGenerator -keystore /etc/certs/jans-auth-keys.p12 -keypasswd <Password> -sig_keys RS256 RS384 -enc_keys RSA1_5 RSA-OAEP -key_ops_type ALL -dnname \"CN=jansAuth CA Certificates\" -expiration 2 > /etc/certs/jans-auth-keys.json Useful references # Key Generation", "title": "Managing Key Rotation"}, {"location": "janssen-server/vm-ops/managing-key-rotation/#managing-key-rotation", "text": "\"Key-rotation\" is a standard procedure for all OpenID Connect deployment. \"Key-rotation\" means replacing existing signing key with newer cryptographic key. For Janssen server, that specific cryptographic key is jans-auth-keys.pkcs12 . There are two possible ways to manage key rotation: - built-in key rotation - external key rotation For VM by default built-in key rotation is on. Key alias or kid has following format (example connect_76297462-a3f8-498e-afc2-670285292553_sig_rs256 ): <operation_type>_<guid>_<use>_<algorithm> operation_type - specifies operation type of the key, possible values: connect - used for OpenID Connect - usually expirable key ssa - used for SSA - usually with very big expiration date (almost non-expirable) all - key can be use for both connect and ssa guid - unique identifier use - use purpose, possible values are sig for signature and enc for encryption algorithm - algorithm use with given key in signature case it can be RS256 , RS384 , RS512 , ES256 , ES384 , ES512 , PS256 , PS384 , PS512 in encryption case case it can be RSA1_5 , RSA-OAEP Key rotation means that new keys are generated and old one are removed for given algorithm (full replacement). Keys are stored in: - key store file (specified by keyStoreFile ) - on persistence level jwks representation of the key are stored in jansConfWebKeys attribute of jansAppConf entity It's important to note that key inside key store file must have representation in jwks and vice versa. It must be always in sync otherwise AS will throw error. Configuration properties related to key store file: - keyStoreFile - The Key Store File (JKS or PKCS12) - keyStoreSecret - The Key Store password", "title": "Managing Key Rotation"}, {"location": "janssen-server/vm-ops/managing-key-rotation/#built-in-key-rotation", "text": "jans-auth-server has KeyGeneratorTimer which is responsible for key rotation. Built-in rotation can be switch on/off via keyRegenerationEnabled AS configuration property (by setting true or false value). graph LR A[Auth Server] --> V(Properties) erDiagram keyRotation { string keyRegenerationEnabled \"True\" string keyRenerationInterval \"48\" string keySelectionStrategy \"OLDER\" string keySignWithSameKeyButDiffAlg \"False\" string keyStoreFile \"/etc/certs/jans-auth-keys.pkcs12\" } Configuration properties relation to built-in rotation: - keyRegenerationEnabled - boolean value specifying whether to turn on ( true value) or off ( false value) built-in key rotation - keyRegenerationInterval - the interval for key regeneration in hours - keyAlgsAllowedForGeneration - List of algorithm allowed to be used for key generation Expiration date during built-in rotation is set as now + keyRegenerationInterval .", "title": "Built-in key rotation"}, {"location": "janssen-server/vm-ops/managing-key-rotation/#external-key-rotation", "text": "External rotation means that keys are rotated by script. In this case keyRegenerationEnabled must be set to false value. Script can be scheduled to run periodically. Such script must invoke KeyGenerator class from jans-auth-client-jar-with-dependencies.jar which will keep keys in key store and in AS persistence consistent. See Key Generation page for more details how to generate keys externally. /opt/jre/bin/java -Dlog4j.defaultInitOverride=true -cp /opt/dist/jans/jans-auth-client-jar-with-dependencies.jar io.jans.as.client.util.KeyGenerator -keystore /etc/certs/jans-auth-keys.p12 -keypasswd <Password> -sig_keys RS256 RS384 -enc_keys RSA1_5 RSA-OAEP -key_ops_type ALL -dnname \"CN=jansAuth CA Certificates\" -expiration 2 > /etc/certs/jans-auth-keys.json", "title": "External key rotation"}, {"location": "janssen-server/vm-ops/managing-key-rotation/#useful-references", "text": "Key Generation", "title": "Useful references"}, {"location": "janssen-server/vm-ops/restarting-services/", "tags": ["administration", "vm", "operations", "services", "lifecycle"], "text": "Janssen System Services Lifecycle Management # Getting list of Jans services # sudo systemctl list-units --all \"jans*\" Output should be like below: UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed. Other Services # There are more services other than Jans services like Apache. To get the status of those services make sure you use command like sudo systemctl list-units --all \"apache2*\" Commands (Ubuntu 20.04, RHEL 8, SUSE 15) # Start # systemctl start [service name] Stop # systemctl stop [service name] Status # systemctl status [service name] Restart # systemctl restart [service name] Reload # This command is used for the apache2 and httpd services. systemctl reload [service name]", "title": "Restarting Services"}, {"location": "janssen-server/vm-ops/restarting-services/#janssen-system-services-lifecycle-management", "text": "", "title": "Janssen System Services Lifecycle Management"}, {"location": "janssen-server/vm-ops/restarting-services/#getting-list-of-jans-services", "text": "sudo systemctl list-units --all \"jans*\" Output should be like below: UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed.", "title": "Getting list of Jans services"}, {"location": "janssen-server/vm-ops/restarting-services/#other-services", "text": "There are more services other than Jans services like Apache. To get the status of those services make sure you use command like sudo systemctl list-units --all \"apache2*\"", "title": "Other Services"}, {"location": "janssen-server/vm-ops/restarting-services/#commands-ubuntu-2004-rhel-8-suse-15", "text": "", "title": "Commands (Ubuntu 20.04, RHEL 8, SUSE 15)"}, {"location": "janssen-server/vm-ops/restarting-services/#start", "text": "systemctl start [service name]", "title": "Start"}, {"location": "janssen-server/vm-ops/restarting-services/#stop", "text": "systemctl stop [service name]", "title": "Stop"}, {"location": "janssen-server/vm-ops/restarting-services/#status", "text": "systemctl status [service name]", "title": "Status"}, {"location": "janssen-server/vm-ops/restarting-services/#restart", "text": "systemctl restart [service name]", "title": "Restart"}, {"location": "janssen-server/vm-ops/restarting-services/#reload", "text": "This command is used for the apache2 and httpd services. systemctl reload [service name]", "title": "Reload"}, {"location": "janssen-server/vm-ops/upgrade/", "tags": ["administration", "VM", "operations", "upgrade"], "text": "This guide shows how to upgrade a Janssen VM deployment. Note VM deployments don't provide automatic upgrade/update support. Uninstalling and re-installing with newer binaries is the only option that requires re-configuration of auth-server. Though this is made easy using Terraform . We recommend using Kubernetes installations over VM, to avail smooth upgrades and better HA support. Let's assume we are upgrading Jans VM installation from current version to nightly Keep the old VM installation running. Install on a separate VM the target new Jans installation, i.e. nightly . You can install with a test client. For example: sudo python3 /opt/jans/jans-setup/setup.py -test-client-id 6382c9da-f25d-435f-ac63-6acde36f4859 -test-client-pw secret1172023 This client-id and client-pw will then be used to import Terraform configurations Use our Terraform docs on the new installation, i.e. nightly to: import all the global configurations from the new installation using terraform import define all the custom IDP configurations and apply them using terraform apply At this point there should be two versions up, old version and nightly . Traffic should be switched gradually from the old setup to the new setup. Once confidence is gained, drain the old VM.", "title": "Upgrade"}, {"location": "script-catalog/application_session/application-session/", "tags": ["administration", "developer", "script-catalog"], "text": "Application Session Script Guide # Overview # The Jans-Auth server allows you to modify the session flow through this script. Interface # The Application Session script implement the ApplicationSessionType interface. This extends methods form the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description def startSession(self, httpRequest, sessionId, configurationAttributes) Called when a session is started. def endSession(self, httpRequest, sessionId, configurationAttributes) Called when a session is ended. def onEvent(self, event) Called when a specific session event occurs.. def modifyActiveSessionsResponse(self, jsonArray, context) Called it during /session/active endpoint call to modify response if needed. All methods return true / false , the server issues an error if this response is false . If parameters is not present then error has to be created and false returned. If all is good script has to return true . Objects # Object name Object description customScript io.jans.model.custom.script.model.CustomScript context io.jans.as.server.service.external.context.ExternalScriptContext sessionId io.jans.as.common.model.session.SessionId event io.jans.as.server.service.external.session.SessionEvent httpRequest jakarta.servlet.http.HttpServletRequest jsonArray org.json.JSONArray configurationAttributes java.util.Map SimpleCustomProperty > Common Use Cases # startSession : Validate first session endSession : Print logs onEvent : If event type is AUTHENTICATED, print sessionId in logs modifyActiveSessionsResponse : Print logs Script type: Python # from io.jans.model.custom.script.type.session import ApplicationSessionType from io.jans.service.cdi.util import CdiUtil from io.jans.orm import PersistenceEntryManager from io.jans.as.model.config import StaticConfiguration from io.jans.as.server.model.ldap import TokenEntity from jakarta.faces.application import FacesMessage from io.jans.jsf2.message import FacesMessages from io.jans.util import StringHelper , ArrayHelper from io.jans.as.server.model.config import Constants from java.util import Arrays , ArrayList from io.jans.as.server.service.external.session import SessionEventType import java class ApplicationSession ( ApplicationSessionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Application session. Initialization\" self . entryManager = CdiUtil . bean ( PersistenceEntryManager ) self . staticConfiguration = CdiUtil . bean ( StaticConfiguration ) print \"Application session. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Application session. Destroy\" print \"Application session. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def onEvent ( self , event ): if event . getType () == SessionEventType . AUTHENTICATED : print \"Session is authenticated, session: \" + event . getSessionId () . getId () return def startSession ( self , httpRequest , sessionId , configurationAttributes ): print \"Application session. Starting external session\" user_name = sessionId . getSessionAttributes () . get ( Constants . AUTHENTICATED_USER ) first_session = self . isFirstSession ( user_name ) if not first_session : facesMessages = CdiUtil . bean ( FacesMessages ) facesMessages . add ( FacesMessage . SEVERITY_ERROR , \"Please, end active session first!\" ) return False print \"Application session. External session started successfully\" return True def endSession ( self , httpRequest , sessionId , configurationAttributes ): print \"Application session. Starting external session end\" print \"Application session. External session ended successfully\" return True def modifyActiveSessionsResponse ( self , jsonArray , context ): print \"Application session. Starting external modify active session\" print \"Application session. External modify active session successfully\" return False def isFirstSession ( self , user_name ): tokenLdap = TokenEntity () tokenLdap . setDn ( self . staticConfiguration . getBaseDn () . getClients ()) tokenLdap . setUserId ( user_name ) tokenLdapList = self . entryManager . findEntries ( tokenLdap , 1 ) print \"Application session. isFirstSession. Get result: ' %s '\" % tokenLdapList if ( tokenLdapList != None ) and ( tokenLdapList . size () > 0 ): print \"Application session. isFirstSession: False\" return False print \"Application session. isFirstSession: True\" return True", "title": "Application Session"}, {"location": "script-catalog/application_session/application-session/#application-session-script-guide", "text": "", "title": "Application Session Script Guide"}, {"location": "script-catalog/application_session/application-session/#overview", "text": "The Jans-Auth server allows you to modify the session flow through this script.", "title": "Overview"}, {"location": "script-catalog/application_session/application-session/#interface", "text": "The Application Session script implement the ApplicationSessionType interface. This extends methods form the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/application_session/application-session/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/application_session/application-session/#new-methods", "text": "Method header Method description def startSession(self, httpRequest, sessionId, configurationAttributes) Called when a session is started. def endSession(self, httpRequest, sessionId, configurationAttributes) Called when a session is ended. def onEvent(self, event) Called when a specific session event occurs.. def modifyActiveSessionsResponse(self, jsonArray, context) Called it during /session/active endpoint call to modify response if needed. All methods return true / false , the server issues an error if this response is false . If parameters is not present then error has to be created and false returned. If all is good script has to return true .", "title": "New methods"}, {"location": "script-catalog/application_session/application-session/#objects", "text": "Object name Object description customScript io.jans.model.custom.script.model.CustomScript context io.jans.as.server.service.external.context.ExternalScriptContext sessionId io.jans.as.common.model.session.SessionId event io.jans.as.server.service.external.session.SessionEvent httpRequest jakarta.servlet.http.HttpServletRequest jsonArray org.json.JSONArray configurationAttributes java.util.Map SimpleCustomProperty >", "title": "Objects"}, {"location": "script-catalog/application_session/application-session/#common-use-cases", "text": "startSession : Validate first session endSession : Print logs onEvent : If event type is AUTHENTICATED, print sessionId in logs modifyActiveSessionsResponse : Print logs", "title": "Common Use Cases"}, {"location": "script-catalog/application_session/application-session/#script-type-python", "text": "from io.jans.model.custom.script.type.session import ApplicationSessionType from io.jans.service.cdi.util import CdiUtil from io.jans.orm import PersistenceEntryManager from io.jans.as.model.config import StaticConfiguration from io.jans.as.server.model.ldap import TokenEntity from jakarta.faces.application import FacesMessage from io.jans.jsf2.message import FacesMessages from io.jans.util import StringHelper , ArrayHelper from io.jans.as.server.model.config import Constants from java.util import Arrays , ArrayList from io.jans.as.server.service.external.session import SessionEventType import java class ApplicationSession ( ApplicationSessionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Application session. Initialization\" self . entryManager = CdiUtil . bean ( PersistenceEntryManager ) self . staticConfiguration = CdiUtil . bean ( StaticConfiguration ) print \"Application session. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Application session. Destroy\" print \"Application session. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def onEvent ( self , event ): if event . getType () == SessionEventType . AUTHENTICATED : print \"Session is authenticated, session: \" + event . getSessionId () . getId () return def startSession ( self , httpRequest , sessionId , configurationAttributes ): print \"Application session. Starting external session\" user_name = sessionId . getSessionAttributes () . get ( Constants . AUTHENTICATED_USER ) first_session = self . isFirstSession ( user_name ) if not first_session : facesMessages = CdiUtil . bean ( FacesMessages ) facesMessages . add ( FacesMessage . SEVERITY_ERROR , \"Please, end active session first!\" ) return False print \"Application session. External session started successfully\" return True def endSession ( self , httpRequest , sessionId , configurationAttributes ): print \"Application session. Starting external session end\" print \"Application session. External session ended successfully\" return True def modifyActiveSessionsResponse ( self , jsonArray , context ): print \"Application session. Starting external modify active session\" print \"Application session. External modify active session successfully\" return False def isFirstSession ( self , user_name ): tokenLdap = TokenEntity () tokenLdap . setDn ( self . staticConfiguration . getBaseDn () . getClients ()) tokenLdap . setUserId ( user_name ) tokenLdapList = self . entryManager . findEntries ( tokenLdap , 1 ) print \"Application session. isFirstSession. Get result: ' %s '\" % tokenLdapList if ( tokenLdapList != None ) and ( tokenLdapList . size () > 0 ): print \"Application session. isFirstSession: False\" return False print \"Application session. isFirstSession: True\" return True", "title": "Script type: Python"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/", "tags": ["administration", "developer", "script-catalog"], "text": "Authorization Challenge Custom Script # Overview # The Jans-Auth server implements OAuth 2.0 for First-Party Applications . This script is used to control/customize Authorization Challenge Endpoint. Behavior # In request to Authorization Challenge Endpoint to is expected to have acr_values request parameter which specifies name of the custom script. If parameter is absent or AS can't find script with this name then it falls back to script with name default_challenge . This script is provided during installation and performs basic username / password authentication. POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea&scope=openid+profile+address+email+phone+user_name&state=b4a41b29-51c8-4354-9c8c-fda38b4dbd43&nonce=3a56f8d0-f78e-4b15-857c-3e792801be68&acr_values=&request_session_id=false&password=secret&username=admin There is authorizationChallengeDefaultAcr AS configuration property which allows to change fallback script name from default_challenge to some other value (value must be valid script name present on AS). Interface # The Authorization Challenage script implements the AuthorizationChallenageType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description def authorize(self, context) Called when the request is received. def getAuthenticationMethodClaims(self, context) Called to get authn method claims. It is injected into id_token . Returns key-value map. def prepareAuthzRequest(self, context) Prepared authorization request before authorize method. It's good place to restore data from session if needed. authorize method returns true/false which indicates to server whether to issue authorization_code in response or not. If parameters is not present then error has to be created and false returned. If all is good script has to return true and it's strongly recommended to set user context.getExecutionContext().setUser(user); so AS can keep tracking what exactly user is authenticated. prepareAuthzRequest should typically be used for authorization request manipulation before authorize method is invoked. Also if there is multi-step flow where some data are stored in session object, it is good place to restore data from session into request (please find example in sample below). Objects # Object name Object description customScript The custom script object. Reference context Reference Common Use Case: Authorize user by username/password # Script Type: Java # import io.jans.as.common.model.common.User ; import io.jans.as.common.model.session.DeviceSession ; import io.jans.as.server.authorize.ws.rs.DeviceSessionService ; import io.jans.as.server.service.UserService ; import io.jans.as.server.service.external.context.ExternalScriptContext ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.authzchallenge.AuthorizationChallengeType ; import io.jans.orm.PersistenceEntryManager ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.service.custom.script.CustomScriptManager ; import org.apache.commons.lang3.StringUtils ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.util.Map ; import java.util.HashMap ; import java.util.UUID ; /** * @author Yuriy Z */ public class AuthorizationChallenge implements AuthorizationChallengeType { public static final String USERNAME_PARAMETER = \"username\" ; public static final String PASSWORD_PARAMETER = \"password\" ; private static final Logger log = LoggerFactory . getLogger ( AuthorizationChallenge . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); /** * Return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. * <p> * Implementation of this method should consist of 3 main parts: * 1. validate all parameters are present and if not -> set error and return false * 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true * 3. if not ok -> set error which explains what is wrong and return false * * @param scriptContext ExternalScriptContext, see https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/context/ExternalScriptContext.java * @return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. */ @Override public boolean authorize ( Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. validate all required parameters are present final String username = getParameterOrCreateError ( context , USERNAME_PARAMETER ); if ( StringUtils . isBlank ( username )) { return false ; } final String password = getParameterOrCreateError ( context , PASSWORD_PARAMETER ); if ( StringUtils . isBlank ( password )) { return false ; } scriptLogger . trace ( \"All required parameters are present\" ); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil . bean ( UserService . class ); PersistenceEntryManager entryManager = CdiUtil . bean ( PersistenceEntryManager . class ); final User user = userService . getUser ( username ); if ( user == null ) { scriptLogger . trace ( \"User is not found by username {}\" , username ); createError ( context , \"username_invalid\" ); return false ; } final boolean ok = entryManager . authenticate ( user . getDn (), User . class , password ); if ( ok ) { context . getExecutionContext (). setUser ( user ); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger . trace ( \"User {} is authenticated successfully.\" , username ); return true ; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger . trace ( \"Failed to authenticate user {}. Please check username and password.\" , username ); createError ( context , \"username_or_password_invalid\" ); return false ; } private String getParameterOrCreateError ( ExternalScriptContext context , String parameterName ) { String value = context . getHttpRequest (). getParameter ( parameterName ); if ( StringUtils . isBlank ( value )) { scriptLogger . trace ( \"No '{}' parameter in request\" , parameterName ); value = getParameterFromDeviceSession ( context , parameterName ); } if ( StringUtils . isBlank ( value )) { scriptLogger . trace ( \"{} is not provided\" , parameterName ); createError ( context , String . format ( \"%s_required\" , parameterName )); return null ; } return value ; } private void createError ( ExternalScriptContext context , String errorCode ) { String deviceSessionPart = prepareDeviceSessionSubJson ( context ); final String entity = String . format ( \"{\\\"error\\\": \\\"%s\\\"%s}\" , errorCode , deviceSessionPart ); context . createWebApplicationException ( 401 , entity ); } private String prepareDeviceSessionSubJson ( ExternalScriptContext context ) { DeviceSession authorizationChallengeSessionObject = context . getAuthzRequest (). getDeviceSessionObject (); if ( authorizationChallengeSessionObject != null ) { prepareDeviceSession ( context , authorizationChallengeSessionObject ); return String . format ( \",\\\"auth_session\\\":\\\"%s\\\"\" , authorizationChallengeSessionObject . getId ()); } else if ( context . getAuthzRequest (). isUseDeviceSession ()) { authorizationChallengeSessionObject = prepareDeviceSession ( context , null ); return String . format ( \",\\\"auth_session\\\":\\\"%s\\\"\" , authorizationChallengeSessionObject . getId ()); } return \"\" ; } private DeviceSession prepareDeviceSession ( ExternalScriptContext context , DeviceSession authorizationChallengeSessionObject ) { DeviceSessionService deviceSessionService = CdiUtil . bean ( DeviceSessionService . class ); boolean newSave = authorizationChallengeSessionObject == null ; if ( newSave ) { authorizationChallengeSessionObject = deviceSessionService . newDeviceSession (); } String username = context . getHttpRequest (). getParameter ( USERNAME_PARAMETER ); if ( StringUtils . isNotBlank ( username )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( USERNAME_PARAMETER , username ); } String password = context . getHttpRequest (). getParameter ( PASSWORD_PARAMETER ); if ( StringUtils . isNotBlank ( password )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( PASSWORD_PARAMETER , password ); } String clientId = context . getHttpRequest (). getParameter ( \"client_id\" ); if ( StringUtils . isNotBlank ( clientId )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"client_id\" , clientId ); } String acrValues = context . getHttpRequest (). getParameter ( \"acr_values\" ); if ( StringUtils . isNotBlank ( acrValues )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"acr_values\" , acrValues ); } if ( newSave ) { deviceSessionService . persist ( authorizationChallengeSessionObject ); } else { deviceSessionService . merge ( authorizationChallengeSessionObject ); } return authorizationChallengeSessionObject ; } private String getParameterFromDeviceSession ( ExternalScriptContext context , String parameterName ) { final DeviceSession authorizationChallengeSessionObject = context . getAuthzRequest (). getDeviceSessionObject (); if ( authorizationChallengeSessionObject != null ) { return authorizationChallengeSessionObject . getAttributes (). getAttributes (). get ( parameterName ); } return null ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Destroyed Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public Map < String , String > getAuthenticationMethodClaims ( Object context ) { return new HashMap <> (); } } Multi-step authorization by username and OTP # Script Type: Java # import io.jans.as.common.model.common.User; import io.jans.as.common.model.session.DeviceSession; import io.jans.as.server.authorize.ws.rs.DeviceSessionService; import io.jans.as.server.service.UserService; import io.jans.as.server.service.external.context.ExternalScriptContext; import io.jans.model.SimpleCustomProperty; import io.jans.model.custom.script.model.CustomScript; import io.jans.model.custom.script.type.authzchallenge.AuthorizationChallengeType; import io.jans.orm.PersistenceEntryManager; import io.jans.service.cdi.util.CdiUtil; import io.jans.service.custom.script.CustomScriptManager; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; import java.util.HashMap; import java.util.UUID; /** * Script is to demo 2 steps flow: * 1) First step -> send username * 2) Second step -> send OTP * * AS tracks data by 'auth_session'. See \"prepareDeviceSession()\" method implemention for details. * * @author Yuriy Z */ public class AuthorizationChallenge implements AuthorizationChallengeType { public static final String USERNAME_PARAMETER = \"username\"; public static final String OTP_PARAMETER = \"otp\"; private static final Logger log = LoggerFactory.getLogger(AuthorizationChallenge.class); private static final Logger scriptLogger = LoggerFactory.getLogger(CustomScriptManager.class); /** * Return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. * <p> * Implementation of this method should consist of 3 main parts: * 1. validate all parameters are present and if not -> set error and return false * 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true * 3. if not ok -> set error which explains what is wrong and return false * * @param scriptContext ExternalScriptContext, see https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/context/ExternalScriptContext.java * @return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. */ @Override public boolean authorize(Object scriptContext) { ExternalScriptContext context = (ExternalScriptContext) scriptContext; // 1. As first step we get username final String username = getParameterOrCreateError(context, USERNAME_PARAMETER); if (StringUtils.isBlank(username)) { return false; } // 2. During first execution OTP is not present, so error will be returned with auth_session (which has saved username) // Note: prepareDeviceSession method implemention final String otp = getParameterOrCreateError(context, OTP_PARAMETER); if (StringUtils.isBlank(otp)) { return false; } scriptLogger.trace(\"All required parameters are present\"); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil.bean(UserService.class); PersistenceEntryManager entryManager = CdiUtil.bean(PersistenceEntryManager.class); final User user = userService.getUser(username); if (user == null) { scriptLogger.trace(\"User is not found by username {}\", username); createError(context, \"username_invalid\"); return false; } // for simplicity OTP is here just username password but in real world scenario real OTP validation is needed. final boolean ok = entryManager.authenticate(user.getDn(), User.class, otp); if (ok) { context.getExecutionContext().setUser(user); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger.trace(\"User {} is authenticated successfully.\", username); return true; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger.trace(\"Failed to authenticate user {}. Please check username and OTP.\", username); createError(context, \"username_or_otp_invalid\"); return false; } private String getParameterOrCreateError(ExternalScriptContext context, String parameterName) { String value = context.getHttpRequest().getParameter(parameterName); if (StringUtils.isBlank(value)) { scriptLogger.trace(\"No '{}' parameter in request\", parameterName); value = getParameterFromDeviceSession(context, parameterName); } if (StringUtils.isBlank(value)) { scriptLogger.trace(\"{} is not provided\", parameterName); createError(context, String.format(\"%s_required\", parameterName)); return null; } return value; } private void createError(ExternalScriptContext context, String errorCode) { String deviceSessionPart = prepareDeviceSessionSubJson(context); final String entity = String.format(\"{\\\"error\\\": \\\"%s\\\"%s}\", errorCode, deviceSessionPart); context.createWebApplicationException(401, entity); } private String prepareDeviceSessionSubJson(ExternalScriptContext context) { DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { prepareDeviceSession(context, authorizationChallengeSessionObject); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } else if (context.getAuthzRequest().isUseDeviceSession()) { authorizationChallengeSessionObject = prepareDeviceSession(context, null); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } return \"\"; } private DeviceSession prepareDeviceSession(ExternalScriptContext context, DeviceSession authorizationChallengeSessionObject) { DeviceSessionService deviceSessionService = CdiUtil.bean(DeviceSessionService.class); boolean newSave = authorizationChallengeSessionObject == null; if (newSave) { authorizationChallengeSessionObject = deviceSessionService.newDeviceSession(); } String username = context.getHttpRequest().getParameter(USERNAME_PARAMETER); if (StringUtils.isNotBlank(username)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(USERNAME_PARAMETER, username); } String otp = context.getHttpRequest().getParameter(OTP_PARAMETER); if (StringUtils.isNotBlank(otp)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(OTP_PARAMETER, otp); } String clientId = context.getHttpRequest().getParameter(\"client_id\"); if (StringUtils.isNotBlank(clientId)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"client_id\", clientId); } String acrValues = context.getHttpRequest().getParameter(\"acr_values\"); if (StringUtils.isNotBlank(acrValues)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"acr_values\", acrValues); } if (newSave) { deviceSessionService.persist(authorizationChallengeSessionObject); } else { deviceSessionService.merge(authorizationChallengeSessionObject); } return authorizationChallengeSessionObject; } private String getParameterFromDeviceSession(ExternalScriptContext context, String parameterName) { final DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { return authorizationChallengeSessionObject.getAttributes().getAttributes().get(parameterName); } return null; } @Override public boolean init(Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Initialized Default AuthorizationChallenge Java custom script.\"); return true; } @Override public boolean init(CustomScript customScript, Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Initialized Default AuthorizationChallenge Java custom script.\"); return true; } @Override public boolean destroy(Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Destroyed Default AuthorizationChallenge Java custom script.\"); return true; } @Override public int getApiVersion() { return 11; } @Override public Map<String, String> getAuthenticationMethodClaims(Object context) { return new HashMap<>(); } @Override public void prepareAuthzRequest(Object scriptContext) { ExternalScriptContext context = (ExternalScriptContext) scriptContext; final AuthorizationChallengeSession sessionObject = context.getAuthzRequest().getAuthorizationChallengeSessionObject(); if (sessionObject != null) { final Map<String, String> sessionAttributes = sessionObject.getAttributes().getAttributes(); final String scopeFromSession = sessionAttributes.get(\"scope\"); if (StringUtils.isNotBlank(scopeFromSession) && StringUtils.isBlank(context.getAuthzRequest().getScope())) { context.getAuthzRequest().setScope(scopeFromSession); } } } } Sample Scripts # AuthorizationChallenge Multi-step AuthorizationChallenge", "title": "Authorization Challenge"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#authorization-challenge-custom-script", "text": "", "title": "Authorization Challenge Custom Script"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#overview", "text": "The Jans-Auth server implements OAuth 2.0 for First-Party Applications . This script is used to control/customize Authorization Challenge Endpoint.", "title": "Overview"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#behavior", "text": "In request to Authorization Challenge Endpoint to is expected to have acr_values request parameter which specifies name of the custom script. If parameter is absent or AS can't find script with this name then it falls back to script with name default_challenge . This script is provided during installation and performs basic username / password authentication. POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea&scope=openid+profile+address+email+phone+user_name&state=b4a41b29-51c8-4354-9c8c-fda38b4dbd43&nonce=3a56f8d0-f78e-4b15-857c-3e792801be68&acr_values=&request_session_id=false&password=secret&username=admin There is authorizationChallengeDefaultAcr AS configuration property which allows to change fallback script name from default_challenge to some other value (value must be valid script name present on AS).", "title": "Behavior"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#interface", "text": "The Authorization Challenage script implements the AuthorizationChallenageType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#new-methods", "text": "Method header Method description def authorize(self, context) Called when the request is received. def getAuthenticationMethodClaims(self, context) Called to get authn method claims. It is injected into id_token . Returns key-value map. def prepareAuthzRequest(self, context) Prepared authorization request before authorize method. It's good place to restore data from session if needed. authorize method returns true/false which indicates to server whether to issue authorization_code in response or not. If parameters is not present then error has to be created and false returned. If all is good script has to return true and it's strongly recommended to set user context.getExecutionContext().setUser(user); so AS can keep tracking what exactly user is authenticated. prepareAuthzRequest should typically be used for authorization request manipulation before authorize method is invoked. Also if there is multi-step flow where some data are stored in session object, it is good place to restore data from session into request (please find example in sample below).", "title": "New methods"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#objects", "text": "Object name Object description customScript The custom script object. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#common-use-case-authorize-user-by-usernamepassword", "text": "", "title": "Common Use Case: Authorize user by username/password"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#script-type-java", "text": "import io.jans.as.common.model.common.User ; import io.jans.as.common.model.session.DeviceSession ; import io.jans.as.server.authorize.ws.rs.DeviceSessionService ; import io.jans.as.server.service.UserService ; import io.jans.as.server.service.external.context.ExternalScriptContext ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.authzchallenge.AuthorizationChallengeType ; import io.jans.orm.PersistenceEntryManager ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.service.custom.script.CustomScriptManager ; import org.apache.commons.lang3.StringUtils ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.util.Map ; import java.util.HashMap ; import java.util.UUID ; /** * @author Yuriy Z */ public class AuthorizationChallenge implements AuthorizationChallengeType { public static final String USERNAME_PARAMETER = \"username\" ; public static final String PASSWORD_PARAMETER = \"password\" ; private static final Logger log = LoggerFactory . getLogger ( AuthorizationChallenge . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); /** * Return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. * <p> * Implementation of this method should consist of 3 main parts: * 1. validate all parameters are present and if not -> set error and return false * 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true * 3. if not ok -> set error which explains what is wrong and return false * * @param scriptContext ExternalScriptContext, see https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/context/ExternalScriptContext.java * @return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. */ @Override public boolean authorize ( Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. validate all required parameters are present final String username = getParameterOrCreateError ( context , USERNAME_PARAMETER ); if ( StringUtils . isBlank ( username )) { return false ; } final String password = getParameterOrCreateError ( context , PASSWORD_PARAMETER ); if ( StringUtils . isBlank ( password )) { return false ; } scriptLogger . trace ( \"All required parameters are present\" ); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil . bean ( UserService . class ); PersistenceEntryManager entryManager = CdiUtil . bean ( PersistenceEntryManager . class ); final User user = userService . getUser ( username ); if ( user == null ) { scriptLogger . trace ( \"User is not found by username {}\" , username ); createError ( context , \"username_invalid\" ); return false ; } final boolean ok = entryManager . authenticate ( user . getDn (), User . class , password ); if ( ok ) { context . getExecutionContext (). setUser ( user ); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger . trace ( \"User {} is authenticated successfully.\" , username ); return true ; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger . trace ( \"Failed to authenticate user {}. Please check username and password.\" , username ); createError ( context , \"username_or_password_invalid\" ); return false ; } private String getParameterOrCreateError ( ExternalScriptContext context , String parameterName ) { String value = context . getHttpRequest (). getParameter ( parameterName ); if ( StringUtils . isBlank ( value )) { scriptLogger . trace ( \"No '{}' parameter in request\" , parameterName ); value = getParameterFromDeviceSession ( context , parameterName ); } if ( StringUtils . isBlank ( value )) { scriptLogger . trace ( \"{} is not provided\" , parameterName ); createError ( context , String . format ( \"%s_required\" , parameterName )); return null ; } return value ; } private void createError ( ExternalScriptContext context , String errorCode ) { String deviceSessionPart = prepareDeviceSessionSubJson ( context ); final String entity = String . format ( \"{\\\"error\\\": \\\"%s\\\"%s}\" , errorCode , deviceSessionPart ); context . createWebApplicationException ( 401 , entity ); } private String prepareDeviceSessionSubJson ( ExternalScriptContext context ) { DeviceSession authorizationChallengeSessionObject = context . getAuthzRequest (). getDeviceSessionObject (); if ( authorizationChallengeSessionObject != null ) { prepareDeviceSession ( context , authorizationChallengeSessionObject ); return String . format ( \",\\\"auth_session\\\":\\\"%s\\\"\" , authorizationChallengeSessionObject . getId ()); } else if ( context . getAuthzRequest (). isUseDeviceSession ()) { authorizationChallengeSessionObject = prepareDeviceSession ( context , null ); return String . format ( \",\\\"auth_session\\\":\\\"%s\\\"\" , authorizationChallengeSessionObject . getId ()); } return \"\" ; } private DeviceSession prepareDeviceSession ( ExternalScriptContext context , DeviceSession authorizationChallengeSessionObject ) { DeviceSessionService deviceSessionService = CdiUtil . bean ( DeviceSessionService . class ); boolean newSave = authorizationChallengeSessionObject == null ; if ( newSave ) { authorizationChallengeSessionObject = deviceSessionService . newDeviceSession (); } String username = context . getHttpRequest (). getParameter ( USERNAME_PARAMETER ); if ( StringUtils . isNotBlank ( username )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( USERNAME_PARAMETER , username ); } String password = context . getHttpRequest (). getParameter ( PASSWORD_PARAMETER ); if ( StringUtils . isNotBlank ( password )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( PASSWORD_PARAMETER , password ); } String clientId = context . getHttpRequest (). getParameter ( \"client_id\" ); if ( StringUtils . isNotBlank ( clientId )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"client_id\" , clientId ); } String acrValues = context . getHttpRequest (). getParameter ( \"acr_values\" ); if ( StringUtils . isNotBlank ( acrValues )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"acr_values\" , acrValues ); } if ( newSave ) { deviceSessionService . persist ( authorizationChallengeSessionObject ); } else { deviceSessionService . merge ( authorizationChallengeSessionObject ); } return authorizationChallengeSessionObject ; } private String getParameterFromDeviceSession ( ExternalScriptContext context , String parameterName ) { final DeviceSession authorizationChallengeSessionObject = context . getAuthzRequest (). getDeviceSessionObject (); if ( authorizationChallengeSessionObject != null ) { return authorizationChallengeSessionObject . getAttributes (). getAttributes (). get ( parameterName ); } return null ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Destroyed Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public Map < String , String > getAuthenticationMethodClaims ( Object context ) { return new HashMap <> (); } }", "title": "Script Type: Java"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#multi-step-authorization-by-username-and-otp", "text": "", "title": "Multi-step authorization by username and OTP"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#script-type-java_1", "text": "import io.jans.as.common.model.common.User; import io.jans.as.common.model.session.DeviceSession; import io.jans.as.server.authorize.ws.rs.DeviceSessionService; import io.jans.as.server.service.UserService; import io.jans.as.server.service.external.context.ExternalScriptContext; import io.jans.model.SimpleCustomProperty; import io.jans.model.custom.script.model.CustomScript; import io.jans.model.custom.script.type.authzchallenge.AuthorizationChallengeType; import io.jans.orm.PersistenceEntryManager; import io.jans.service.cdi.util.CdiUtil; import io.jans.service.custom.script.CustomScriptManager; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; import java.util.HashMap; import java.util.UUID; /** * Script is to demo 2 steps flow: * 1) First step -> send username * 2) Second step -> send OTP * * AS tracks data by 'auth_session'. See \"prepareDeviceSession()\" method implemention for details. * * @author Yuriy Z */ public class AuthorizationChallenge implements AuthorizationChallengeType { public static final String USERNAME_PARAMETER = \"username\"; public static final String OTP_PARAMETER = \"otp\"; private static final Logger log = LoggerFactory.getLogger(AuthorizationChallenge.class); private static final Logger scriptLogger = LoggerFactory.getLogger(CustomScriptManager.class); /** * Return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. * <p> * Implementation of this method should consist of 3 main parts: * 1. validate all parameters are present and if not -> set error and return false * 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true * 3. if not ok -> set error which explains what is wrong and return false * * @param scriptContext ExternalScriptContext, see https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/context/ExternalScriptContext.java * @return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. */ @Override public boolean authorize(Object scriptContext) { ExternalScriptContext context = (ExternalScriptContext) scriptContext; // 1. As first step we get username final String username = getParameterOrCreateError(context, USERNAME_PARAMETER); if (StringUtils.isBlank(username)) { return false; } // 2. During first execution OTP is not present, so error will be returned with auth_session (which has saved username) // Note: prepareDeviceSession method implemention final String otp = getParameterOrCreateError(context, OTP_PARAMETER); if (StringUtils.isBlank(otp)) { return false; } scriptLogger.trace(\"All required parameters are present\"); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil.bean(UserService.class); PersistenceEntryManager entryManager = CdiUtil.bean(PersistenceEntryManager.class); final User user = userService.getUser(username); if (user == null) { scriptLogger.trace(\"User is not found by username {}\", username); createError(context, \"username_invalid\"); return false; } // for simplicity OTP is here just username password but in real world scenario real OTP validation is needed. final boolean ok = entryManager.authenticate(user.getDn(), User.class, otp); if (ok) { context.getExecutionContext().setUser(user); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger.trace(\"User {} is authenticated successfully.\", username); return true; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger.trace(\"Failed to authenticate user {}. Please check username and OTP.\", username); createError(context, \"username_or_otp_invalid\"); return false; } private String getParameterOrCreateError(ExternalScriptContext context, String parameterName) { String value = context.getHttpRequest().getParameter(parameterName); if (StringUtils.isBlank(value)) { scriptLogger.trace(\"No '{}' parameter in request\", parameterName); value = getParameterFromDeviceSession(context, parameterName); } if (StringUtils.isBlank(value)) { scriptLogger.trace(\"{} is not provided\", parameterName); createError(context, String.format(\"%s_required\", parameterName)); return null; } return value; } private void createError(ExternalScriptContext context, String errorCode) { String deviceSessionPart = prepareDeviceSessionSubJson(context); final String entity = String.format(\"{\\\"error\\\": \\\"%s\\\"%s}\", errorCode, deviceSessionPart); context.createWebApplicationException(401, entity); } private String prepareDeviceSessionSubJson(ExternalScriptContext context) { DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { prepareDeviceSession(context, authorizationChallengeSessionObject); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } else if (context.getAuthzRequest().isUseDeviceSession()) { authorizationChallengeSessionObject = prepareDeviceSession(context, null); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } return \"\"; } private DeviceSession prepareDeviceSession(ExternalScriptContext context, DeviceSession authorizationChallengeSessionObject) { DeviceSessionService deviceSessionService = CdiUtil.bean(DeviceSessionService.class); boolean newSave = authorizationChallengeSessionObject == null; if (newSave) { authorizationChallengeSessionObject = deviceSessionService.newDeviceSession(); } String username = context.getHttpRequest().getParameter(USERNAME_PARAMETER); if (StringUtils.isNotBlank(username)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(USERNAME_PARAMETER, username); } String otp = context.getHttpRequest().getParameter(OTP_PARAMETER); if (StringUtils.isNotBlank(otp)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(OTP_PARAMETER, otp); } String clientId = context.getHttpRequest().getParameter(\"client_id\"); if (StringUtils.isNotBlank(clientId)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"client_id\", clientId); } String acrValues = context.getHttpRequest().getParameter(\"acr_values\"); if (StringUtils.isNotBlank(acrValues)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"acr_values\", acrValues); } if (newSave) { deviceSessionService.persist(authorizationChallengeSessionObject); } else { deviceSessionService.merge(authorizationChallengeSessionObject); } return authorizationChallengeSessionObject; } private String getParameterFromDeviceSession(ExternalScriptContext context, String parameterName) { final DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { return authorizationChallengeSessionObject.getAttributes().getAttributes().get(parameterName); } return null; } @Override public boolean init(Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Initialized Default AuthorizationChallenge Java custom script.\"); return true; } @Override public boolean init(CustomScript customScript, Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Initialized Default AuthorizationChallenge Java custom script.\"); return true; } @Override public boolean destroy(Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Destroyed Default AuthorizationChallenge Java custom script.\"); return true; } @Override public int getApiVersion() { return 11; } @Override public Map<String, String> getAuthenticationMethodClaims(Object context) { return new HashMap<>(); } @Override public void prepareAuthzRequest(Object scriptContext) { ExternalScriptContext context = (ExternalScriptContext) scriptContext; final AuthorizationChallengeSession sessionObject = context.getAuthzRequest().getAuthorizationChallengeSessionObject(); if (sessionObject != null) { final Map<String, String> sessionAttributes = sessionObject.getAttributes().getAttributes(); final String scopeFromSession = sessionAttributes.get(\"scope\"); if (StringUtils.isNotBlank(scopeFromSession) && StringUtils.isBlank(context.getAuthzRequest().getScope())) { context.getAuthzRequest().setScope(scopeFromSession); } } } }", "title": "Script Type: Java"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#sample-scripts", "text": "AuthorizationChallenge Multi-step AuthorizationChallenge", "title": "Sample Scripts"}, {"location": "script-catalog/ciba/ciba/", "tags": ["administration", "developer", "script-catalog"], "text": "CIBA End User Notification Script (EndUserNotification) # Overview # The Jans-Auth server implements OAuth 2.0 Rich Authorization Requests . This script is used to control/customize cache refresh. Interface # The CIBA end user script implements the EndUserNotificationType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description notifyEndUser(self, context) Returns boolean true or false depending on the process, if the notification is sent successfully or not Script Type: Python # from io.jans.as.client.fcm import FirebaseCloudMessagingResponse from io.jans.as.client.fcm import FirebaseCloudMessagingClient from io.jans.as.client.fcm import FirebaseCloudMessagingRequest from io.jans.as.util import RedirectUri from io.jans.model.custom.script.type.ciba import EndUserNotificationType from java.lang import String from java.util import UUID class EndUserNotification(EndUserNotificationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, configurationAttributes): print \"Firebase EndUserNotification script. Initializing ...\" print \"Firebase EndUserNotification script. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Firebase EndUserNotification script. Destroying ...\" print \"Firebase EndUserNotification script. Destroyed successfully\" return True def getApiVersion(self): return 1 # Returns boolean true or false depending on the process, if the notification # is sent successfully or not. def notifyEndUser(self, context): print 'Sending push notification using Firebase Cloud Messaging' appConfiguration = context.getAppConfiguration() encryptionService = context.getEncryptionService() clientId = appConfiguration.getBackchannelClientId() redirectUri = appConfiguration.getBackchannelRedirectUri() url = appConfiguration.getCibaEndUserNotificationConfig().getNotificationUrl() key = encryptionService.decrypt(appConfiguration.getCibaEndUserNotificationConfig().getNotificationKey(), True) to = context.getDeviceRegistrationToken() title = \"oxAuth Authentication Request\" body = \"Client Initiated Backchannel Authentication (CIBA)\" authorizationRequestUri = RedirectUri(appConfiguration.getAuthorizationEndpoint()) authorizationRequestUri.addResponseParameter(\"client_id\", clientId) authorizationRequestUri.addResponseParameter(\"response_type\", \"id_token\") authorizationRequestUri.addResponseParameter(\"scope\", context.getScope()) authorizationRequestUri.addResponseParameter(\"acr_values\", context.getAcrValues()) authorizationRequestUri.addResponseParameter(\"redirect_uri\", redirectUri) authorizationRequestUri.addResponseParameter(\"state\", UUID.randomUUID().toString()) authorizationRequestUri.addResponseParameter(\"nonce\", UUID.randomUUID().toString()) authorizationRequestUri.addResponseParameter(\"prompt\", \"consent\") authorizationRequestUri.addResponseParameter(\"auth_req_id\", context.getAuthReqId()) clickAction = authorizationRequestUri.toString() firebaseCloudMessagingRequest = FirebaseCloudMessagingRequest(key, to, title, body, clickAction) firebaseCloudMessagingClient = FirebaseCloudMessagingClient(url) firebaseCloudMessagingClient.setRequest(firebaseCloudMessagingRequest) firebaseCloudMessagingResponse = firebaseCloudMessagingClient.exec() responseStatus = firebaseCloudMessagingResponse.getStatus() print \"CIBA: firebase cloud messaging result status \" + str(responseStatus) return (responseStatus >= 200 and responseStatus < 300 ) Sample Scripts # EndUserNotification This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "CIBA End User Notification"}, {"location": "script-catalog/ciba/ciba/#ciba-end-user-notification-script-endusernotification", "text": "", "title": "CIBA End User Notification Script (EndUserNotification)"}, {"location": "script-catalog/ciba/ciba/#overview", "text": "The Jans-Auth server implements OAuth 2.0 Rich Authorization Requests . This script is used to control/customize cache refresh.", "title": "Overview"}, {"location": "script-catalog/ciba/ciba/#interface", "text": "The CIBA end user script implements the EndUserNotificationType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/ciba/ciba/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/ciba/ciba/#new-methods", "text": "Method header Method description notifyEndUser(self, context) Returns boolean true or false depending on the process, if the notification is sent successfully or not", "title": "New methods"}, {"location": "script-catalog/ciba/ciba/#script-type-python", "text": "from io.jans.as.client.fcm import FirebaseCloudMessagingResponse from io.jans.as.client.fcm import FirebaseCloudMessagingClient from io.jans.as.client.fcm import FirebaseCloudMessagingRequest from io.jans.as.util import RedirectUri from io.jans.model.custom.script.type.ciba import EndUserNotificationType from java.lang import String from java.util import UUID class EndUserNotification(EndUserNotificationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, configurationAttributes): print \"Firebase EndUserNotification script. Initializing ...\" print \"Firebase EndUserNotification script. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Firebase EndUserNotification script. Destroying ...\" print \"Firebase EndUserNotification script. Destroyed successfully\" return True def getApiVersion(self): return 1 # Returns boolean true or false depending on the process, if the notification # is sent successfully or not. def notifyEndUser(self, context): print 'Sending push notification using Firebase Cloud Messaging' appConfiguration = context.getAppConfiguration() encryptionService = context.getEncryptionService() clientId = appConfiguration.getBackchannelClientId() redirectUri = appConfiguration.getBackchannelRedirectUri() url = appConfiguration.getCibaEndUserNotificationConfig().getNotificationUrl() key = encryptionService.decrypt(appConfiguration.getCibaEndUserNotificationConfig().getNotificationKey(), True) to = context.getDeviceRegistrationToken() title = \"oxAuth Authentication Request\" body = \"Client Initiated Backchannel Authentication (CIBA)\" authorizationRequestUri = RedirectUri(appConfiguration.getAuthorizationEndpoint()) authorizationRequestUri.addResponseParameter(\"client_id\", clientId) authorizationRequestUri.addResponseParameter(\"response_type\", \"id_token\") authorizationRequestUri.addResponseParameter(\"scope\", context.getScope()) authorizationRequestUri.addResponseParameter(\"acr_values\", context.getAcrValues()) authorizationRequestUri.addResponseParameter(\"redirect_uri\", redirectUri) authorizationRequestUri.addResponseParameter(\"state\", UUID.randomUUID().toString()) authorizationRequestUri.addResponseParameter(\"nonce\", UUID.randomUUID().toString()) authorizationRequestUri.addResponseParameter(\"prompt\", \"consent\") authorizationRequestUri.addResponseParameter(\"auth_req_id\", context.getAuthReqId()) clickAction = authorizationRequestUri.toString() firebaseCloudMessagingRequest = FirebaseCloudMessagingRequest(key, to, title, body, clickAction) firebaseCloudMessagingClient = FirebaseCloudMessagingClient(url) firebaseCloudMessagingClient.setRequest(firebaseCloudMessagingRequest) firebaseCloudMessagingResponse = firebaseCloudMessagingClient.exec() responseStatus = firebaseCloudMessagingResponse.getStatus() print \"CIBA: firebase cloud messaging result status \" + str(responseStatus) return (responseStatus >= 200 and responseStatus < 300 )", "title": "Script Type: Python"}, {"location": "script-catalog/ciba/ciba/#sample-scripts", "text": "EndUserNotification", "title": "Sample Scripts"}, {"location": "script-catalog/ciba/ciba/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/ciba/ciba/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/ciba/ciba/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/client_authn/client-authn/", "tags": ["administration", "developer", "script-catalog"], "text": "Client Authentication Custom Script # Overview # AS support different types of client authentications such as : client_secret_basic client_secret_post client_secret_jwt private_key_jwt Sometimes it's convenient to customize default AS client authentication process. For this reason Client Authentication custom script was introduced. If script successfully authenticated client, it should return it in authenticateClient . If client is not returned then AS performs built-in authentication. Interface # The Client Authentication script implements the ClientAuthnType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description def authenticateClient(self, context) Called when the request is received. authenticateClient method returns authenticated Client object or null if authentication failed. Objects # Object name Object description customScript The custom script object. Reference context Reference Sample script which demonstrates basic client authentication # Script Type: Java # import io.jans.as.common.model.registration.Client ; import io.jans.as.model.config.Constants ; import io.jans.as.server.service.ClientService ; import io.jans.as.server.service.external.context.ExternalClientAuthnContext ; import io.jans.as.server.service.token.TokenService ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.client.ClientAuthnType ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.service.custom.script.CustomScriptManager ; import jakarta.servlet.http.HttpServletRequest ; import jakarta.servlet.http.HttpServletResponse ; import org.apache.commons.codec.binary.Base64 ; import org.apache.commons.lang.StringUtils ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.net.URLDecoder ; import java.nio.charset.StandardCharsets ; import java.util.Map ; /** * @author Yuriy Z */ public class ClientAuthn implements ClientAuthnType { private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public Object authenticateClient ( Object clientAuthnContext ) { final ExternalClientAuthnContext context = ( ExternalClientAuthnContext ) clientAuthnContext ; final HttpServletRequest request = context . getHttpRequest (); final HttpServletResponse response = context . getHttpResponse (); String authorization = request . getHeader ( Constants . AUTHORIZATION ); if ( ! StringUtils . startsWith ( authorization , \"Basic\" )) { context . sendUnauthorizedError (); return null ; } TokenService tokenService = CdiUtil . bean ( TokenService . class ); ClientService clientService = CdiUtil . bean ( ClientService . class ); String base64Token = tokenService . getBasicToken ( authorization ); String token = new String ( Base64 . decodeBase64 ( base64Token ), StandardCharsets . UTF_8 ); int delim = token . indexOf ( \":\" ); if ( delim != - 1 ) { String clientId = URLDecoder . decode ( token . substring ( 0 , delim ), StandardCharsets . UTF_8 ); String clientSecret = URLDecoder . decode ( token . substring ( delim + 1 ), StandardCharsets . UTF_8 ); final boolean authenticated = clientService . authenticate ( clientId , clientSecret ); if ( authenticated ) { final Client client = clientService . getClient ( clientId ); scriptLogger . debug ( \"Successfully performed basic client authentication, clientId: {}\" , clientId ); return client ; } } context . sendUnauthorizedError (); return null ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized ClientAuthn Java custom script.\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized ClientAuthn Java custom script.\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Destroyed ClientAuthn Java custom script.\" ); return false ; } @Override public int getApiVersion () { return 11 ; } } Sample Scripts # ClientAuthentication", "title": "Client Authentication"}, {"location": "script-catalog/client_authn/client-authn/#client-authentication-custom-script", "text": "", "title": "Client Authentication Custom Script"}, {"location": "script-catalog/client_authn/client-authn/#overview", "text": "AS support different types of client authentications such as : client_secret_basic client_secret_post client_secret_jwt private_key_jwt Sometimes it's convenient to customize default AS client authentication process. For this reason Client Authentication custom script was introduced. If script successfully authenticated client, it should return it in authenticateClient . If client is not returned then AS performs built-in authentication.", "title": "Overview"}, {"location": "script-catalog/client_authn/client-authn/#interface", "text": "The Client Authentication script implements the ClientAuthnType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/client_authn/client-authn/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/client_authn/client-authn/#new-methods", "text": "Method header Method description def authenticateClient(self, context) Called when the request is received. authenticateClient method returns authenticated Client object or null if authentication failed.", "title": "New methods"}, {"location": "script-catalog/client_authn/client-authn/#objects", "text": "Object name Object description customScript The custom script object. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/client_authn/client-authn/#sample-script-which-demonstrates-basic-client-authentication", "text": "", "title": "Sample script which demonstrates basic client authentication"}, {"location": "script-catalog/client_authn/client-authn/#script-type-java", "text": "import io.jans.as.common.model.registration.Client ; import io.jans.as.model.config.Constants ; import io.jans.as.server.service.ClientService ; import io.jans.as.server.service.external.context.ExternalClientAuthnContext ; import io.jans.as.server.service.token.TokenService ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.client.ClientAuthnType ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.service.custom.script.CustomScriptManager ; import jakarta.servlet.http.HttpServletRequest ; import jakarta.servlet.http.HttpServletResponse ; import org.apache.commons.codec.binary.Base64 ; import org.apache.commons.lang.StringUtils ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.net.URLDecoder ; import java.nio.charset.StandardCharsets ; import java.util.Map ; /** * @author Yuriy Z */ public class ClientAuthn implements ClientAuthnType { private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public Object authenticateClient ( Object clientAuthnContext ) { final ExternalClientAuthnContext context = ( ExternalClientAuthnContext ) clientAuthnContext ; final HttpServletRequest request = context . getHttpRequest (); final HttpServletResponse response = context . getHttpResponse (); String authorization = request . getHeader ( Constants . AUTHORIZATION ); if ( ! StringUtils . startsWith ( authorization , \"Basic\" )) { context . sendUnauthorizedError (); return null ; } TokenService tokenService = CdiUtil . bean ( TokenService . class ); ClientService clientService = CdiUtil . bean ( ClientService . class ); String base64Token = tokenService . getBasicToken ( authorization ); String token = new String ( Base64 . decodeBase64 ( base64Token ), StandardCharsets . UTF_8 ); int delim = token . indexOf ( \":\" ); if ( delim != - 1 ) { String clientId = URLDecoder . decode ( token . substring ( 0 , delim ), StandardCharsets . UTF_8 ); String clientSecret = URLDecoder . decode ( token . substring ( delim + 1 ), StandardCharsets . UTF_8 ); final boolean authenticated = clientService . authenticate ( clientId , clientSecret ); if ( authenticated ) { final Client client = clientService . getClient ( clientId ); scriptLogger . debug ( \"Successfully performed basic client authentication, clientId: {}\" , clientId ); return client ; } } context . sendUnauthorizedError (); return null ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized ClientAuthn Java custom script.\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized ClientAuthn Java custom script.\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Destroyed ClientAuthn Java custom script.\" ); return false ; } @Override public int getApiVersion () { return 11 ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/client_authn/client-authn/#sample-scripts", "text": "ClientAuthentication", "title": "Sample Scripts"}, {"location": "script-catalog/client_registration/client-registration/", "tags": ["administration", "developer", "script-catalog"], "text": "Client Registration scripts # Overview # The Jans-Auth server implements the OpenID Connect Dynamic Client Registration specification. This allows developers to register a client with the Authorization Server (AS) without any intervention from the administrator. By default, all clients are given the same default scopes and attributes. Through the use of an interception script, this behavior can be modified. These scripts can be used to analyze the registration request and apply customizations to the registered client. For example, a client can be given specific scopes by analyzing the Software Statement that is sent with the registration request. Behavior # By default, Jans server has no dynamic client registration scripts enabled, and all clients are given the same attributes. When a script is added and enabled, the script will run and return a boolean after applying logic to the registration request. If true , the client is registered and client credentials are returned. Generally, the script is global for all registration requests, and only one script is enabled at a time. Registration flow # sequenceDiagram title Client Registration script autonumber 1 RP->>Jans AS: /register request Jans AS->>Jans AS: Is there a client registration script enabled? Jans AS->>Jans AS: run script note right of Jans AS: Apply custom logic e.g <br/> Add scopes <br/> Set attributes <br/> validate SSA Jans AS->>RP: return client credentials Interface # The client registration script implements the ClientRegistrationType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description def createClient(self, context) Called when the dynamic client registration request is received. def updateClient(self, context) Called when the PUT method is called on registration endpoint to update client details. def getSoftwareStatementHmacSecret(self, context) Returns secret key which will be used to validate Software Statement if HMAC algorithm is used (e.g. HS256, HS512) def getSoftwareStatementJwks(self, context) Returns JWKS which will be used to validate Software Statement if keys are used (e.g. RS256) def modifyPutResponse(self, responseAsJsonObject, executionContext) Modifies the response from the PUT request to registration endpoint def modifyReadResponse(self, responseAsJsonObject, executionContext) Modifies the response from the GET request to registration endpoint def modifyPostResponse(self, responseAsJsonObject, executionContext) Modifies the response from the POST request to registration endpoint Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference responseAsJsonObject Java JSONObject. Reference executionContext Reference Common Use Case: Adding scopes defined in the script configuration parameters # Script Type: Python # from io.jans.model.custom.script.type.client import ClientRegistrationType from io.jans.service.cdi.util import CdiUtil from io.jans.orm.util import StringHelper , ArrayHelper from io.jans.as.server.service import ScopeService import json class ClientRegistration ( ClientRegistrationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Client registration. Initialization\" if ( not configurationAttributes . containsKey ( \"scope_list\" )): print \"Client registration. Initialization failed. Scope List not defined.\" return False else : self . scope_list = configurationAttributes . get ( \"scope_list\" ) . getValue2 () print \"Client registration. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Client registration. Destroy\" print \"Client registration. Destroyed successfully\" return True def createClient ( self , context ): scopeService = CdiUtil . bean ( ScopeService ) currentScopes = client . getScopes () for newScope in self . scope_list : foundScope = scopeService . getScopeById ( newScope ) if foundScope is None : print \"Client Registration. New scope(s) not found.\" return False newScopes = ArrayHelper . addItemToStringArray ( currentScopes , foundScope . getDn ()) client . setScopes ( newScopes ) return True def updateClient ( self , context ): print \"SSA Client registration. UpdateClient method\" pass def getApiVersion ( self ): return 11 # Returns secret key which will be used to validate Software Statement if HMAC algorithm is used (e.g. HS256, HS512). Invoked if oxauth conf property softwareStatementValidationType=SCRIPT which is default/fallback value. def getSoftwareStatementHmacSecret ( self , context ): pass # Returns JWKS which will be used to validate Software Statement if keys are used (e.g. RS256). Invoked if oxauth conf property softwareStatementValidationType=SCRIPT which is default/fallback value. def getSoftwareStatementJwks ( self , context ): pass def modifyPutResponse ( self , responseAsJsonObject , executionContext ): return False def modifyReadResponse ( self , responseAsJsonObject , executionContext ): return False def modifyPostResponse ( self , responseAsJsonObject , executionContext ): return False Script Type: Java # import io.jans.as.common.model.registration.Client ; import io.jans.as.persistence.model.Scope ; import io.jans.as.server.service.ScopeService ; import io.jans.as.server.service.external.context.DynamicClientRegistrationContext ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.client.ClientRegistrationType ; import io.jans.orm.util.ArrayHelper ; import io.jans.service.cdi.util.CdiUtil ; import org.json.JSONArray ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.util.Map ; public class ClientRegistration implements ClientRegistrationType { private static final Logger log = LoggerFactory . getLogger ( ClientRegistration . class ); JSONArray json_array = null ; @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { if ( ! configurationAttributes . containsKey ( \"scope_list\" )) { log . info ( \"Client registration. Initialization failed. Scope List not found.\" ); return false ; } String scope_list = configurationAttributes . get ( \"scope_list\" ). getValue2 (); json_array = new JSONArray ( scope_list ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Client registration. Initialization.\" ); log . info ( configurationAttributes . toString ()); if ( ! configurationAttributes . containsKey ( \"scope_list\" )) { log . info ( \"Client registration. Initialization failed. Scope List not found.\" ); return false ; } String scope_list = configurationAttributes . get ( \"scope_list\" ). getValue2 (); json_array = new JSONArray ( scope_list ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Client registration. Destroy.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean createClient ( Object context ) { log . info ( \"Client registration. CreateClient method\" ); DynamicClientRegistrationContext regContext = ( DynamicClientRegistrationContext ) context ; Client client = regContext . getClient (); ScopeService scopeService = CdiUtil . bean ( ScopeService . class ); String [] currentScopes = client . getScopes (); String [] newScopes = currentScopes . clone (); for ( int i = 0 ; i < json_array . length (); i ++ ) { String scopeName = ( String ) json_array . get ( i ); Scope foundScope = scopeService . getScopeById ( scopeName ); if ( foundScope == null ) { log . info ( \"Client registration. Scope not found\" ); return false ; } newScopes = ArrayHelper . addItemToStringArray ( newScopes , foundScope . getDn ()); } client . setScopes ( newScopes ); log . info ( \"Client registration. Scopes added.\" ); return true ; } @Override public boolean updateClient ( Object context ) { return true ; } // This method needs to be overridden if client is providing an SSA with HMAC @Override public String getSoftwareStatementHmacSecret ( Object context ) { return \"\" ; } // This method needs to be overridden if client is providing an SSA and RS256 validation @Override public String getSoftwareStatementJwks ( Object context ) { return \"\" ; } @Override public String getDcrHmacSecret ( Object o ) { return \"\" ; } @Override public String getDcrJwks ( Object o ) { return \"\" ; } @Override public boolean isCertValidForClient ( Object o , Object o1 ) { return false ; } @Override public boolean modifyPutResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } @Override public boolean modifyReadResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } @Override public boolean modifyPostResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } } Sample Scripts # OpenBanking", "title": "Client Registration"}, {"location": "script-catalog/client_registration/client-registration/#client-registration-scripts", "text": "", "title": "Client Registration scripts"}, {"location": "script-catalog/client_registration/client-registration/#overview", "text": "The Jans-Auth server implements the OpenID Connect Dynamic Client Registration specification. This allows developers to register a client with the Authorization Server (AS) without any intervention from the administrator. By default, all clients are given the same default scopes and attributes. Through the use of an interception script, this behavior can be modified. These scripts can be used to analyze the registration request and apply customizations to the registered client. For example, a client can be given specific scopes by analyzing the Software Statement that is sent with the registration request.", "title": "Overview"}, {"location": "script-catalog/client_registration/client-registration/#behavior", "text": "By default, Jans server has no dynamic client registration scripts enabled, and all clients are given the same attributes. When a script is added and enabled, the script will run and return a boolean after applying logic to the registration request. If true , the client is registered and client credentials are returned. Generally, the script is global for all registration requests, and only one script is enabled at a time.", "title": "Behavior"}, {"location": "script-catalog/client_registration/client-registration/#registration-flow", "text": "sequenceDiagram title Client Registration script autonumber 1 RP->>Jans AS: /register request Jans AS->>Jans AS: Is there a client registration script enabled? Jans AS->>Jans AS: run script note right of Jans AS: Apply custom logic e.g <br/> Add scopes <br/> Set attributes <br/> validate SSA Jans AS->>RP: return client credentials", "title": "Registration flow"}, {"location": "script-catalog/client_registration/client-registration/#interface", "text": "The client registration script implements the ClientRegistrationType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/client_registration/client-registration/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/client_registration/client-registration/#new-methods", "text": "Method header Method description def createClient(self, context) Called when the dynamic client registration request is received. def updateClient(self, context) Called when the PUT method is called on registration endpoint to update client details. def getSoftwareStatementHmacSecret(self, context) Returns secret key which will be used to validate Software Statement if HMAC algorithm is used (e.g. HS256, HS512) def getSoftwareStatementJwks(self, context) Returns JWKS which will be used to validate Software Statement if keys are used (e.g. RS256) def modifyPutResponse(self, responseAsJsonObject, executionContext) Modifies the response from the PUT request to registration endpoint def modifyReadResponse(self, responseAsJsonObject, executionContext) Modifies the response from the GET request to registration endpoint def modifyPostResponse(self, responseAsJsonObject, executionContext) Modifies the response from the POST request to registration endpoint", "title": "New methods"}, {"location": "script-catalog/client_registration/client-registration/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference responseAsJsonObject Java JSONObject. Reference executionContext Reference", "title": "Objects"}, {"location": "script-catalog/client_registration/client-registration/#common-use-case-adding-scopes-defined-in-the-script-configuration-parameters", "text": "", "title": "Common Use Case: Adding scopes defined in the script configuration parameters"}, {"location": "script-catalog/client_registration/client-registration/#script-type-python", "text": "from io.jans.model.custom.script.type.client import ClientRegistrationType from io.jans.service.cdi.util import CdiUtil from io.jans.orm.util import StringHelper , ArrayHelper from io.jans.as.server.service import ScopeService import json class ClientRegistration ( ClientRegistrationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Client registration. Initialization\" if ( not configurationAttributes . containsKey ( \"scope_list\" )): print \"Client registration. Initialization failed. Scope List not defined.\" return False else : self . scope_list = configurationAttributes . get ( \"scope_list\" ) . getValue2 () print \"Client registration. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Client registration. Destroy\" print \"Client registration. Destroyed successfully\" return True def createClient ( self , context ): scopeService = CdiUtil . bean ( ScopeService ) currentScopes = client . getScopes () for newScope in self . scope_list : foundScope = scopeService . getScopeById ( newScope ) if foundScope is None : print \"Client Registration. New scope(s) not found.\" return False newScopes = ArrayHelper . addItemToStringArray ( currentScopes , foundScope . getDn ()) client . setScopes ( newScopes ) return True def updateClient ( self , context ): print \"SSA Client registration. UpdateClient method\" pass def getApiVersion ( self ): return 11 # Returns secret key which will be used to validate Software Statement if HMAC algorithm is used (e.g. HS256, HS512). Invoked if oxauth conf property softwareStatementValidationType=SCRIPT which is default/fallback value. def getSoftwareStatementHmacSecret ( self , context ): pass # Returns JWKS which will be used to validate Software Statement if keys are used (e.g. RS256). Invoked if oxauth conf property softwareStatementValidationType=SCRIPT which is default/fallback value. def getSoftwareStatementJwks ( self , context ): pass def modifyPutResponse ( self , responseAsJsonObject , executionContext ): return False def modifyReadResponse ( self , responseAsJsonObject , executionContext ): return False def modifyPostResponse ( self , responseAsJsonObject , executionContext ): return False", "title": "Script Type: Python"}, {"location": "script-catalog/client_registration/client-registration/#script-type-java", "text": "import io.jans.as.common.model.registration.Client ; import io.jans.as.persistence.model.Scope ; import io.jans.as.server.service.ScopeService ; import io.jans.as.server.service.external.context.DynamicClientRegistrationContext ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.client.ClientRegistrationType ; import io.jans.orm.util.ArrayHelper ; import io.jans.service.cdi.util.CdiUtil ; import org.json.JSONArray ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.util.Map ; public class ClientRegistration implements ClientRegistrationType { private static final Logger log = LoggerFactory . getLogger ( ClientRegistration . class ); JSONArray json_array = null ; @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { if ( ! configurationAttributes . containsKey ( \"scope_list\" )) { log . info ( \"Client registration. Initialization failed. Scope List not found.\" ); return false ; } String scope_list = configurationAttributes . get ( \"scope_list\" ). getValue2 (); json_array = new JSONArray ( scope_list ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Client registration. Initialization.\" ); log . info ( configurationAttributes . toString ()); if ( ! configurationAttributes . containsKey ( \"scope_list\" )) { log . info ( \"Client registration. Initialization failed. Scope List not found.\" ); return false ; } String scope_list = configurationAttributes . get ( \"scope_list\" ). getValue2 (); json_array = new JSONArray ( scope_list ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Client registration. Destroy.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean createClient ( Object context ) { log . info ( \"Client registration. CreateClient method\" ); DynamicClientRegistrationContext regContext = ( DynamicClientRegistrationContext ) context ; Client client = regContext . getClient (); ScopeService scopeService = CdiUtil . bean ( ScopeService . class ); String [] currentScopes = client . getScopes (); String [] newScopes = currentScopes . clone (); for ( int i = 0 ; i < json_array . length (); i ++ ) { String scopeName = ( String ) json_array . get ( i ); Scope foundScope = scopeService . getScopeById ( scopeName ); if ( foundScope == null ) { log . info ( \"Client registration. Scope not found\" ); return false ; } newScopes = ArrayHelper . addItemToStringArray ( newScopes , foundScope . getDn ()); } client . setScopes ( newScopes ); log . info ( \"Client registration. Scopes added.\" ); return true ; } @Override public boolean updateClient ( Object context ) { return true ; } // This method needs to be overridden if client is providing an SSA with HMAC @Override public String getSoftwareStatementHmacSecret ( Object context ) { return \"\" ; } // This method needs to be overridden if client is providing an SSA and RS256 validation @Override public String getSoftwareStatementJwks ( Object context ) { return \"\" ; } @Override public String getDcrHmacSecret ( Object o ) { return \"\" ; } @Override public String getDcrJwks ( Object o ) { return \"\" ; } @Override public boolean isCertValidForClient ( Object o , Object o1 ) { return false ; } @Override public boolean modifyPutResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } @Override public boolean modifyReadResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } @Override public boolean modifyPostResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/client_registration/client-registration/#sample-scripts", "text": "OpenBanking", "title": "Sample Scripts"}, {"location": "script-catalog/config_api/config-api/", "tags": ["administration", "developer", "script-catalog"], "text": "Config Api interception Script # Interface # The Config Api Interception script implements the ConfigApiType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description authorize(self, responseAsJsonObject, context) responseAsJsonObject - is org.codehaus.jettison.json.JSONObject , you can use any method to manipulate json . context is reference of io.jans.as.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenFederation/oxauth project,) Sample script which demonstrates basic client authentication # Script Type: Python # from io.jans.as.model.jwt import Jwt from io.jans.as.model.crypto import AuthCryptoProvider from io.jans.model.custom.script.conf import CustomScriptConfiguration from io.jans.model.custom.script.type.configapi import ConfigApiType from io.jans.orm import PersistenceEntryManager from io.jans.service.cdi.util import CdiUtil from io.jans.util import StringHelper , ArrayHelper from io.jans.configapi.model.configuration import ApiAppConfiguration from org.json import JSONObject from java.lang import String from jakarta.servlet.http import HttpServletRequest from jakarta.servlet.http import HttpServletResponse class ConfigApiAuthorization ( ConfigApiType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"ConfigApiType script. Initializing ...\" print \"ConfigApiType script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"ConfigApiType script. Destroying ...\" print \"ConfigApiType script. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Returns boolean true or false depending on the process, if the client is authorized # or not. # This method is called after introspection response is ready. This method can modify introspection response. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenFederation/oxauth project, ) def authorize ( self , responseAsJsonObject , context ): print \" responseAsJsonObject: %s \" % responseAsJsonObject print \" context: %s \" % context print \"Config Authentication process\" request = context . httpRequest response = context . httpResponse print \" request = : %s \" % request print \" response = : %s \" % response appConfiguration = context . getApiAppConfiguration () customScriptConfiguration = context . getScript () issuer = context . getRequestParameters () . get ( \"ISSUER\" ) token = context . getRequestParameters () . get ( \"TOKEN\" ) method = context . getRequestParameters () . get ( \"METHOD\" ) path = context . getRequestParameters () . get ( \"PATH\" ) print \" requese2: %s \" % request print \" response2 new: %s \" % response print \"ConfigApiType.appConfiguration: %s \" % appConfiguration print \"ConfigApiType.customScriptConfiguration: %s \" % customScriptConfiguration print \"ConfigApiType.issuer: %s \" % issuer print \"ConfigApiType.token: %s \" % token print \"ConfigApiType.method: %s \" % method print \"ConfigApiType.path: %s \" % path #Example to validate method if ( \"GET\" == StringHelper . toUpperCase ( method ) ): print \"Validate method: %s \" % method if ( \"attributes\" == StringHelper . toLowerCase ( path ) ): print \"ConfigApiType.path: %s \" % path responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) print \" final responseAsJsonObject: %s \" % responseAsJsonObject return True Sample Scripts # ConfigApiInterception", "title": "Config API"}, {"location": "script-catalog/config_api/config-api/#config-api-interception-script", "text": "", "title": "Config Api interception Script"}, {"location": "script-catalog/config_api/config-api/#interface", "text": "The Config Api Interception script implements the ConfigApiType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/config_api/config-api/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/config_api/config-api/#new-methods", "text": "Method header Method description authorize(self, responseAsJsonObject, context) responseAsJsonObject - is org.codehaus.jettison.json.JSONObject , you can use any method to manipulate json . context is reference of io.jans.as.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenFederation/oxauth project,)", "title": "New methods"}, {"location": "script-catalog/config_api/config-api/#sample-script-which-demonstrates-basic-client-authentication", "text": "", "title": "Sample script which demonstrates basic client authentication"}, {"location": "script-catalog/config_api/config-api/#script-type-python", "text": "from io.jans.as.model.jwt import Jwt from io.jans.as.model.crypto import AuthCryptoProvider from io.jans.model.custom.script.conf import CustomScriptConfiguration from io.jans.model.custom.script.type.configapi import ConfigApiType from io.jans.orm import PersistenceEntryManager from io.jans.service.cdi.util import CdiUtil from io.jans.util import StringHelper , ArrayHelper from io.jans.configapi.model.configuration import ApiAppConfiguration from org.json import JSONObject from java.lang import String from jakarta.servlet.http import HttpServletRequest from jakarta.servlet.http import HttpServletResponse class ConfigApiAuthorization ( ConfigApiType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"ConfigApiType script. Initializing ...\" print \"ConfigApiType script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"ConfigApiType script. Destroying ...\" print \"ConfigApiType script. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Returns boolean true or false depending on the process, if the client is authorized # or not. # This method is called after introspection response is ready. This method can modify introspection response. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenFederation/oxauth project, ) def authorize ( self , responseAsJsonObject , context ): print \" responseAsJsonObject: %s \" % responseAsJsonObject print \" context: %s \" % context print \"Config Authentication process\" request = context . httpRequest response = context . httpResponse print \" request = : %s \" % request print \" response = : %s \" % response appConfiguration = context . getApiAppConfiguration () customScriptConfiguration = context . getScript () issuer = context . getRequestParameters () . get ( \"ISSUER\" ) token = context . getRequestParameters () . get ( \"TOKEN\" ) method = context . getRequestParameters () . get ( \"METHOD\" ) path = context . getRequestParameters () . get ( \"PATH\" ) print \" requese2: %s \" % request print \" response2 new: %s \" % response print \"ConfigApiType.appConfiguration: %s \" % appConfiguration print \"ConfigApiType.customScriptConfiguration: %s \" % customScriptConfiguration print \"ConfigApiType.issuer: %s \" % issuer print \"ConfigApiType.token: %s \" % token print \"ConfigApiType.method: %s \" % method print \"ConfigApiType.path: %s \" % path #Example to validate method if ( \"GET\" == StringHelper . toUpperCase ( method ) ): print \"Validate method: %s \" % method if ( \"attributes\" == StringHelper . toLowerCase ( path ) ): print \"ConfigApiType.path: %s \" % path responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) print \" final responseAsJsonObject: %s \" % responseAsJsonObject return True", "title": "Script Type: Python"}, {"location": "script-catalog/config_api/config-api/#sample-scripts", "text": "ConfigApiInterception", "title": "Sample Scripts"}, {"location": "script-catalog/consent_gathering/consent-gathering/", "tags": ["administration", "developer", "script-catalog", "ConsentGathering"], "text": "Overview # OAuth 2.0 allows providers to prompt users for consent before releasing their personal information to a client (application). The standard consent process is binary: approve or deny. Using the consent gathering interception script, the consent flow can be customized to meet unique business requirements, for instance to support payment authorization, where you need to present transactional information, or where you need to step-up authentication to add security. Interface # The consent gathering script implements the ConsentGathering interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def authorize(self, step, consentContext) Main consent-gather method. Must return True (if consent gathered successfully) or False (if failed). def getNextStep(self, step, context) def getStepsCount(self, context) Return total number of consent gathering steps def getPageForStep(self, step, context) Returns the consent page corresponding to the current step of consent gathering Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference Use case: Dummy Consent Gathering Form # This script has been adapted from the Gluu Server sample consent gathering script . Script Type: Python # from io.jans.model.custom.script.type.authz import ConsentGatheringType import random class ConsentGathering ( ConsentGatheringType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Consent-Gathering. Initializing ...\" print \"Consent-Gathering. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Consent-Gathering. Destroying ...\" print \"Consent-Gathering. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 # All user entered values can be access via Map<String, String> context.getPageAttributes() def authorize ( self , step , context ): print \"Consent-Gathering. Authorizing...\" if step == 1 : allowButton = context . getRequestParameters () . get ( \"authorizeForm:allowButton\" ) if ( allowButton != None ) and ( len ( allowButton ) > 0 ): print \"Consent-Gathering. Authorization success for step 1\" return True print \"Consent-Gathering. Authorization declined for step 1\" elif step == 2 : allowButton = context . getRequestParameters () . get ( \"authorizeForm:allowButton\" ) if ( allowButton != None ) and ( len ( allowButton ) > 0 ): print \"Consent-Gathering. Authorization success for step 2\" return True print \"Consent-Gathering. Authorization declined for step 2\" return False def getNextStep ( self , step , context ): return - 1 def prepareForStep ( self , step , context ): if not context . isAuthenticated (): print \"User is not authenticated. Aborting authorization flow ...\" return False if step == 2 : pageAttributes = context . getPageAttributes () # Generate random consent gathering request consentRequest = \"Requested transaction # %s approval for the amount of sum $ %s .00\" % ( random . randint ( 100000 , 1000000 ), random . randint ( 1 , 100 ) ) pageAttributes . put ( \"consent_request\" , consentRequest ) return True return True def getStepsCount ( self , context ): return 2 def getPageForStep ( self , step , context ): if step == 1 : return \"/authz/authorize.xhtml\" elif step == 2 : return \"/authz/transaction.xhtml\" return \"\" Script Type: Java # import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.authz.ConsentGatheringType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.ConsentGatheringContext ; import java.util.Map ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class ConsentGathering implements ConsentGatheringType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Initializing...\" ); log . info ( \"Consent gathering. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Initializing...\" ); log . info ( \"Consent gathering. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Destroying...\" ); log . info ( \"Consent gathering. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean authorize ( int step , Object consentContext ) { log . info ( \"Consent gathering. Authorizing...\" ); ConsentGatheringContext gatheringContext = ( ConsentGatheringContext ) consentContext ; String [] allowButton = gatheringContext . getRequestParameters (). get ( \"authorizeForm:allowButton\" ); if ( step == 1 ) { if ( allowButton != null && allowButton . length > 0 ) { log . info ( \"Consent gathering. Authorization success for step 1\" ); return true ; } log . info ( \"Consent gathering. Authorization declined for step 1\" ); } else if ( step == 2 ) { if ( allowButton != null && allowButton . length > 0 ) { log . info ( \"Consent gathering. Authorization success for step 2\" ); return true ; } log . info ( \"Consent gathering. Authorization declined for step 2\" ); } return false ; } @Override public int getNextStep ( int step , Object consentContext ) { return - 1 ; } @Override public boolean prepareForStep ( int step , Object consentContext ) { ConsentGatheringContext gatheringContext = ( ConsentGatheringContext ) consentContext ; if ( ! gatheringContext . isAuthenticated ()) { log . info ( \"User is not authenticated. Aborting authorization flow...\" ); return false ; } if ( step == 2 ) { Map < String , String > pageAttributes = gatheringContext . getPageAttributes (); String consentRequest = \"This is a random consent request\" ; pageAttributes . put ( \"consent_request\" , consentRequest ); return true ; } return false ; } @Override public int getStepsCount ( Object consentContext ) { return 2 ; } @Override public String getPageForStep ( int step , Object consentContext ) { if ( step == 1 ) { return \"/authz/authorize.xhtml\" ; } else if ( step == 2 ) { return \"return \\\"/authz/transaction.xhtml\\\"\" ; } return \"\" ; } }", "title": "Consent Gathering"}, {"location": "script-catalog/consent_gathering/consent-gathering/#overview", "text": "OAuth 2.0 allows providers to prompt users for consent before releasing their personal information to a client (application). The standard consent process is binary: approve or deny. Using the consent gathering interception script, the consent flow can be customized to meet unique business requirements, for instance to support payment authorization, where you need to present transactional information, or where you need to step-up authentication to add security.", "title": "Overview"}, {"location": "script-catalog/consent_gathering/consent-gathering/#interface", "text": "The consent gathering script implements the ConsentGathering interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/consent_gathering/consent-gathering/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/consent_gathering/consent-gathering/#new-methods", "text": "Method header Method description def authorize(self, step, consentContext) Main consent-gather method. Must return True (if consent gathered successfully) or False (if failed). def getNextStep(self, step, context) def getStepsCount(self, context) Return total number of consent gathering steps def getPageForStep(self, step, context) Returns the consent page corresponding to the current step of consent gathering", "title": "New Methods"}, {"location": "script-catalog/consent_gathering/consent-gathering/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/consent_gathering/consent-gathering/#use-case-dummy-consent-gathering-form", "text": "This script has been adapted from the Gluu Server sample consent gathering script .", "title": "Use case: Dummy Consent Gathering Form"}, {"location": "script-catalog/consent_gathering/consent-gathering/#script-type-python", "text": "from io.jans.model.custom.script.type.authz import ConsentGatheringType import random class ConsentGathering ( ConsentGatheringType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Consent-Gathering. Initializing ...\" print \"Consent-Gathering. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Consent-Gathering. Destroying ...\" print \"Consent-Gathering. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 # All user entered values can be access via Map<String, String> context.getPageAttributes() def authorize ( self , step , context ): print \"Consent-Gathering. Authorizing...\" if step == 1 : allowButton = context . getRequestParameters () . get ( \"authorizeForm:allowButton\" ) if ( allowButton != None ) and ( len ( allowButton ) > 0 ): print \"Consent-Gathering. Authorization success for step 1\" return True print \"Consent-Gathering. Authorization declined for step 1\" elif step == 2 : allowButton = context . getRequestParameters () . get ( \"authorizeForm:allowButton\" ) if ( allowButton != None ) and ( len ( allowButton ) > 0 ): print \"Consent-Gathering. Authorization success for step 2\" return True print \"Consent-Gathering. Authorization declined for step 2\" return False def getNextStep ( self , step , context ): return - 1 def prepareForStep ( self , step , context ): if not context . isAuthenticated (): print \"User is not authenticated. Aborting authorization flow ...\" return False if step == 2 : pageAttributes = context . getPageAttributes () # Generate random consent gathering request consentRequest = \"Requested transaction # %s approval for the amount of sum $ %s .00\" % ( random . randint ( 100000 , 1000000 ), random . randint ( 1 , 100 ) ) pageAttributes . put ( \"consent_request\" , consentRequest ) return True return True def getStepsCount ( self , context ): return 2 def getPageForStep ( self , step , context ): if step == 1 : return \"/authz/authorize.xhtml\" elif step == 2 : return \"/authz/transaction.xhtml\" return \"\"", "title": "Script Type: Python"}, {"location": "script-catalog/consent_gathering/consent-gathering/#script-type-java", "text": "import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.authz.ConsentGatheringType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.ConsentGatheringContext ; import java.util.Map ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class ConsentGathering implements ConsentGatheringType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Initializing...\" ); log . info ( \"Consent gathering. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Initializing...\" ); log . info ( \"Consent gathering. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Destroying...\" ); log . info ( \"Consent gathering. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean authorize ( int step , Object consentContext ) { log . info ( \"Consent gathering. Authorizing...\" ); ConsentGatheringContext gatheringContext = ( ConsentGatheringContext ) consentContext ; String [] allowButton = gatheringContext . getRequestParameters (). get ( \"authorizeForm:allowButton\" ); if ( step == 1 ) { if ( allowButton != null && allowButton . length > 0 ) { log . info ( \"Consent gathering. Authorization success for step 1\" ); return true ; } log . info ( \"Consent gathering. Authorization declined for step 1\" ); } else if ( step == 2 ) { if ( allowButton != null && allowButton . length > 0 ) { log . info ( \"Consent gathering. Authorization success for step 2\" ); return true ; } log . info ( \"Consent gathering. Authorization declined for step 2\" ); } return false ; } @Override public int getNextStep ( int step , Object consentContext ) { return - 1 ; } @Override public boolean prepareForStep ( int step , Object consentContext ) { ConsentGatheringContext gatheringContext = ( ConsentGatheringContext ) consentContext ; if ( ! gatheringContext . isAuthenticated ()) { log . info ( \"User is not authenticated. Aborting authorization flow...\" ); return false ; } if ( step == 2 ) { Map < String , String > pageAttributes = gatheringContext . getPageAttributes (); String consentRequest = \"This is a random consent request\" ; pageAttributes . put ( \"consent_request\" , consentRequest ); return true ; } return false ; } @Override public int getStepsCount ( Object consentContext ) { return 2 ; } @Override public String getPageForStep ( int step , Object consentContext ) { if ( step == 1 ) { return \"/authz/authorize.xhtml\" ; } else if ( step == 2 ) { return \"return \\\"/authz/transaction.xhtml\\\"\" ; } return \"\" ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/discovery/discovery/", "tags": ["administration", "developer", "script-catalog"], "text": "Discovery Script # Overview # This script is used to modify the response of the OpenID well-known discovery endpoint, /.well-known/openid-configuration . The specification for this endpoint is defined in the OpenID Connect documentation . Interface # Methods # The discovery interception script extends the base script type with the init , destroy and getApiVersion methods: Inherited Methods Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . The discovery interception script also adds the following method(s): Method def modifyResponse(self, responseAsJsonObject, context) Method Paramater responseAsJsonObject is org.json.JSONObject context is io.jans.as.server.model.common.ExecutionContext Objects # Definitions of all objects used in the script Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference Common Use Case # Script Type: Python # Add custom values to the OpenID configuration endpoint # from io.jans.model.custom.script.type.discovery import DiscoveryType from java.lang import String class Discovery ( DiscoveryType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Custom Discovery script. Initializing ...\" print \"Custom Discovery script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Custom Discovery script. Destroying ...\" print \"Custom Discovery script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply Discovery method, false - ignore it. # This method is called after Discovery response is ready. This method can modify Discovery response. # Note : # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.server.model.common.ExecutionContext (in https://github.com/JanssenProject project, ) def modifyResponse ( self , responseAsJsonObject , context ): print \"Custom - Inside modifyResponse method of Discovery script ....\" # Add a value to Discovery Response responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) # Filter out a value from Discovery Response responseAsJsonObject . remove ( \"pushed_authorization_request_endpoint\" ) # Get an IP Address of the Client making the request responseAsJsonObject . accumulate ( \"Client IP Address\" , context . getHttpRequest () . getHeader ( \"X-Forwarded-For\" )) return True Script Type: Python # Add custom values, remove values, and add client's IP request # from io.jans.model.custom.script.type.discovery import DiscoveryType from java.lang import String class Discovery ( DiscoveryType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Custom Discovery script. Initializing ...\" print \"Custom Discovery script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Custom Discovery script. Destroying ...\" print \"Custom Discovery script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def modifyResponse ( self , responseAsJsonObject , context ): print \"Custom - Inside modifyResponse method of Discovery script ....\" # Add a value to Discovery Response responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) # Filter out a value from Discovery Response responseAsJsonObject . remove ( \"pushed_authorization_request_endpoint\" ) # Get an IP Address of the Client making the request responseAsJsonObject . accumulate ( \"Client IP Address\" , context . getHttpRequest () . getHeader ( \"X-Forwarded-For\" )) return True Script Type: Java # Add custom values, remove values, and add client's IP request # import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.discovery.DiscoveryType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.model.common.ExecutionContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import org.json.JSONObject ; import java.util.Map ; public class Discovery implements DiscoveryType { private static final Logger log = LoggerFactory . getLogger ( Discovery . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Discovery Java custom script\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Discovery Java custom script\" ); scriptLogger . info ( \"Discovery Java script. Initializing ...\" ); scriptLogger . info ( \"Discovery Java script. Initialized successfully\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Destroy of Discovery Java custom script\" ); scriptLogger . info ( \"Discovery Java script. Destroying ...\" ); scriptLogger . info ( \"Discovery Java script. Destroyed successfully\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { scriptLogger . info ( \"Custom Java - Inside modifyResponse method of Discovery script ....\" ); JSONObject response = ( JSONObject ) responseAsJsonObject ; ExecutionContext ctx = ( ExecutionContext ) context ; // Add a value to Discovery Response response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); // Filter out a value from Discovery Response response . remove ( \"pushed_authorization_request_endpoint\" ); // Get an IP Address of the Client making the request response . accumulate ( \"Client IP Address\" , ctx . getHttpRequest (). getHeader ( \"X-Forwarded-For\" )); return true ; } }", "title": "OpenID Configuration"}, {"location": "script-catalog/discovery/discovery/#discovery-script", "text": "", "title": "Discovery Script"}, {"location": "script-catalog/discovery/discovery/#overview", "text": "This script is used to modify the response of the OpenID well-known discovery endpoint, /.well-known/openid-configuration . The specification for this endpoint is defined in the OpenID Connect documentation .", "title": "Overview"}, {"location": "script-catalog/discovery/discovery/#interface", "text": "", "title": "Interface"}, {"location": "script-catalog/discovery/discovery/#methods", "text": "The discovery interception script extends the base script type with the init , destroy and getApiVersion methods: Inherited Methods Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . The discovery interception script also adds the following method(s): Method def modifyResponse(self, responseAsJsonObject, context) Method Paramater responseAsJsonObject is org.json.JSONObject context is io.jans.as.server.model.common.ExecutionContext", "title": "Methods"}, {"location": "script-catalog/discovery/discovery/#objects", "text": "Definitions of all objects used in the script", "title": "Objects"}, {"location": "script-catalog/discovery/discovery/#objects_1", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/discovery/discovery/#common-use-case", "text": "", "title": "Common Use Case"}, {"location": "script-catalog/discovery/discovery/#script-type-python", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/discovery/discovery/#add-custom-values-to-the-openid-configuration-endpoint", "text": "from io.jans.model.custom.script.type.discovery import DiscoveryType from java.lang import String class Discovery ( DiscoveryType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Custom Discovery script. Initializing ...\" print \"Custom Discovery script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Custom Discovery script. Destroying ...\" print \"Custom Discovery script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply Discovery method, false - ignore it. # This method is called after Discovery response is ready. This method can modify Discovery response. # Note : # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.server.model.common.ExecutionContext (in https://github.com/JanssenProject project, ) def modifyResponse ( self , responseAsJsonObject , context ): print \"Custom - Inside modifyResponse method of Discovery script ....\" # Add a value to Discovery Response responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) # Filter out a value from Discovery Response responseAsJsonObject . remove ( \"pushed_authorization_request_endpoint\" ) # Get an IP Address of the Client making the request responseAsJsonObject . accumulate ( \"Client IP Address\" , context . getHttpRequest () . getHeader ( \"X-Forwarded-For\" )) return True", "title": "Add custom values to the OpenID configuration endpoint"}, {"location": "script-catalog/discovery/discovery/#script-type-python_1", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/discovery/discovery/#add-custom-values-remove-values-and-add-clients-ip-request", "text": "from io.jans.model.custom.script.type.discovery import DiscoveryType from java.lang import String class Discovery ( DiscoveryType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Custom Discovery script. Initializing ...\" print \"Custom Discovery script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Custom Discovery script. Destroying ...\" print \"Custom Discovery script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def modifyResponse ( self , responseAsJsonObject , context ): print \"Custom - Inside modifyResponse method of Discovery script ....\" # Add a value to Discovery Response responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) # Filter out a value from Discovery Response responseAsJsonObject . remove ( \"pushed_authorization_request_endpoint\" ) # Get an IP Address of the Client making the request responseAsJsonObject . accumulate ( \"Client IP Address\" , context . getHttpRequest () . getHeader ( \"X-Forwarded-For\" )) return True", "title": "Add custom values, remove values, and add client's IP request"}, {"location": "script-catalog/discovery/discovery/#script-type-java", "text": "", "title": "Script Type: Java"}, {"location": "script-catalog/discovery/discovery/#add-custom-values-remove-values-and-add-clients-ip-request_1", "text": "import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.discovery.DiscoveryType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.model.common.ExecutionContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import org.json.JSONObject ; import java.util.Map ; public class Discovery implements DiscoveryType { private static final Logger log = LoggerFactory . getLogger ( Discovery . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Discovery Java custom script\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Discovery Java custom script\" ); scriptLogger . info ( \"Discovery Java script. Initializing ...\" ); scriptLogger . info ( \"Discovery Java script. Initialized successfully\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Destroy of Discovery Java custom script\" ); scriptLogger . info ( \"Discovery Java script. Destroying ...\" ); scriptLogger . info ( \"Discovery Java script. Destroyed successfully\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { scriptLogger . info ( \"Custom Java - Inside modifyResponse method of Discovery script ....\" ); JSONObject response = ( JSONObject ) responseAsJsonObject ; ExecutionContext ctx = ( ExecutionContext ) context ; // Add a value to Discovery Response response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); // Filter out a value from Discovery Response response . remove ( \"pushed_authorization_request_endpoint\" ); // Get an IP Address of the Client making the request response . accumulate ( \"Client IP Address\" , ctx . getHttpRequest (). getHeader ( \"X-Forwarded-For\" )); return true ; } }", "title": "Add custom values, remove values, and add client's IP request"}, {"location": "script-catalog/discovery/discovery/", "text": "Discovery Script Guide # Overview # The Authorization Server Metadata spec RFC8414 (also known as OAuth Discovery) defines a format for clients to use to look up the information needed to interact with a particular OAuth server. This includes things like:- - finding the authorization endpoint, - listing the supported scopes and client authentication mechanisms. The \"OpenID Connect Discovery 1.0\" defines the metadata in such a way that is compatible with OpenID Connect Discovery while being applicable to a wider set of OAuth 2.0 use cases. This is intentionally parallel to the way that \"OAuth 2.0 Dynamic Client Registration Protocol\" RFC7591 defines the dynamic client registration mechanisms \"OpenID Connect Dynamic Client Registration 1.0 OpenID.Registration so that is compatible with it. The metadata for an authorization server is retrieved from a know location as a JSON object RFC8259 , which defines its endpoint locations and authorization server capabilities. This metadata can be passed either:- - in a self-asserted fashion from the server origin via HTTPS - or as a set of signed metadata values represented as claims in a JSON Web Token JWT . In the JWT case, the issuer is vouching for the validity of the data coming from the authorization server. This is analogous to the role that the Software Statement plays in OAuth Dynamic Client Registration RFC7591. Note: The means by which the client chooses an authorization server is out of scope. In some cases, the issuer identifier may be manually configured into the client. In other cases, it may be dynamically discovered, for instance, through the use of WebFinger . Discovery script allows to modify response of OpenID Connect Discovery RFC8414 . Methods # The discovery interception script extends the base script type with the methods - Method Method description def init(self, customScript, configurationAttributes) Inherited Method This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) Inherited Method This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) Inherited Method The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 def modifyResponse(self, responseAsJsonObject, context) This method is called after discovery response is ready. This method can modify discovery response. responseAsJsonObject is org.codehaus.jettison.json.JSONObject context is io.jans.as.server.model.common.ExecutionContext The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . configurationAttributes = new HashMap < String , SimpleCustomProperty > () ; configurationAttributes . put ( \"Location Type\" , new SimpleCustomProperty ( \"location_type\" , \"MySQL\" , \"Storage Location for the script\" )) ; Snippet # # Returns boolean , true - apply discovery method , false - ignore it . # This method is called after discovery response is ready . This method can modify discovery response . # Note : # responseAsJsonObject - is org . codehaus . jettison . json . JSONObject , you can use any method to manipulate json # context is reference of io . jans . as . server . model . common . ExecutionContext ( in https : // github . com / JanssenProject project ) def modifyResponse ( self , responseAsJsonObject , context ) : responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True Common Use Cases # Script Type: Python # Add a value (Client IP Address) and Filter out a value from Discovery Response # The sample code snippet shows how to add and filter out a value from Discovery Response. Script Type: Java # Add a value (Client IP Address) and Filter out a value from Discovery Response # The sample code snippet shows how to add and filter out a value from Discovery Response.", "title": "Discovery Script Guide"}, {"location": "script-catalog/discovery/discovery/#discovery-script-guide", "text": "", "title": "Discovery Script Guide"}, {"location": "script-catalog/discovery/discovery/#overview", "text": "The Authorization Server Metadata spec RFC8414 (also known as OAuth Discovery) defines a format for clients to use to look up the information needed to interact with a particular OAuth server. This includes things like:- - finding the authorization endpoint, - listing the supported scopes and client authentication mechanisms. The \"OpenID Connect Discovery 1.0\" defines the metadata in such a way that is compatible with OpenID Connect Discovery while being applicable to a wider set of OAuth 2.0 use cases. This is intentionally parallel to the way that \"OAuth 2.0 Dynamic Client Registration Protocol\" RFC7591 defines the dynamic client registration mechanisms \"OpenID Connect Dynamic Client Registration 1.0 OpenID.Registration so that is compatible with it. The metadata for an authorization server is retrieved from a know location as a JSON object RFC8259 , which defines its endpoint locations and authorization server capabilities. This metadata can be passed either:- - in a self-asserted fashion from the server origin via HTTPS - or as a set of signed metadata values represented as claims in a JSON Web Token JWT . In the JWT case, the issuer is vouching for the validity of the data coming from the authorization server. This is analogous to the role that the Software Statement plays in OAuth Dynamic Client Registration RFC7591. Note: The means by which the client chooses an authorization server is out of scope. In some cases, the issuer identifier may be manually configured into the client. In other cases, it may be dynamically discovered, for instance, through the use of WebFinger . Discovery script allows to modify response of OpenID Connect Discovery RFC8414 .", "title": "Overview"}, {"location": "script-catalog/discovery/discovery/#methods", "text": "The discovery interception script extends the base script type with the methods - Method Method description def init(self, customScript, configurationAttributes) Inherited Method This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) Inherited Method This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) Inherited Method The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 def modifyResponse(self, responseAsJsonObject, context) This method is called after discovery response is ready. This method can modify discovery response. responseAsJsonObject is org.codehaus.jettison.json.JSONObject context is io.jans.as.server.model.common.ExecutionContext The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . configurationAttributes = new HashMap < String , SimpleCustomProperty > () ; configurationAttributes . put ( \"Location Type\" , new SimpleCustomProperty ( \"location_type\" , \"MySQL\" , \"Storage Location for the script\" )) ;", "title": "Methods"}, {"location": "script-catalog/discovery/discovery/#snippet", "text": "# Returns boolean , true - apply discovery method , false - ignore it . # This method is called after discovery response is ready . This method can modify discovery response . # Note : # responseAsJsonObject - is org . codehaus . jettison . json . JSONObject , you can use any method to manipulate json # context is reference of io . jans . as . server . model . common . ExecutionContext ( in https : // github . com / JanssenProject project ) def modifyResponse ( self , responseAsJsonObject , context ) : responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True", "title": "Snippet"}, {"location": "script-catalog/discovery/discovery/#common-use-cases", "text": "", "title": "Common Use Cases"}, {"location": "script-catalog/discovery/discovery/#script-type-python", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/discovery/discovery/#add-a-value-client-ip-address-and-filter-out-a-value-from-discovery-response", "text": "The sample code snippet shows how to add and filter out a value from Discovery Response.", "title": "Add a value (Client IP Address) and Filter out a value from Discovery Response"}, {"location": "script-catalog/discovery/discovery/#script-type-java", "text": "", "title": "Script Type: Java"}, {"location": "script-catalog/discovery/discovery/#add-a-value-client-ip-address-and-filter-out-a-value-from-discovery-response_1", "text": "The sample code snippet shows how to add and filter out a value from Discovery Response.", "title": "Add a value (Client IP Address) and Filter out a value from Discovery Response"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/", "tags": ["administration", "developer", "script-catalog", "DynamicScope"], "text": "Overview # The dynamic scope custom script allows the authorization server to generate a list of claims (and their values) on the fly, depending on circumstances such as the ID of the client requesting it, authenticated user's session parameters, values of other users' attributes, results of some calculations implementing specific business logic and/or requests to remote APIs or databases. Claims are then returned the usual way in a response to a call to the /userinfo endpoint. Interface # The dynamic scope script implements the DynamicScopeType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def update(self, dynamicScopeContext, configurationAttributes) Main dynamic scope method. Peforms any needed logic, updates JSON Web Token and returns True if dynamic scope was added successfully, false otherwise. def getSupportedClaims(self, configurationAttributes) Returns an array of claims that are allowed to be added by the custom script Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference dynamicScopeContext Reference Use case: Add dynamic scope with the org_name claim # This script has been adapted from the Gluu Server sample dynamic scope script Script Type: Python # from java.util import Arrays , ArrayList from io.jans.model.custom.script.type.scope import DynamicScopeType class DynamicScope ( DynamicScopeType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"Dynamic scope. Initialization\" print \"Dynamic scope. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Dynamic scope. Destroy\" print \"Dynamic scope. Destroyed successfully\" return True def update ( self , dynamicScopeContext , configurationAttributes ): print \"Dynamic scope. Update method\" dynamicScopes = dynamicScopeContext . getDynamicScopes () user = dynamicScopeContext . getUser () jsonToken = dynamicScopeContext . getJsonToken () claims = jsonToken . getClaims () # Iterate through list of dynamic scopes in order to add custom scopes if needed print \"Dynamic scope. Dynamic scopes:\" , dynamicScopes for dynamicScope in dynamicScopes : # Add organization name if there is scope = org_name if ( StringHelper . equalsIgnoreCase ( dynamicScope , \"org_name\" )): claims . setClaim ( \"org_name\" , \"Test Value\" ) continue # Add work phone if there is scope = work_phone return True def getApiVersion ( self ): return 1 def getSupportedClaims ( self , configurationAttributes ): return Arrays . asList ( \"org_name\" ) Script Type: Java # import java.util.List ; import java.util.Map ; import java.util.Arrays ; import java.util.ArrayList ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.model.custom.script.type.scope.DynamicScopeType ; import io.jans.as.server.service.external.context.DynamicScopeExternalContext ; import io.jans.as.model.token.JsonWebResponse ; import io.jans.as.model.jwt.JwtClaims ; import io.jans.util.StringHelper ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class DynamicScope implements DynamicScopeType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Initializing...\" ); log . info ( \"Dynamic Scope. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Initializing...\" ); log . info ( \"Dynamic Scope. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Destroying...\" ); log . info ( \"Dynamic Scope. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean update ( Object dynamicScopeContext , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Updating...\" ); DynamicScopeExternalContext dynamicContext = ( DynamicScopeExternalContext ) dynamicScopeContext ; ArrayList < String > dynamicScopes = ( ArrayList < String > ) dynamicContext . getDynamicScopes (); JsonWebResponse jwt = dynamicContext . getJsonWebResponse (); JwtClaims claims = jwt . getClaims (); log . info ( \"Dynamic Scope. Dynamic scopes: \" + dynamicScopes . toString ()); for ( String dynamicScope : dynamicScopes ) { if ( StringHelper . equalsIgnoreCase ( dynamicScope , \"org_name\" )) { claims . setClaim ( \"org_name\" , \"Test Value\" ); continue ; } } return true ; } @Override public List < String > getSupportedClaims ( Map < String , SimpleCustomProperty > configurationAttributes ) { return Arrays . asList ( \"org_name\" ); } } Sample Scripts # Dynamic Permission MemberOf Attribute Organization Name Session Parameter Work Phone", "title": "Dynamic Scope"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#overview", "text": "The dynamic scope custom script allows the authorization server to generate a list of claims (and their values) on the fly, depending on circumstances such as the ID of the client requesting it, authenticated user's session parameters, values of other users' attributes, results of some calculations implementing specific business logic and/or requests to remote APIs or databases. Claims are then returned the usual way in a response to a call to the /userinfo endpoint.", "title": "Overview"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#interface", "text": "The dynamic scope script implements the DynamicScopeType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#new-methods", "text": "Method header Method description def update(self, dynamicScopeContext, configurationAttributes) Main dynamic scope method. Peforms any needed logic, updates JSON Web Token and returns True if dynamic scope was added successfully, false otherwise. def getSupportedClaims(self, configurationAttributes) Returns an array of claims that are allowed to be added by the custom script", "title": "New Methods"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference dynamicScopeContext Reference", "title": "Objects"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#use-case-add-dynamic-scope-with-the-org_name-claim", "text": "This script has been adapted from the Gluu Server sample dynamic scope script", "title": "Use case: Add dynamic scope with the org_name claim"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#script-type-python", "text": "from java.util import Arrays , ArrayList from io.jans.model.custom.script.type.scope import DynamicScopeType class DynamicScope ( DynamicScopeType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"Dynamic scope. Initialization\" print \"Dynamic scope. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Dynamic scope. Destroy\" print \"Dynamic scope. Destroyed successfully\" return True def update ( self , dynamicScopeContext , configurationAttributes ): print \"Dynamic scope. Update method\" dynamicScopes = dynamicScopeContext . getDynamicScopes () user = dynamicScopeContext . getUser () jsonToken = dynamicScopeContext . getJsonToken () claims = jsonToken . getClaims () # Iterate through list of dynamic scopes in order to add custom scopes if needed print \"Dynamic scope. Dynamic scopes:\" , dynamicScopes for dynamicScope in dynamicScopes : # Add organization name if there is scope = org_name if ( StringHelper . equalsIgnoreCase ( dynamicScope , \"org_name\" )): claims . setClaim ( \"org_name\" , \"Test Value\" ) continue # Add work phone if there is scope = work_phone return True def getApiVersion ( self ): return 1 def getSupportedClaims ( self , configurationAttributes ): return Arrays . asList ( \"org_name\" )", "title": "Script Type: Python"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#script-type-java", "text": "import java.util.List ; import java.util.Map ; import java.util.Arrays ; import java.util.ArrayList ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.model.custom.script.type.scope.DynamicScopeType ; import io.jans.as.server.service.external.context.DynamicScopeExternalContext ; import io.jans.as.model.token.JsonWebResponse ; import io.jans.as.model.jwt.JwtClaims ; import io.jans.util.StringHelper ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class DynamicScope implements DynamicScopeType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Initializing...\" ); log . info ( \"Dynamic Scope. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Initializing...\" ); log . info ( \"Dynamic Scope. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Destroying...\" ); log . info ( \"Dynamic Scope. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean update ( Object dynamicScopeContext , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Updating...\" ); DynamicScopeExternalContext dynamicContext = ( DynamicScopeExternalContext ) dynamicScopeContext ; ArrayList < String > dynamicScopes = ( ArrayList < String > ) dynamicContext . getDynamicScopes (); JsonWebResponse jwt = dynamicContext . getJsonWebResponse (); JwtClaims claims = jwt . getClaims (); log . info ( \"Dynamic Scope. Dynamic scopes: \" + dynamicScopes . toString ()); for ( String dynamicScope : dynamicScopes ) { if ( StringHelper . equalsIgnoreCase ( dynamicScope , \"org_name\" )) { claims . setClaim ( \"org_name\" , \"Test Value\" ); continue ; } } return true ; } @Override public List < String > getSupportedClaims ( Map < String , SimpleCustomProperty > configurationAttributes ) { return Arrays . asList ( \"org_name\" ); } }", "title": "Script Type: Java"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#sample-scripts", "text": "Dynamic Permission MemberOf Attribute Organization Name Session Parameter Work Phone", "title": "Sample Scripts"}, {"location": "script-catalog/end_session/end-session/", "tags": ["administration", "developer", "script-catalog", "EndSession"], "text": "Overview # End Session scripts allows the administrator to modify HTML response for OpenID Connect Frontchannel logout ( spec ). Interface # The end session script implements the EndSessionType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def getFrontchannelHtml(self, context) Returns string, it must be valid HTML (with iframes according to specification ). This method is called on /end_session after actual session is killed and authorization server constructs HTML to return to RP. Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Reference Use case: Dummy Logout Page # This script has been adapted from the Gluu Server sample end session script . Note The example script is a proof of concept, as the getFrontchannelHtml() must return an actual HTML string. Script Type: Python # from io.jans.model.custom.script.type.logout import EndSessionType from java.lang import String class EndSession ( EndSessionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"EndSession script. Initializing ...\" print \"EndSession script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"EndSession script. Destroying ...\" print \"EndSession script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Must return an HTML string def getFrontchannelHtml ( self , context ): return \"\" Script Type: Java # import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.logout.EndSessionType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.EndSessionContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class EndSession implements EndSessionType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Destroying...\" ); log . info ( \"ROPC Script. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public String getFrontchannelHtml ( Object context ) { EndSessionContext endSessionContext = ( EndSessionContext ) context ; // Must return a real HTML string as per OIDC front channel logout spec return \"\" ; } }", "title": "End Session"}, {"location": "script-catalog/end_session/end-session/#overview", "text": "End Session scripts allows the administrator to modify HTML response for OpenID Connect Frontchannel logout ( spec ).", "title": "Overview"}, {"location": "script-catalog/end_session/end-session/#interface", "text": "The end session script implements the EndSessionType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/end_session/end-session/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/end_session/end-session/#new-methods", "text": "Method header Method description def getFrontchannelHtml(self, context) Returns string, it must be valid HTML (with iframes according to specification ). This method is called on /end_session after actual session is killed and authorization server constructs HTML to return to RP.", "title": "New Methods"}, {"location": "script-catalog/end_session/end-session/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Reference", "title": "Objects"}, {"location": "script-catalog/end_session/end-session/#use-case-dummy-logout-page", "text": "This script has been adapted from the Gluu Server sample end session script . Note The example script is a proof of concept, as the getFrontchannelHtml() must return an actual HTML string.", "title": "Use case: Dummy Logout Page"}, {"location": "script-catalog/end_session/end-session/#script-type-python", "text": "from io.jans.model.custom.script.type.logout import EndSessionType from java.lang import String class EndSession ( EndSessionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"EndSession script. Initializing ...\" print \"EndSession script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"EndSession script. Destroying ...\" print \"EndSession script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Must return an HTML string def getFrontchannelHtml ( self , context ): return \"\"", "title": "Script Type: Python"}, {"location": "script-catalog/end_session/end-session/#script-type-java", "text": "import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.logout.EndSessionType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.EndSessionContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class EndSession implements EndSessionType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Destroying...\" ); log . info ( \"ROPC Script. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public String getFrontchannelHtml ( Object context ) { EndSessionContext endSessionContext = ( EndSessionContext ) context ; // Must return a real HTML string as per OIDC front channel logout spec return \"\" ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/id_generator/id-generator/", "tags": ["administration", "developer", "script-catalog", "IdGenerator"], "text": "Overview # By default Janssen Auth Server uses an internal method to generate unique identifiers for new person/client, etc. entries. In most cases the format of the ID is: '!' + idType.getInum() + '!' + four_random_HEX_characters + '.' + four_random_HEX_characters. The ID generation script enables an admin to implement custom ID generation rules. Interface # The ID Generator script implements the IdGeneratorType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def generateId(self, appId, idType, idPrefix, configurationAttributes) appId is application ID, idType is ID Type, idPrefix is ID Prefix Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes Use case: Sample ID generator # This script has been adapted from the Gluu Server sample ID generator script . Script Type: Python # from io.jans.model.custom.script.type.id import IdGeneratorType import java class IdGenerator ( IdGeneratorType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"Id generator. Initialization\" print \"Id generator. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Id generator. Destroy\" print \"Id generator. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Id generator init method # appId is application Id # idType is Id Type # idPrefix is Id Prefix def generateId ( self , appId , idType , idPrefix , configurationAttributes ): print \"Id generator. Generate Id\" print \"Id generator. Generate Id. AppId: '\" , appId , \"', IdType: '\" , idType , \"', IdPrefix: '\" , idPrefix , \"'\" # Return None or empty string to trigger default Id generation method return None Script Type: Java # import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.id.IdGeneratorType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class EndSession implements EndSessionType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Initializing...\" ); log . info ( \"ID Generator. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Initializing...\" ); log . info ( \"ID Generator. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Destroying...\" ); log . info ( \"ID Generator. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public String generateId ( String appId , String idType , String idPrefix , Map < String SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Generate Id\" ); // Return None or empty string to trigger default Id generation method return \"\" ; } }", "title": "ID Generator"}, {"location": "script-catalog/id_generator/id-generator/#overview", "text": "By default Janssen Auth Server uses an internal method to generate unique identifiers for new person/client, etc. entries. In most cases the format of the ID is: '!' + idType.getInum() + '!' + four_random_HEX_characters + '.' + four_random_HEX_characters. The ID generation script enables an admin to implement custom ID generation rules.", "title": "Overview"}, {"location": "script-catalog/id_generator/id-generator/#interface", "text": "The ID Generator script implements the IdGeneratorType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/id_generator/id-generator/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/id_generator/id-generator/#new-methods", "text": "Method header Method description def generateId(self, appId, idType, idPrefix, configurationAttributes) appId is application ID, idType is ID Type, idPrefix is ID Prefix", "title": "New Methods"}, {"location": "script-catalog/id_generator/id-generator/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes", "title": "Objects"}, {"location": "script-catalog/id_generator/id-generator/#use-case-sample-id-generator", "text": "This script has been adapted from the Gluu Server sample ID generator script .", "title": "Use case: Sample ID generator"}, {"location": "script-catalog/id_generator/id-generator/#script-type-python", "text": "from io.jans.model.custom.script.type.id import IdGeneratorType import java class IdGenerator ( IdGeneratorType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"Id generator. Initialization\" print \"Id generator. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Id generator. Destroy\" print \"Id generator. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Id generator init method # appId is application Id # idType is Id Type # idPrefix is Id Prefix def generateId ( self , appId , idType , idPrefix , configurationAttributes ): print \"Id generator. Generate Id\" print \"Id generator. Generate Id. AppId: '\" , appId , \"', IdType: '\" , idType , \"', IdPrefix: '\" , idPrefix , \"'\" # Return None or empty string to trigger default Id generation method return None", "title": "Script Type: Python"}, {"location": "script-catalog/id_generator/id-generator/#script-type-java", "text": "import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.id.IdGeneratorType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class EndSession implements EndSessionType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Initializing...\" ); log . info ( \"ID Generator. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Initializing...\" ); log . info ( \"ID Generator. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Destroying...\" ); log . info ( \"ID Generator. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public String generateId ( String appId , String idType , String idPrefix , Map < String SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Generate Id\" ); // Return None or empty string to trigger default Id generation method return \"\" ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/introspection/interception-scripts-debug/", "tags": ["administration", "developer"], "text": "Setup # For development the kubernetes setup must be local and accessible to the debug server address. The following steps will walk you trough a setup using Minikube with docker driver, and ksync for syncing the files between local, and the container. The following instructions assume a fresh ubuntu 20.04, however the setup can be done on a different operating systems such as macOS or Windows. System Requirements # The minimum system requirement for running all jans services are 8GB RAM , 4 CPU , and 50GB disk . This can be dropped to 4GB RAM , 4CPU and 20GB disk space if operating with required services auth-server, and LDAP. Setup Minikube # Install Docker 18.09 or higher. For other operating systems follow the appropriate docs . Install minikube , but do not start it yet. Install kubectl . Once Minikube is installed start it with the docker driver. minikube start --driver = docker If not automatically set configure kubectl to use the cluster: kubectl config use-context minikube Enable ingress on minikube minikube addons enable ingress Install Janssen # Install Helm3 Install Janssen helm repo add jans https://janssenproject.github.io/jans-cloud-native/charts kubectl create ns jans helm install jans-auth jans/jans -n jans --set global.lbIp = \" $( minikube ip ) \" --set global.provisioner = \"k8s.io/minikube-hostpath\" --devel Install Ksync # Once Janssen is fully running we want to create an active sync between a local folder, and the folder that will hold the interception scripts inside the auth server container. Create a folder that will hold the interception script inside the auth server container. Place the namespace where jans is installed in the env JANS_NAMESPACE and execute: JANS_NAMESPACE = <jans-namespace> for pod in $( kubectl get pods -n $JANS_NAMESPACE --selector = APP_NAME = auth-server --output = jsonpath ={ .items..metadata.name } ) ; do kubectl exec -ti $pod -n $JANS_NAMESPACE -- mkdir -p /deploy/interception-scripts-ksync done Install ksync curl https://ksync.github.io/gimme-that/gimme.sh | bash Initialize ksync ksync init -n <jans-namespace> Start ksync. ksync watch -n <jans-namespace> & Open a new terminal and create a folder called interception-scripts-ksync mkdir -p $( pwd ) /interception-scripts-ksync Create a spec to start syncing folders between the local system and auth server container. ksync create --selector = APP_NAME = auth-server $( pwd ) /interception-scripts-ksync /deploy/interception-scripts-ksync -n <jans-namespace> Check the status. Also check the terminal where the watch command is running. ksync get 1. Move the interception script to the local folder $(pwd)/interception-scripts-ksync . In the below example we copied the following script as basic.py : # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2016, Janssen # # Author: Yuriy Movchan # from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper import java class PersonAuthentication ( PersonAuthenticationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Basic. Initialization\" print \"Basic. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Basic. Destroy\" print \"Basic. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 def isValidAuthenticationMethod ( self , usageType , configurationAttributes ): return True def getAlternativeAuthenticationMethod ( self , usageType , configurationAttributes ): return None def authenticate ( self , configurationAttributes , requestParameters , step ): authenticationService = CdiUtil . bean ( AuthenticationService ) if ( step == 1 ): print \"Basic. Authenticate for step 1\" identity = CdiUtil . bean ( Identity ) credentials = identity . getCredentials () user_name = credentials . getUsername () user_password = credentials . getPassword () logged_in = False if ( StringHelper . isNotEmptyString ( user_name ) and StringHelper . isNotEmptyString ( user_password )): logged_in = authenticationService . authenticate ( user_name , user_password ) if ( not logged_in ): return False return True else : return False def prepareForStep ( self , configurationAttributes , requestParameters , step ): if ( step == 1 ): print \"Basic. Prepare for Step 1\" return True else : return False def getExtraParametersForStep ( self , configurationAttributes , step ): return None def getCountAuthenticationSteps ( self , configurationAttributes ): return 1 def getPageForStep ( self , configurationAttributes , step ): return \"\" def getNextStep ( self , configurationAttributes , requestParameters , step ): return - 1 def getLogoutExternalUrl ( self , configurationAttributes , requestParameters ): print \"Get external logout URL call\" return None def logout ( self , configurationAttributes , requestParameters ): return True Install an IDE # The IDE can be of choice but must contain PyDev. We chose Liclipse for this demonstration. Once complete, start the PyDev debug server: Open Liclipse Install the jython jar for the interpreter. wget https://repo1.maven.org/maven2/org/python/jython-standalone/2.7.2/jython-standalone-2.7.2.jar From the menu: go to File -> Open File and choose the interception script that will be debugged in $(pwd)/interception-scripts-ksync . When opening the Python file for the first time, we need to instruct Liclipse to use a specific interpreter. Follow these steps: Press the \"Manual Config\" button in the dialog box after opening the Python file Open \"PyDev->Interpreters->Jython Interpreters\" Click the \"New...\" button in the right panel. Name it \"Jython\" and specify the interpreter executable that was downloaded previously \"jython-standalone-2.7.2.jar\" Click \"OK\", then confirm the settings by clicking \"OK\" again, then \"Apply and Close\" In the final dialog, confirm the settings by clicking \"OK\" From the menu: go to Window -> Perspective -> Open Perspective -> Other.. -> Debug From the menu: go to Pydev > Start Debug Server . Now the server should have started at port 5678 . Take a note of the ip of the computer running Liclipse and save it for later use. Remember that the auth server pod must be able to communicate with this ip. If you have followed the instructions above and installed minikube on your local computer which is the same computer Liclipse is operating on you should be able to reach it from within the pods. Development & Debugging # Now we are ready to perform script development and debugging. Here is a quick overview: Enable remote debugging on the jans-auth service. Instruct the auth server to load the script from the file system instead of LDAP. Add debug instructions to the script. Execute the script. Enable Remote Debugging in jans-auth # In order to enable remote debugging in the jans-auth process, open /etc/default/jans-auth in your favorite text editor. The default JAVA_OPTIONS variable is as follows: JAVA_OPTIONS=\"-server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base=/etc/jans -Dserver.base=/opt/jans/jetty/jans-auth -Dlog.base=/opt/jans/jetty/jans-auth -Dpython.home=/opt/jython\" Modify to this: JAVA_OPTIONS=\"-server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base=/etc/jans -Dserver.base=/opt/jans/jetty/jans-auth -Dlog.base=/opt/jans/jetty/jans-auth -Dpython.home=/opt/jython -Dorg.eclipse.jetty.server.Request.maxFormContentSize=50000000 -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005\" The last line will enable remote debug on port 5005. Now restart the jans-auth service. # To list all jans processes systemctl list-units --all \"jans*\" # On Ubuntu, the service name is jans-auth.service systemctl restart jans-auth.service If you are running Jans on a local VM or anywhere that is not the same as the machine that will be debugging, you will need to set up an SSH tunnel on port 5005. Execute the following command: ssh -L 5005:localhost:5005 <username>@<host> This will cause your local host's port 5005 to listen on the remote server's port 5005. Now you can use your favorite IDE and set up the remote debugger to connect to localhost:5005 . Enable remote debug in Jython Custom Script # For Jython scripts, we need additional steps to enable breakpoints. After the import section, add: REMOTE_DEBUG = True if REMOTE_DEBUG: try: import sys import pydevd except ImportError as ex: print \"Failed to import pydevd: %s\" % ex raise Add the following lines wherever breakpoints are needed: if REMOTE_DEBUG: pydevd.settrace('localhost', port=5678, stdoutToServer=True, stderrToServer=True) Sample Scenario # Copy the below script to $(pwd)/interception-scripts-ksync/basic.py # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2016, Janssen # # Author: Yuriy Movchan # from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper import java class PersonAuthentication ( PersonAuthenticationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Basic. Initialization\" print \"Basic. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Basic. Destroy\" print \"Basic. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 def isValidAuthenticationMethod ( self , usageType , configurationAttributes ): return True def getAlternativeAuthenticationMethod ( self , usageType , configurationAttributes ): return None def authenticate ( self , configurationAttributes , requestParameters , step ): authenticationService = CdiUtil . bean ( AuthenticationService ) if ( step == 1 ): print \"Basic. Authenticate for step 1\" identity = CdiUtil . bean ( Identity ) credentials = identity . getCredentials () user_name = credentials . getUsername () user_password = credentials . getPassword () logged_in = False if ( StringHelper . isNotEmptyString ( user_name ) and StringHelper . isNotEmptyString ( user_password )): logged_in = authenticationService . authenticate ( user_name , user_password ) if ( not logged_in ): return False return True else : return False def prepareForStep ( self , configurationAttributes , requestParameters , step ): if ( step == 1 ): print \"Basic. Prepare for Step 1\" return True else : return False def getExtraParametersForStep ( self , configurationAttributes , step ): return None def getCountAuthenticationSteps ( self , configurationAttributes ): return 1 def getPageForStep ( self , configurationAttributes , step ): return \"\" def getNextStep ( self , configurationAttributes , requestParameters , step ): return - 1 def getLogoutExternalUrl ( self , configurationAttributes , requestParameters ): print \"Get external logout URL call\" return None def logout ( self , configurationAttributes , requestParameters ): return True Make sure to have an LDAP browser available. We recommend Apache Directory Studio . Port forward the opendj pod. kubectl port-forward jans-opendj-0 -n <jans-namespace> 1636 :1636 --address 0 .0.0.0 Create a connection to the ldap browser. The default password will be Test1234# if not changed in the helm install command. Inside the browser navigate to o=jans, ou=scripts . Right click on ou=scripts and click on Quick Search . Inside the pop up box that appears fill Returning Attributes with displayName , and press Apply and Close In the results that appear click on the Dn that has a displayName of basic . Choose to load the script from file instead of ldap. Inside the browser change jansModuleProperty with value {\"value1\":\"location_type\",\"value2\":\"ldap\",\"description\":\"\"} to {\"value1\":\"location_type\",\"value2\":\"file\",\"description\":\"\"} Specify the Script Path location to the location of the folder inside auth server pods: /deploy/interception-scripts-ksync/basic.py . Right click the upper jansModuleProperty and click New Value . A new entry for jansModuleProperty will be created. Insert the following for the value: {\"value1\":\"location_path\",\"value2\":\"/deploy/interception-scripts-ksync/basic.py\",\"description\":\"\"} Enable the script by settings jansEnabled to true . The following is an example of how the basic script entry should look. Check the following log inside the the auth-server container to verify that auth server loaded the script properly: /opt/jans/jetty/jans-auth/logs/jans-auth_script.log . It should look like this: kubectl exec -ti <auth-server-pod-name> -n <jans-namespace> -- tail -f /opt/jans/jetty/jans-auth/logs/jans-auth_script.log You should find the following in the log: ... (PythonService.java:239) - Basic. Initialization ... (PythonService.java:239) - Basic. Initialized successfully Download the jython jar for the interpreter. wget https://repo1.maven.org/maven2/org/python/jython-standalone/2.7.2/jython-standalone-2.7.2.jar From the IDE (Liclipse) menu: navigate to File -> Open File and choose the interception script that will be debugged in $(pwd)/interception-scripts-ksync/basic.py When opening the Python file for the first time, we need to instruct Liclipse to use a specific interpreter. Follow these steps: Press the \"Manual Config\" button in the dialog box after opening the Python file Open \"PyDev->Interpreters->Jython Interpreters\" Click the \"New...\" button in the right panel. Name it \"Jython\" and specify the interpreter executable that was downloaded previously \"jython-standalone-2.7.2.jar\" Click \"OK\", then confirm the settings by clicking \"OK\" again, then \"Apply and Close\" In the final dialog, confirm the settings by clicking \"OK\" Open basic.py in a file editor. After the import section, add the following lines to load the PyDev libraries: REMOTE_DEBUG = True if REMOTE_DEBUG: try: import sys import pydevd except ImportError as ex: print \"Failed to import pydevd: %s\" % ex raise Add this break condition to the first line in the authenticate method. Place the ip of the maching running the ide , here liclipse i.e 192.168.140.2 . if REMOTE_DEBUG: pydevd.settrace ( '<ip-of-machine-running-ide>' , port = 5678 , stdoutToServer = True, stderrToServer = True ) Save basic.py Within one minute, the auth server should load the changed file. Check the following log file again to make sure there are no load errors: /opt/jans/jetty/jans-auth/logs/jans-auth_script.log To check if the script works, update the default authentication method to Basic Authentication. Preform this in the LDAP browser. Navigate to o=jans,ou=configuration . Change the jansAuthMode to basic instead of simple_password_auth . After executing pydevd.settrace the script will transfer execution control to the PyDev server in Liclipse. You can use any debug commands. For example: Step Over (F6), Resume (F8), etc After debugging is finished, resume script execution to transfer execution control back to the auth server.", "title": "Script Debugging"}, {"location": "script-catalog/introspection/interception-scripts-debug/#setup", "text": "For development the kubernetes setup must be local and accessible to the debug server address. The following steps will walk you trough a setup using Minikube with docker driver, and ksync for syncing the files between local, and the container. The following instructions assume a fresh ubuntu 20.04, however the setup can be done on a different operating systems such as macOS or Windows.", "title": "Setup"}, {"location": "script-catalog/introspection/interception-scripts-debug/#system-requirements", "text": "The minimum system requirement for running all jans services are 8GB RAM , 4 CPU , and 50GB disk . This can be dropped to 4GB RAM , 4CPU and 20GB disk space if operating with required services auth-server, and LDAP.", "title": "System Requirements"}, {"location": "script-catalog/introspection/interception-scripts-debug/#setup-minikube", "text": "Install Docker 18.09 or higher. For other operating systems follow the appropriate docs . Install minikube , but do not start it yet. Install kubectl . Once Minikube is installed start it with the docker driver. minikube start --driver = docker If not automatically set configure kubectl to use the cluster: kubectl config use-context minikube Enable ingress on minikube minikube addons enable ingress", "title": "Setup Minikube"}, {"location": "script-catalog/introspection/interception-scripts-debug/#install-janssen", "text": "Install Helm3 Install Janssen helm repo add jans https://janssenproject.github.io/jans-cloud-native/charts kubectl create ns jans helm install jans-auth jans/jans -n jans --set global.lbIp = \" $( minikube ip ) \" --set global.provisioner = \"k8s.io/minikube-hostpath\" --devel", "title": "Install Janssen"}, {"location": "script-catalog/introspection/interception-scripts-debug/#install-ksync", "text": "Once Janssen is fully running we want to create an active sync between a local folder, and the folder that will hold the interception scripts inside the auth server container. Create a folder that will hold the interception script inside the auth server container. Place the namespace where jans is installed in the env JANS_NAMESPACE and execute: JANS_NAMESPACE = <jans-namespace> for pod in $( kubectl get pods -n $JANS_NAMESPACE --selector = APP_NAME = auth-server --output = jsonpath ={ .items..metadata.name } ) ; do kubectl exec -ti $pod -n $JANS_NAMESPACE -- mkdir -p /deploy/interception-scripts-ksync done Install ksync curl https://ksync.github.io/gimme-that/gimme.sh | bash Initialize ksync ksync init -n <jans-namespace> Start ksync. ksync watch -n <jans-namespace> & Open a new terminal and create a folder called interception-scripts-ksync mkdir -p $( pwd ) /interception-scripts-ksync Create a spec to start syncing folders between the local system and auth server container. ksync create --selector = APP_NAME = auth-server $( pwd ) /interception-scripts-ksync /deploy/interception-scripts-ksync -n <jans-namespace> Check the status. Also check the terminal where the watch command is running. ksync get 1. Move the interception script to the local folder $(pwd)/interception-scripts-ksync . In the below example we copied the following script as basic.py : # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2016, Janssen # # Author: Yuriy Movchan # from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper import java class PersonAuthentication ( PersonAuthenticationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Basic. Initialization\" print \"Basic. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Basic. Destroy\" print \"Basic. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 def isValidAuthenticationMethod ( self , usageType , configurationAttributes ): return True def getAlternativeAuthenticationMethod ( self , usageType , configurationAttributes ): return None def authenticate ( self , configurationAttributes , requestParameters , step ): authenticationService = CdiUtil . bean ( AuthenticationService ) if ( step == 1 ): print \"Basic. Authenticate for step 1\" identity = CdiUtil . bean ( Identity ) credentials = identity . getCredentials () user_name = credentials . getUsername () user_password = credentials . getPassword () logged_in = False if ( StringHelper . isNotEmptyString ( user_name ) and StringHelper . isNotEmptyString ( user_password )): logged_in = authenticationService . authenticate ( user_name , user_password ) if ( not logged_in ): return False return True else : return False def prepareForStep ( self , configurationAttributes , requestParameters , step ): if ( step == 1 ): print \"Basic. Prepare for Step 1\" return True else : return False def getExtraParametersForStep ( self , configurationAttributes , step ): return None def getCountAuthenticationSteps ( self , configurationAttributes ): return 1 def getPageForStep ( self , configurationAttributes , step ): return \"\" def getNextStep ( self , configurationAttributes , requestParameters , step ): return - 1 def getLogoutExternalUrl ( self , configurationAttributes , requestParameters ): print \"Get external logout URL call\" return None def logout ( self , configurationAttributes , requestParameters ): return True", "title": "Install Ksync"}, {"location": "script-catalog/introspection/interception-scripts-debug/#install-an-ide", "text": "The IDE can be of choice but must contain PyDev. We chose Liclipse for this demonstration. Once complete, start the PyDev debug server: Open Liclipse Install the jython jar for the interpreter. wget https://repo1.maven.org/maven2/org/python/jython-standalone/2.7.2/jython-standalone-2.7.2.jar From the menu: go to File -> Open File and choose the interception script that will be debugged in $(pwd)/interception-scripts-ksync . When opening the Python file for the first time, we need to instruct Liclipse to use a specific interpreter. Follow these steps: Press the \"Manual Config\" button in the dialog box after opening the Python file Open \"PyDev->Interpreters->Jython Interpreters\" Click the \"New...\" button in the right panel. Name it \"Jython\" and specify the interpreter executable that was downloaded previously \"jython-standalone-2.7.2.jar\" Click \"OK\", then confirm the settings by clicking \"OK\" again, then \"Apply and Close\" In the final dialog, confirm the settings by clicking \"OK\" From the menu: go to Window -> Perspective -> Open Perspective -> Other.. -> Debug From the menu: go to Pydev > Start Debug Server . Now the server should have started at port 5678 . Take a note of the ip of the computer running Liclipse and save it for later use. Remember that the auth server pod must be able to communicate with this ip. If you have followed the instructions above and installed minikube on your local computer which is the same computer Liclipse is operating on you should be able to reach it from within the pods.", "title": "Install an IDE"}, {"location": "script-catalog/introspection/interception-scripts-debug/#development-debugging", "text": "Now we are ready to perform script development and debugging. Here is a quick overview: Enable remote debugging on the jans-auth service. Instruct the auth server to load the script from the file system instead of LDAP. Add debug instructions to the script. Execute the script.", "title": "Development & Debugging"}, {"location": "script-catalog/introspection/interception-scripts-debug/#enable-remote-debugging-in-jans-auth", "text": "In order to enable remote debugging in the jans-auth process, open /etc/default/jans-auth in your favorite text editor. The default JAVA_OPTIONS variable is as follows: JAVA_OPTIONS=\"-server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base=/etc/jans -Dserver.base=/opt/jans/jetty/jans-auth -Dlog.base=/opt/jans/jetty/jans-auth -Dpython.home=/opt/jython\" Modify to this: JAVA_OPTIONS=\"-server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base=/etc/jans -Dserver.base=/opt/jans/jetty/jans-auth -Dlog.base=/opt/jans/jetty/jans-auth -Dpython.home=/opt/jython -Dorg.eclipse.jetty.server.Request.maxFormContentSize=50000000 -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005\" The last line will enable remote debug on port 5005. Now restart the jans-auth service. # To list all jans processes systemctl list-units --all \"jans*\" # On Ubuntu, the service name is jans-auth.service systemctl restart jans-auth.service If you are running Jans on a local VM or anywhere that is not the same as the machine that will be debugging, you will need to set up an SSH tunnel on port 5005. Execute the following command: ssh -L 5005:localhost:5005 <username>@<host> This will cause your local host's port 5005 to listen on the remote server's port 5005. Now you can use your favorite IDE and set up the remote debugger to connect to localhost:5005 .", "title": "Enable Remote Debugging in jans-auth"}, {"location": "script-catalog/introspection/interception-scripts-debug/#enable-remote-debug-in-jython-custom-script", "text": "For Jython scripts, we need additional steps to enable breakpoints. After the import section, add: REMOTE_DEBUG = True if REMOTE_DEBUG: try: import sys import pydevd except ImportError as ex: print \"Failed to import pydevd: %s\" % ex raise Add the following lines wherever breakpoints are needed: if REMOTE_DEBUG: pydevd.settrace('localhost', port=5678, stdoutToServer=True, stderrToServer=True)", "title": "Enable remote debug in Jython Custom Script"}, {"location": "script-catalog/introspection/interception-scripts-debug/#sample-scenario", "text": "Copy the below script to $(pwd)/interception-scripts-ksync/basic.py # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2016, Janssen # # Author: Yuriy Movchan # from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper import java class PersonAuthentication ( PersonAuthenticationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Basic. Initialization\" print \"Basic. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Basic. Destroy\" print \"Basic. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 def isValidAuthenticationMethod ( self , usageType , configurationAttributes ): return True def getAlternativeAuthenticationMethod ( self , usageType , configurationAttributes ): return None def authenticate ( self , configurationAttributes , requestParameters , step ): authenticationService = CdiUtil . bean ( AuthenticationService ) if ( step == 1 ): print \"Basic. Authenticate for step 1\" identity = CdiUtil . bean ( Identity ) credentials = identity . getCredentials () user_name = credentials . getUsername () user_password = credentials . getPassword () logged_in = False if ( StringHelper . isNotEmptyString ( user_name ) and StringHelper . isNotEmptyString ( user_password )): logged_in = authenticationService . authenticate ( user_name , user_password ) if ( not logged_in ): return False return True else : return False def prepareForStep ( self , configurationAttributes , requestParameters , step ): if ( step == 1 ): print \"Basic. Prepare for Step 1\" return True else : return False def getExtraParametersForStep ( self , configurationAttributes , step ): return None def getCountAuthenticationSteps ( self , configurationAttributes ): return 1 def getPageForStep ( self , configurationAttributes , step ): return \"\" def getNextStep ( self , configurationAttributes , requestParameters , step ): return - 1 def getLogoutExternalUrl ( self , configurationAttributes , requestParameters ): print \"Get external logout URL call\" return None def logout ( self , configurationAttributes , requestParameters ): return True Make sure to have an LDAP browser available. We recommend Apache Directory Studio . Port forward the opendj pod. kubectl port-forward jans-opendj-0 -n <jans-namespace> 1636 :1636 --address 0 .0.0.0 Create a connection to the ldap browser. The default password will be Test1234# if not changed in the helm install command. Inside the browser navigate to o=jans, ou=scripts . Right click on ou=scripts and click on Quick Search . Inside the pop up box that appears fill Returning Attributes with displayName , and press Apply and Close In the results that appear click on the Dn that has a displayName of basic . Choose to load the script from file instead of ldap. Inside the browser change jansModuleProperty with value {\"value1\":\"location_type\",\"value2\":\"ldap\",\"description\":\"\"} to {\"value1\":\"location_type\",\"value2\":\"file\",\"description\":\"\"} Specify the Script Path location to the location of the folder inside auth server pods: /deploy/interception-scripts-ksync/basic.py . Right click the upper jansModuleProperty and click New Value . A new entry for jansModuleProperty will be created. Insert the following for the value: {\"value1\":\"location_path\",\"value2\":\"/deploy/interception-scripts-ksync/basic.py\",\"description\":\"\"} Enable the script by settings jansEnabled to true . The following is an example of how the basic script entry should look. Check the following log inside the the auth-server container to verify that auth server loaded the script properly: /opt/jans/jetty/jans-auth/logs/jans-auth_script.log . It should look like this: kubectl exec -ti <auth-server-pod-name> -n <jans-namespace> -- tail -f /opt/jans/jetty/jans-auth/logs/jans-auth_script.log You should find the following in the log: ... (PythonService.java:239) - Basic. Initialization ... (PythonService.java:239) - Basic. Initialized successfully Download the jython jar for the interpreter. wget https://repo1.maven.org/maven2/org/python/jython-standalone/2.7.2/jython-standalone-2.7.2.jar From the IDE (Liclipse) menu: navigate to File -> Open File and choose the interception script that will be debugged in $(pwd)/interception-scripts-ksync/basic.py When opening the Python file for the first time, we need to instruct Liclipse to use a specific interpreter. Follow these steps: Press the \"Manual Config\" button in the dialog box after opening the Python file Open \"PyDev->Interpreters->Jython Interpreters\" Click the \"New...\" button in the right panel. Name it \"Jython\" and specify the interpreter executable that was downloaded previously \"jython-standalone-2.7.2.jar\" Click \"OK\", then confirm the settings by clicking \"OK\" again, then \"Apply and Close\" In the final dialog, confirm the settings by clicking \"OK\" Open basic.py in a file editor. After the import section, add the following lines to load the PyDev libraries: REMOTE_DEBUG = True if REMOTE_DEBUG: try: import sys import pydevd except ImportError as ex: print \"Failed to import pydevd: %s\" % ex raise Add this break condition to the first line in the authenticate method. Place the ip of the maching running the ide , here liclipse i.e 192.168.140.2 . if REMOTE_DEBUG: pydevd.settrace ( '<ip-of-machine-running-ide>' , port = 5678 , stdoutToServer = True, stderrToServer = True ) Save basic.py Within one minute, the auth server should load the changed file. Check the following log file again to make sure there are no load errors: /opt/jans/jetty/jans-auth/logs/jans-auth_script.log To check if the script works, update the default authentication method to Basic Authentication. Preform this in the LDAP browser. Navigate to o=jans,ou=configuration . Change the jansAuthMode to basic instead of simple_password_auth . After executing pydevd.settrace the script will transfer execution control to the PyDev server in Liclipse. You can use any debug commands. For example: Step Over (F6), Resume (F8), etc After debugging is finished, resume script execution to transfer execution control back to the auth server.", "title": "Sample Scenario"}, {"location": "script-catalog/introspection/introspection/", "tags": ["administration", "developer", "script-catalog", "Introspection"], "text": "Introspection Script Guide # Overview # In OAuth 2.0 [RFC6749], the contents of tokens are opaque to clients. However, there is still a large amount of metadata that may be attached to a token, such as its current validity, approved scopes, and information about the context in which the token was issued. These pieces of information are often vital to protected resources making authorization decisions based on the tokens being presented. Token introspection allows a protected resource to query this information. Introspection scripts allows to modify response of Introspection Endpoint spec and present additional meta information surrounding the token. Interface # Introspection script should be associated with client (used for obtaining the token) in order to be run. Otherwise it's possible to set introspectionScriptBackwardCompatibility global AS configuration property to true, in this case AS will run all scripts (ignoring client configuration). Methods # The introspection interception script extends the base script type with the init , destroy and getApiVersion methods: Inherited Methods Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . The introspection interception script also adds the following method(s): Method def modifyResponse(self, responseAsJsonObject, context) Method Paramater responseAsJsonObject is org.codehaus.jettison.json.JSONObject context is io.jans.as.service.external.context.ExternalIntrospectionContext Snippet # # Returns boolean , true - apply introspection method , false - ignore it . # This method is called after introspection response is ready . This method can modify introspection response . # Note : # responseAsJsonObject - is org . codehaus . jettison . json . JSONObject , you can use any method to manipulate json # context is reference of io . jans . as . server . service . external . context . ExternalIntrospectionContext ( in https : // github . com / JanssenProject project ) def modifyResponse ( self , responseAsJsonObject , context ) : responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True It is also possible to run introspection script during access_token creation as JWT. It can be controlled by run_introspection_script_before_jwt_creation client property which is set to false by default. If run_introspection_script_before_jwt_creation set to true and access_token_as_jwt set to true then introspection script will be run before JWT ( access_token ) is created and all JSON values will be transfered to JWT. Also context inside script has additional method which allows to cancel transfering of claims if needed context.setTranferIntrospectionPropertiesIntoJwtClaims(false) Common Use Cases # Script Type: Python # Retrieve Grant, Session and User Details from Access Token # Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. from io.jans.model.custom.script.type.introspection import IntrospectionType from io.jans.as.server.service import SessionIdService from io.jans.service.cdi.util import CdiUtil class Introspection ( IntrospectionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Introspection script. Initializing ...\" print \"Introspection script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Introspection script. Destroying ...\" print \"Introspection script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply introspection method, false - ignore it. # This method is called after introspection response is ready. This method can modify introspection response. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.server.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenProject project, ) def modifyResponse ( self , responseAsJsonObject , context ): authorizationGrant = context . getTokenGrant () if authorizationGrant is None : print \"Introspection. Failed to load authorization grant by context\" return False # Put user_id into response responseAsJsonObject . accumulate ( \"user_id\" , authorizationGrant . getUser () . getUserId ()) # Put custom parameters into response sessionDn = authorizationGrant . getSessionDn () if sessionDn is None : # There is no session print \"Introspection. Failed to load session DN\" return True # Return session_id responseAsJsonObject . accumulate ( \"session_id\" , sessionDn ) sessionIdService = CdiUtil . bean ( SessionIdService ) session = sessionIdService . getSessionById ( sessionDn , False ) if session is None : print \"Introspection. Failed to load session ' %s '\" % sessionDn return True sessionAttributes = session . getSessionAttributes () if sessionAttributes is None : # There is no session attributes return True # Append custom claims if sessionAttributes . containsKey ( \"custom1\" ): responseAsJsonObject . accumulate ( \"custom1\" , sessionAttributes . get ( \"custom1\" )) if sessionAttributes . containsKey ( \"custom2\" ): responseAsJsonObject . accumulate ( \"custom2\" , sessionAttributes . get ( \"custom2\" )) return True Script Type: Java # Retrieve Grant, Session and User Details from Access Token # Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.introspection.IntrospectionType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.ExternalIntrospectionContext ; import io.jans.as.server.model.common.AuthorizationGrant ; import io.jans.as.server.service.SessionIdService ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.as.server.model.common.SessionId ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import org.json.JSONObject ; import java.util.Map ; public class Introspection implements IntrospectionType { private static final Logger log = LoggerFactory . getLogger ( Introspection . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Introspection Java custom script\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Introspection Java custom script\" ); scriptLogger . info ( \"Introspection Java script. Initializing ...\" ); scriptLogger . info ( \"Introspection Java script. Initialized successfully\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Destroy of Introspection Java custom script\" ); scriptLogger . info ( \"Introspection Java script. Destroying ...\" ); scriptLogger . info ( \"Introspection Java script. Destroyed successfully\" ); return true ; } @Override public int getApiVersion () { return 11 ; } // Returns boolean , true - apply introspection method , false - ignore it . // This method is called after introspection response is ready . This method can modify introspection response . // Note : // responseAsJsonObject - is org . json . JSONObject , you can use any method to manipulate json // context is reference of io . jans . as . server . service . external . context . ExternalIntrospectionContext ( in https : // github . com / JanssenProject project , ) @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { JSONObject response = ( JSONObject ) responseAsJsonObject ; ExternalIntrospectionContext ctx = ( ExternalIntrospectionContext ) context ; response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); AuthorizationGrant authorizationGrant = ctx . getTokenGrant (); if ( authorizationGrant == null ) { scriptLogger . info ( \"Introspection Java script. Failed to load authorization grant by context\" ); return false ; } // Put user_id into response response . accumulate ( \"user_id\" , authorizationGrant . getUser () . getUserId ()); // Put custom parameters into response String sessionDn = authorizationGrant . getSessionDn (); if ( sessionDn == null ) { // There is no session scriptLogger . info ( \"Introspection Java script. Failed to load session DN\" ); return true ; } // Return session_id response . accumulate ( \"session_id\" , sessionDn ); SessionIdService sessionIdService = CdiUtil . bean ( SessionIdService . class ); SessionId session = sessionIdService . getSessionById ( sessionDn , false ); if ( session == null ) { scriptLogger . info ( \"Introspection Java script. Failed to load session\" ); return true ; } Map < String , String > sessionAttributes = session . getSessionAttributes (); if ( sessionAttributes == null ) { // There is no session attributes return true ; } // Append custom claims if ( sessionAttributes . containsKey ( \"custom1\" )) { response . accumulate ( \"custom1\" , sessionAttributes . get ( \"custom1\" )); } if ( sessionAttributes . containsKey ( \"custom2\" )) { response . accumulate ( \"custom2\" , sessionAttributes . get ( \"custom2\" )); } return true ; } }", "title": "Introspection"}, {"location": "script-catalog/introspection/introspection/#introspection-script-guide", "text": "", "title": "Introspection Script Guide"}, {"location": "script-catalog/introspection/introspection/#overview", "text": "In OAuth 2.0 [RFC6749], the contents of tokens are opaque to clients. However, there is still a large amount of metadata that may be attached to a token, such as its current validity, approved scopes, and information about the context in which the token was issued. These pieces of information are often vital to protected resources making authorization decisions based on the tokens being presented. Token introspection allows a protected resource to query this information. Introspection scripts allows to modify response of Introspection Endpoint spec and present additional meta information surrounding the token.", "title": "Overview"}, {"location": "script-catalog/introspection/introspection/#interface", "text": "Introspection script should be associated with client (used for obtaining the token) in order to be run. Otherwise it's possible to set introspectionScriptBackwardCompatibility global AS configuration property to true, in this case AS will run all scripts (ignoring client configuration).", "title": "Interface"}, {"location": "script-catalog/introspection/introspection/#methods", "text": "The introspection interception script extends the base script type with the init , destroy and getApiVersion methods: Inherited Methods Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . The introspection interception script also adds the following method(s): Method def modifyResponse(self, responseAsJsonObject, context) Method Paramater responseAsJsonObject is org.codehaus.jettison.json.JSONObject context is io.jans.as.service.external.context.ExternalIntrospectionContext", "title": "Methods"}, {"location": "script-catalog/introspection/introspection/#snippet", "text": "# Returns boolean , true - apply introspection method , false - ignore it . # This method is called after introspection response is ready . This method can modify introspection response . # Note : # responseAsJsonObject - is org . codehaus . jettison . json . JSONObject , you can use any method to manipulate json # context is reference of io . jans . as . server . service . external . context . ExternalIntrospectionContext ( in https : // github . com / JanssenProject project ) def modifyResponse ( self , responseAsJsonObject , context ) : responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True It is also possible to run introspection script during access_token creation as JWT. It can be controlled by run_introspection_script_before_jwt_creation client property which is set to false by default. If run_introspection_script_before_jwt_creation set to true and access_token_as_jwt set to true then introspection script will be run before JWT ( access_token ) is created and all JSON values will be transfered to JWT. Also context inside script has additional method which allows to cancel transfering of claims if needed context.setTranferIntrospectionPropertiesIntoJwtClaims(false)", "title": "Snippet"}, {"location": "script-catalog/introspection/introspection/#common-use-cases", "text": "", "title": "Common Use Cases"}, {"location": "script-catalog/introspection/introspection/#script-type-python", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/introspection/introspection/#retrieve-grant-session-and-user-details-from-access-token", "text": "Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. from io.jans.model.custom.script.type.introspection import IntrospectionType from io.jans.as.server.service import SessionIdService from io.jans.service.cdi.util import CdiUtil class Introspection ( IntrospectionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Introspection script. Initializing ...\" print \"Introspection script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Introspection script. Destroying ...\" print \"Introspection script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply introspection method, false - ignore it. # This method is called after introspection response is ready. This method can modify introspection response. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.server.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenProject project, ) def modifyResponse ( self , responseAsJsonObject , context ): authorizationGrant = context . getTokenGrant () if authorizationGrant is None : print \"Introspection. Failed to load authorization grant by context\" return False # Put user_id into response responseAsJsonObject . accumulate ( \"user_id\" , authorizationGrant . getUser () . getUserId ()) # Put custom parameters into response sessionDn = authorizationGrant . getSessionDn () if sessionDn is None : # There is no session print \"Introspection. Failed to load session DN\" return True # Return session_id responseAsJsonObject . accumulate ( \"session_id\" , sessionDn ) sessionIdService = CdiUtil . bean ( SessionIdService ) session = sessionIdService . getSessionById ( sessionDn , False ) if session is None : print \"Introspection. Failed to load session ' %s '\" % sessionDn return True sessionAttributes = session . getSessionAttributes () if sessionAttributes is None : # There is no session attributes return True # Append custom claims if sessionAttributes . containsKey ( \"custom1\" ): responseAsJsonObject . accumulate ( \"custom1\" , sessionAttributes . get ( \"custom1\" )) if sessionAttributes . containsKey ( \"custom2\" ): responseAsJsonObject . accumulate ( \"custom2\" , sessionAttributes . get ( \"custom2\" )) return True", "title": "Retrieve Grant, Session and User Details from Access Token"}, {"location": "script-catalog/introspection/introspection/#script-type-java", "text": "", "title": "Script Type: Java"}, {"location": "script-catalog/introspection/introspection/#retrieve-grant-session-and-user-details-from-access-token_1", "text": "Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.introspection.IntrospectionType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.ExternalIntrospectionContext ; import io.jans.as.server.model.common.AuthorizationGrant ; import io.jans.as.server.service.SessionIdService ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.as.server.model.common.SessionId ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import org.json.JSONObject ; import java.util.Map ; public class Introspection implements IntrospectionType { private static final Logger log = LoggerFactory . getLogger ( Introspection . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Introspection Java custom script\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Introspection Java custom script\" ); scriptLogger . info ( \"Introspection Java script. Initializing ...\" ); scriptLogger . info ( \"Introspection Java script. Initialized successfully\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Destroy of Introspection Java custom script\" ); scriptLogger . info ( \"Introspection Java script. Destroying ...\" ); scriptLogger . info ( \"Introspection Java script. Destroyed successfully\" ); return true ; } @Override public int getApiVersion () { return 11 ; } // Returns boolean , true - apply introspection method , false - ignore it . // This method is called after introspection response is ready . This method can modify introspection response . // Note : // responseAsJsonObject - is org . json . JSONObject , you can use any method to manipulate json // context is reference of io . jans . as . server . service . external . context . ExternalIntrospectionContext ( in https : // github . com / JanssenProject project , ) @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { JSONObject response = ( JSONObject ) responseAsJsonObject ; ExternalIntrospectionContext ctx = ( ExternalIntrospectionContext ) context ; response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); AuthorizationGrant authorizationGrant = ctx . getTokenGrant (); if ( authorizationGrant == null ) { scriptLogger . info ( \"Introspection Java script. Failed to load authorization grant by context\" ); return false ; } // Put user_id into response response . accumulate ( \"user_id\" , authorizationGrant . getUser () . getUserId ()); // Put custom parameters into response String sessionDn = authorizationGrant . getSessionDn (); if ( sessionDn == null ) { // There is no session scriptLogger . info ( \"Introspection Java script. Failed to load session DN\" ); return true ; } // Return session_id response . accumulate ( \"session_id\" , sessionDn ); SessionIdService sessionIdService = CdiUtil . bean ( SessionIdService . class ); SessionId session = sessionIdService . getSessionById ( sessionDn , false ); if ( session == null ) { scriptLogger . info ( \"Introspection Java script. Failed to load session\" ); return true ; } Map < String , String > sessionAttributes = session . getSessionAttributes (); if ( sessionAttributes == null ) { // There is no session attributes return true ; } // Append custom claims if ( sessionAttributes . containsKey ( \"custom1\" )) { response . accumulate ( \"custom1\" , sessionAttributes . get ( \"custom1\" )); } if ( sessionAttributes . containsKey ( \"custom2\" )) { response . accumulate ( \"custom2\" , sessionAttributes . get ( \"custom2\" )); } return true ; } }", "title": "Retrieve Grant, Session and User Details from Access Token"}, {"location": "script-catalog/introspection/introspection/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Index"}, {"location": "script-catalog/introspection/introspection/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/introspection/introspection/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/introspection/introspection/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/persistence_extension/persistence/", "tags": ["administration", "developer", "script-catalog", "Hashed Passwords", "Entry manager", "Persistence Extension"], "text": "Persistence Script # By overriding the interface methods in PersistenceType inside a custom script you can Load initialization data from DB or initialize services after the creation of Entry Manager. Release resources, terminate services etc. after the destruction of Entry Manager. Create hashed passwords Compare hashed passwords What is an Entry Manager? The Janssen server's Peristence Layer can be MySQL database. Information about an entity (person, session, client, scripts etc) constitutes an Entry. The Entry Manager (CRUD operations) implementation for each type of Persistence is available in the Janssen server and the relevant Entry Manager (SQLEntryManager, etc.) is created when the server starts up. Usage # The Jans-Auth server contains a PeristenceType script. Hashed Passwords # Hashed passwords can be created using any method from this enum , instead of the native/default SSHA256. The ORM module of the Janssen server does the following: When User entry is persisted and userPassword is specified, ORM calls createHashedPassword User authenticates and the password is checked, the ORM module invokes compareHashedPasswords We need to specify which one to use in /etc/gluu/conf/jans-couchbase.properties password.encryption.method: SSHA-256 Implementation createHashedPassword and compareHashedPasswords the script: Creation def createHashedPassword(self, credential): hashed_password= PasswordEncryptionHelper.createStoragePassword(credential, PasswordEncryptionMethod.HASH_METHOD_PKCS5S2) return hashed_password Comparing Hashed Password: def compareHashedPasswords(self, credential, storedCredential): auth_result = PasswordEncryptionHelper.compareCredentials(credential, storedCredential) return auth_result Script Type: Python # Retrieve Grant, Session and User Details from Access Token # Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. from io.jans.service.cdi.util import CdiUtil from io.jans.model.custom.script.type.persistence import PersistenceType from io.jans.util import StringHelper from io.jans.persist.operation.auth import PasswordEncryptionHelper from io.jans.persist.operation.auth import PasswordEncryptionMethod import java class PersistenceExtension ( PersistenceType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Persistence extension. Initialization\" return True def destroy ( self , configurationAttributes ): print \"Persistence extension. Destroy\" return True def getApiVersion ( self ): return 11 def onAfterCreate ( self , context , configurationAttributes ): print \"Persistence extension. Method: onAfterCreate\" def onAfterDestroy ( self , context , configurationAttributes ): print \"Persistence extension. Method: onAfterDestroy\" def createHashedPassword ( self , credential ): print \"Persistence extension. Method: createHashedPassword\" hashed_password = PasswordEncryptionHelper . createStoragePassword ( credential , PasswordEncryptionMethod . HASH_METHOD_PKCS5S2 ) return hashed_password def compareHashedPasswords ( self , credential , storedCredential ): print \"Persistence extension. Method: compareHashedPasswords\" auth_result = PasswordEncryptionHelper . compareCredentials ( credential , storedCredential ) return auth_result", "title": "Persistence"}, {"location": "script-catalog/persistence_extension/persistence/#persistence-script", "text": "By overriding the interface methods in PersistenceType inside a custom script you can Load initialization data from DB or initialize services after the creation of Entry Manager. Release resources, terminate services etc. after the destruction of Entry Manager. Create hashed passwords Compare hashed passwords What is an Entry Manager? The Janssen server's Peristence Layer can be MySQL database. Information about an entity (person, session, client, scripts etc) constitutes an Entry. The Entry Manager (CRUD operations) implementation for each type of Persistence is available in the Janssen server and the relevant Entry Manager (SQLEntryManager, etc.) is created when the server starts up.", "title": "Persistence Script"}, {"location": "script-catalog/persistence_extension/persistence/#usage", "text": "The Jans-Auth server contains a PeristenceType script.", "title": "Usage"}, {"location": "script-catalog/persistence_extension/persistence/#hashed-passwords", "text": "Hashed passwords can be created using any method from this enum , instead of the native/default SSHA256. The ORM module of the Janssen server does the following: When User entry is persisted and userPassword is specified, ORM calls createHashedPassword User authenticates and the password is checked, the ORM module invokes compareHashedPasswords We need to specify which one to use in /etc/gluu/conf/jans-couchbase.properties password.encryption.method: SSHA-256 Implementation createHashedPassword and compareHashedPasswords the script: Creation def createHashedPassword(self, credential): hashed_password= PasswordEncryptionHelper.createStoragePassword(credential, PasswordEncryptionMethod.HASH_METHOD_PKCS5S2) return hashed_password Comparing Hashed Password: def compareHashedPasswords(self, credential, storedCredential): auth_result = PasswordEncryptionHelper.compareCredentials(credential, storedCredential) return auth_result", "title": "Hashed Passwords"}, {"location": "script-catalog/persistence_extension/persistence/#script-type-python", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/persistence_extension/persistence/#retrieve-grant-session-and-user-details-from-access-token", "text": "Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. from io.jans.service.cdi.util import CdiUtil from io.jans.model.custom.script.type.persistence import PersistenceType from io.jans.util import StringHelper from io.jans.persist.operation.auth import PasswordEncryptionHelper from io.jans.persist.operation.auth import PasswordEncryptionMethod import java class PersistenceExtension ( PersistenceType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Persistence extension. Initialization\" return True def destroy ( self , configurationAttributes ): print \"Persistence extension. Destroy\" return True def getApiVersion ( self ): return 11 def onAfterCreate ( self , context , configurationAttributes ): print \"Persistence extension. Method: onAfterCreate\" def onAfterDestroy ( self , context , configurationAttributes ): print \"Persistence extension. Method: onAfterDestroy\" def createHashedPassword ( self , credential ): print \"Persistence extension. Method: createHashedPassword\" hashed_password = PasswordEncryptionHelper . createStoragePassword ( credential , PasswordEncryptionMethod . HASH_METHOD_PKCS5S2 ) return hashed_password def compareHashedPasswords ( self , credential , storedCredential ): print \"Persistence extension. Method: compareHashedPasswords\" auth_result = PasswordEncryptionHelper . compareCredentials ( credential , storedCredential ) return auth_result", "title": "Retrieve Grant, Session and User Details from Access Token"}, {"location": "script-catalog/person_authentication/person-authentication/", "tags": ["administration", "developer", "script-catalog", "acr_values_supported", "2FA", "PersonAuthenticationType", "acr", "weld"], "text": "Person Authentication scripts # The Janssen Server leverages interception scripts of PersonAuthenticationType which when implemented can facilitate complex multi-step, multi-factor authentication workflows. The authentication flow in the Janssen Server is driven by the OpenID Connect specification . The authorization request to the OP (the Janssen Server) contains an optional query parameter called acr_values which is used by the OP to pick an interception script which will be run when /authorize endpoint (Authentication flow) is invoked. Each authentication method, whose name is the acr value, is tied to a PersonAuthenticationType script which offers the authentication workflow. Typically, a PersonAuthenticationType script can be used to: Introduce a new 2FA authentication mechanism Customize multi-step authentication Offer Social logins Proactively perform fraud detection and block a fraudulent user Authentication mechanisms offered by Jans can be confirmed by checking the Janssen Server OP configuration URL: https://<hostname>/.well-known/openid-configuration under the claim acr_values_supported . Building blocks of an authentication workflow # Jans-auth server comprises of a number of beans, configuration files and Facelets (JSF) views, packaged as a WAR module. That means custom scripts and custom pages (JSF facelets) can make use of business logic already encapsulated in the Weld managed beans. The following sections explain how authentication flow can be built using a custom script. A. Custom script # The PersonAuthenticationType script is described by a java interface whose methods should be overridden to implement an authentication workflow. The article talks about these methods in detail and the psuedo code for each method. B. UI pages: # All web pages are xhtml files. The Command-Action offering by JSF framework is used by the Jans-auth server to implement authentication flows. a. Server-side actions implemented by custom script: # The custom script's authenticate and prepareForStep implementations are called by the following java class - Authenticator . These methods are mapped as command actions and view actions respectively in the web page. Relevant methods: Signature Description boolean authenticate() Makes the authentication flow proceed by calling the authenticate method of the custom script String prepareAuthenticationForStep() Makes the authentication flow proceed by calling the prepareForStep method of the custom script b. Web page in xhtml: # The f:metadata and f:viewAction tags are used to load variables (prepared in the prepareForStep method of the custom script). These variables are rendered on the UI page. <f:metadata> <f:viewAction action=\"#{authenticator.prepareAuthenticationForStep}\" if=\"#{not identity.loggedIn}\" /> </f:metadata> A form submit takes the flow to the authenticate() method of the custom script. <h:commandButton id=\"updateButton\" value=\"Update\" styleClass=\"btn btn-primary col-sm-4\" action=\"#{authenticator.authenticate}\" style=\"margin:5px;\" /> c. Page customizations: # The Jans-auth server comes with a default set of pages for login, logout, errors, authorizations. You can easily override these pages or write new ones. You can easily apply your own stylesheet, images and resouce-bundles to your pages. This article covers all the details you need to write your own web page. C. Business logic in Custom script: # Jans-auth server uses Weld 3.0 (JSR-365 aka CDI 2.0) for managed beans. The most important aspects of business logic are implemented through a set of beans. Details and examples of this can be found in this article D. Third party libraries for use in the custom script # Java or Python libraries to be imported and used very easily. Remember, you can import a python library only if it has been written in \"pure python\". More details of this mentioned here E. Configuring the acr parameter in the Jans-auth server: # The acr parameter can be configured in the following ways : Default authentication method: # default_acr : This is the default authentication mechanism exposed to all applications that send users to the Janssen Server for sign-in. Unless an app specifically requests a different form of authentication using the OpenID Connect acr_values parameter (as specified below), users will receive the form of authentication specified in this field. Internal ACR # If a default ACR is not specified, Janssen will determine it based on enabled scripts and the internal user/password ACR. This internal ACR, simple_password_auth , is set to level -1. This means that it has lower priority than any scripts, so Janssen server will use it only if no other authentication method is set. Use the jans-cli to update / look-up the default authentication method . Authentication method for a client (RP): # A client may also specify default_acr_values during registration (and omit the parameter acr_values while making an authentication request). Multiple Authentication Mechanisms # The Jans Server can concurrently support multiple authentication mechanisms, enabling Web and mobile apps (clients) to request a specific type of authentication using the standard OpenID Connect request parameter: acr_values . Learn more about acr_values in the OpenID Connect core spec . Enabling an authentication mechanism # An Authentication method is offered by the AS if its ACR value i.e. its corresponding custom script is enabled . By default, users will get the default authentication mechanism as specified above. However, using the OpenID Connect acr_values parameter, web and mobile clients can request any enabled authentication mechanism . Obtain the json contents of a custom script by using a jans-cli command like get-config-scripts-by-type , get-config-scripts-by-inum etc. Example : /opt/jans/jans-cli/config-cli.py --operation-id get-config-scripts-by-type --url-suffix type:PERSON_AUTHENTICATION /opt/jans/jans-cli/config-cli.py --operation-id get-config-scripts-by-inum --url-suffix inum:6122281b-b55d-4dd0-8115-b098eeeee2b7 Update the custom script and change the enabled attribute to true Level (rank) of an Authentication mechanism : # Each authentication mechanism (script) has a \"Level\" assigned to it which describes how secure and reliable it is. The higher the \"Level\", higher is the reliability represented by the script. Though several mechanisms can be enabled at the same Janssen server instance at the same time, for any specific user's session only one of them can be set as the current one (and will be returned as acr claim of id_token for them). If after initial session is created a new authorization request from a RP comes in specifying another authentication method, its \"Level\" will be compared to that of the method currently associated with this session. If requested method's \"Level\" is lower or equal to it, nothing is changed and the usual SSO behavior is observed. If it's higher (i.e. a more secure method is requested), it's not possible to serve such request using the existing session's context, and user must re-authenticate themselves to continue. If they succeed, a new session becomes associated with that requested mechanism instead. F. Using person authenticator jansAuthenticator attribute : # The jansAuthenticator attribute can be used in cases when person authenticator need to persist data between person logins. For example script can have enrollment and authentication flows. And after enrollment it needs to store data into user entry for later use in authentication flow. In order to search by enrolled authenticator there is another multi-valued attribute jansExtUid . This attribute has default DB index to quick search. Both attributes is recommended to use In Jans since 1.1.1 version for better compatibility in future. 1. Format of attributes # jansExtUid: [otp:xyz1, cert:xyz2, duo:xyz3, ...] jansAuthenticator: { \"xyz1\": {\"id\": \"xyz1\", \"type\": \"otp\", \"custom\": {...}}, \"xyz2\": {\"id\": \"xyz2\", \"type\": \"cert\", \"custom\": {...}}, \"xyz3\": {\"id\": \"xyz3\", \"type\": \"duo\", \"custom\": {...}}, ... } 2. Sample data: # jansExtUid: [hotp:S9dO_qKQoOcpPk9GuStlNO9seoA=, cert:totp, duo:Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=] jansAuthenticator: { \"S9dO_qKQoOcpPk9GuStlNO9seoA=\": { \"id\": \"S9dO_qKQoOcpPk9GuStlNO9seoA=\", \"type\": \"hotp\", \"custom\": { \"movingFactor\": 3 } }, \"Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=\": { \"id\": \"Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=\", \"type\": \"totp\" } } 2. Access jansAuthenticator and jansExtUid from generic bean # For both attributes there are get/set methods in User entry. After loading user object script can call these methods to get required data. ... @AttributeName(name = \"jansExtUid\") private String[] externalUid; @JsonObject @AttributeName(name = \"jansAuthenticator\") private UserAuthenticatorList authenticator ... public String[] getExternalUid() { return externalUid; } public void setExternalUid(String[] externalUid) { this.externalUid = externalUid; } public UserAuthenticatorList getAuthenticator() { return authenticator; } public void setAuthenticator(UserAuthenticatorList authenticator) { this.authenticator = authenticator; } ... UserAuthenticatorList is defined here . It contains list of UserAuthenticator objects. UserAuthenticator is defined here For convenience in 1.1.1 there is new service UserAuthenticator . See it's code here It provides next API methods: public UserAuthenticatorList getUserAuthenticatorList(SimpleUser user); public List<UserAuthenticator> getUserAuthenticatorsByType(SimpleUser user, String type); public UserAuthenticator getUserAuthenticatorById(SimpleUser user, String id); public void addUserAuthenticator(SimpleUser user, UserAuthenticator userAuthenticator); public void removeUserAuthenticator(SimpleUser user, UserAuthenticator userAuthenticator); public void removeUserAuthenticator(SimpleUser user, String type); public UserAuthenticator createUserAuthenticator(String id, String type); public UserAuthenticator createUserAuthenticator(String id, String type, Map<String, Object> custom); public String formatExternalUid(String id, String type); public boolean checkAndMigrateToAuthenticatorList(SimpleUser user); All these methods update both jansAuthenticator and jansExtUid attributes without persisting changes to DB. After calling these methods script should persist user entry. It's expected behaviour because script might update other fields too. Hence it's better to persist all changes in one update request to DB. 1. Default authentication method: # default_acr : This is the default authentication mechanism exposed to all applications that send users to the Janssen Server for sign-in. Unless an app specifically requests a different form of authentication using the OpenID Connect acr_values parameter (as specified below), users will receive the form of authentication specified in this field. Usage scenarios # A. Implementing 2FA authentication mechanisms # FIDO2 : Authentications using platform authenticators embedded into a person's device or physical USB, NFC or Bluetooth security keys that are inserted into a USB slot of a computer OTP authentication : Authentication mechanism using an app like Google authenticator , FreeOTP or Authy that implements the open standards HOTP and TOTP SMS OTP : Email OTP: B. Implementing Multistep authentication # Redirect to previous step : The script here an example of how the number of steps can be varied depending on the context or business requirement. C. Implementing Social logins # You can use a PersonAuthenticationType script to allow users to sign using credentials from popular Social Identity providers or Inbound Identity Providers like Facebook, Google and Apple. After users authenticate, thier Social Identity Provider credentials are provisioned into the Jans-auth server. More on this topic in this article D. Proactively perform fraud detection # Impossible travel Testing an authentication flow # An example of a complete URL looks like this - ``` https://<your.jans.server>/jans-auth/authorize.htm? \\ response_type=code&redirect_uri=https://<your.jans.server>/admin \\ &client_id=17b8b82e-b3ec-42a2-bd90-097028a37f3 \\ &scope=openid+profile+email+user_name \\ &state=faad2cdjfdddjfkdf&nonce=dajdffdfsdcfff ``` To test , enter the complete URL for authorization in a browser or create a simple webmapage with a link that simulates the user sign-in attempt. If the server is configured properly, the first page for the selected authentication method will be displayed to the user. FAQs # 1. How can error messages be displayed on a web page? # FacesMessage bean is used for this purpose. from org.jans.jsf2.message import FacesMessages from org.jans.service.cdi.util import CdiUtil from javax.faces.application import FacesMessage ... facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Please enter a valid username\") The error will appear in the associated template using the following markup: ... <h:messages /> ... See an example here 2. How is redirection to a third party application for authentication handled in a script? # For user authentication or consent gathering, there might be a need to redirect to a third party application to perform some operation and return the control back to authentication steps of the custom script. Please apply these steps to a person authentication script in such a scenario: Return from def getPageForStep(self, step, context), a page /auth/method_name/redirect.html ; with content similar to the code snippet below - def getPageForStep(self, step, context): return \"/auth/method_name/redirect.html\" Contents of redirect.xhtml should take the flow to prepareForStep method ... <f:metadata> <f:viewAction action=\"#{authenticator.prepareForStep}\" if=\"#{not identity.loggedIn}\" /> </f:metadata> In method prepareForStep prepare data needed for redirect and perform the redirection to the external service. def prepareForStep(self, step, context): ..... facesService = CdiUtil.bean(FacesService) facesService.redirectToExternalURL(third_party_URL ) return True In order to resume flow after the redirection, invoke a similar URL to https://my.gluu.server/postlogin.htm?param=123 from the third party app which takes the flow back to the authenticate method of the custom script. So create an xhtml page postlogin.xhtml which will look like this : <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> <html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:f=\"http://xmlns.jcp.org/jsf/core\"> <f:view transient=\"true\" contentType=\"text/html\"> <f:metadata> <f:viewAction action=\"#{authenticator.authenticateWithOutcome}\" /> </f:metadata> </f:view> </html> The <f:viewAction action=\"#{authenticator.authenticateWithOutcome}\" /> in step 4 takes us to the authenticate method inside the custom script def authenticate(self, configurationAttributes, requestParameters, step): . Here you can use parameters from request param = ServerUtil.getFirstValue(requestParameters, \"param-name\")) perform the state check (state : Opaque value used to maintain state between the request and the callback.) finally, return true or false from this method.", "title": "Person Authentication"}, {"location": "script-catalog/person_authentication/person-authentication/#person-authentication-scripts", "text": "The Janssen Server leverages interception scripts of PersonAuthenticationType which when implemented can facilitate complex multi-step, multi-factor authentication workflows. The authentication flow in the Janssen Server is driven by the OpenID Connect specification . The authorization request to the OP (the Janssen Server) contains an optional query parameter called acr_values which is used by the OP to pick an interception script which will be run when /authorize endpoint (Authentication flow) is invoked. Each authentication method, whose name is the acr value, is tied to a PersonAuthenticationType script which offers the authentication workflow. Typically, a PersonAuthenticationType script can be used to: Introduce a new 2FA authentication mechanism Customize multi-step authentication Offer Social logins Proactively perform fraud detection and block a fraudulent user Authentication mechanisms offered by Jans can be confirmed by checking the Janssen Server OP configuration URL: https://<hostname>/.well-known/openid-configuration under the claim acr_values_supported .", "title": "Person Authentication scripts"}, {"location": "script-catalog/person_authentication/person-authentication/#building-blocks-of-an-authentication-workflow", "text": "Jans-auth server comprises of a number of beans, configuration files and Facelets (JSF) views, packaged as a WAR module. That means custom scripts and custom pages (JSF facelets) can make use of business logic already encapsulated in the Weld managed beans. The following sections explain how authentication flow can be built using a custom script.", "title": "Building blocks of an authentication workflow"}, {"location": "script-catalog/person_authentication/person-authentication/#a-custom-script", "text": "The PersonAuthenticationType script is described by a java interface whose methods should be overridden to implement an authentication workflow. The article talks about these methods in detail and the psuedo code for each method.", "title": "A. Custom script"}, {"location": "script-catalog/person_authentication/person-authentication/#b-ui-pages", "text": "All web pages are xhtml files. The Command-Action offering by JSF framework is used by the Jans-auth server to implement authentication flows.", "title": "B. UI pages:"}, {"location": "script-catalog/person_authentication/person-authentication/#a-server-side-actions-implemented-by-custom-script", "text": "The custom script's authenticate and prepareForStep implementations are called by the following java class - Authenticator . These methods are mapped as command actions and view actions respectively in the web page. Relevant methods: Signature Description boolean authenticate() Makes the authentication flow proceed by calling the authenticate method of the custom script String prepareAuthenticationForStep() Makes the authentication flow proceed by calling the prepareForStep method of the custom script", "title": "a. Server-side actions implemented by custom script:"}, {"location": "script-catalog/person_authentication/person-authentication/#b-web-page-in-xhtml", "text": "The f:metadata and f:viewAction tags are used to load variables (prepared in the prepareForStep method of the custom script). These variables are rendered on the UI page. <f:metadata> <f:viewAction action=\"#{authenticator.prepareAuthenticationForStep}\" if=\"#{not identity.loggedIn}\" /> </f:metadata> A form submit takes the flow to the authenticate() method of the custom script. <h:commandButton id=\"updateButton\" value=\"Update\" styleClass=\"btn btn-primary col-sm-4\" action=\"#{authenticator.authenticate}\" style=\"margin:5px;\" />", "title": "b. Web page in xhtml:"}, {"location": "script-catalog/person_authentication/person-authentication/#c-page-customizations", "text": "The Jans-auth server comes with a default set of pages for login, logout, errors, authorizations. You can easily override these pages or write new ones. You can easily apply your own stylesheet, images and resouce-bundles to your pages. This article covers all the details you need to write your own web page.", "title": "c. Page customizations:"}, {"location": "script-catalog/person_authentication/person-authentication/#c-business-logic-in-custom-script", "text": "Jans-auth server uses Weld 3.0 (JSR-365 aka CDI 2.0) for managed beans. The most important aspects of business logic are implemented through a set of beans. Details and examples of this can be found in this article", "title": "C. Business logic in Custom script:"}, {"location": "script-catalog/person_authentication/person-authentication/#d-third-party-libraries-for-use-in-the-custom-script", "text": "Java or Python libraries to be imported and used very easily. Remember, you can import a python library only if it has been written in \"pure python\". More details of this mentioned here", "title": "D. Third party libraries for use in the custom script"}, {"location": "script-catalog/person_authentication/person-authentication/#e-configuring-the-acr-parameter-in-the-jans-auth-server", "text": "The acr parameter can be configured in the following ways :", "title": "E. Configuring the acr parameter in the Jans-auth server:"}, {"location": "script-catalog/person_authentication/person-authentication/#default-authentication-method", "text": "default_acr : This is the default authentication mechanism exposed to all applications that send users to the Janssen Server for sign-in. Unless an app specifically requests a different form of authentication using the OpenID Connect acr_values parameter (as specified below), users will receive the form of authentication specified in this field.", "title": "Default authentication method:"}, {"location": "script-catalog/person_authentication/person-authentication/#internal-acr", "text": "If a default ACR is not specified, Janssen will determine it based on enabled scripts and the internal user/password ACR. This internal ACR, simple_password_auth , is set to level -1. This means that it has lower priority than any scripts, so Janssen server will use it only if no other authentication method is set. Use the jans-cli to update / look-up the default authentication method .", "title": "Internal ACR"}, {"location": "script-catalog/person_authentication/person-authentication/#authentication-method-for-a-client-rp", "text": "A client may also specify default_acr_values during registration (and omit the parameter acr_values while making an authentication request).", "title": "Authentication method for a client (RP):"}, {"location": "script-catalog/person_authentication/person-authentication/#multiple-authentication-mechanisms", "text": "The Jans Server can concurrently support multiple authentication mechanisms, enabling Web and mobile apps (clients) to request a specific type of authentication using the standard OpenID Connect request parameter: acr_values . Learn more about acr_values in the OpenID Connect core spec .", "title": "Multiple Authentication Mechanisms"}, {"location": "script-catalog/person_authentication/person-authentication/#enabling-an-authentication-mechanism", "text": "An Authentication method is offered by the AS if its ACR value i.e. its corresponding custom script is enabled . By default, users will get the default authentication mechanism as specified above. However, using the OpenID Connect acr_values parameter, web and mobile clients can request any enabled authentication mechanism . Obtain the json contents of a custom script by using a jans-cli command like get-config-scripts-by-type , get-config-scripts-by-inum etc. Example : /opt/jans/jans-cli/config-cli.py --operation-id get-config-scripts-by-type --url-suffix type:PERSON_AUTHENTICATION /opt/jans/jans-cli/config-cli.py --operation-id get-config-scripts-by-inum --url-suffix inum:6122281b-b55d-4dd0-8115-b098eeeee2b7 Update the custom script and change the enabled attribute to true", "title": "Enabling an authentication mechanism"}, {"location": "script-catalog/person_authentication/person-authentication/#level-rank-of-an-authentication-mechanism", "text": "Each authentication mechanism (script) has a \"Level\" assigned to it which describes how secure and reliable it is. The higher the \"Level\", higher is the reliability represented by the script. Though several mechanisms can be enabled at the same Janssen server instance at the same time, for any specific user's session only one of them can be set as the current one (and will be returned as acr claim of id_token for them). If after initial session is created a new authorization request from a RP comes in specifying another authentication method, its \"Level\" will be compared to that of the method currently associated with this session. If requested method's \"Level\" is lower or equal to it, nothing is changed and the usual SSO behavior is observed. If it's higher (i.e. a more secure method is requested), it's not possible to serve such request using the existing session's context, and user must re-authenticate themselves to continue. If they succeed, a new session becomes associated with that requested mechanism instead.", "title": "Level (rank) of an Authentication mechanism :"}, {"location": "script-catalog/person_authentication/person-authentication/#f-using-person-authenticator-jansauthenticator-attribute", "text": "The jansAuthenticator attribute can be used in cases when person authenticator need to persist data between person logins. For example script can have enrollment and authentication flows. And after enrollment it needs to store data into user entry for later use in authentication flow. In order to search by enrolled authenticator there is another multi-valued attribute jansExtUid . This attribute has default DB index to quick search. Both attributes is recommended to use In Jans since 1.1.1 version for better compatibility in future.", "title": "F. Using person authenticator jansAuthenticator attribute :"}, {"location": "script-catalog/person_authentication/person-authentication/#1-format-of-attributes", "text": "jansExtUid: [otp:xyz1, cert:xyz2, duo:xyz3, ...] jansAuthenticator: { \"xyz1\": {\"id\": \"xyz1\", \"type\": \"otp\", \"custom\": {...}}, \"xyz2\": {\"id\": \"xyz2\", \"type\": \"cert\", \"custom\": {...}}, \"xyz3\": {\"id\": \"xyz3\", \"type\": \"duo\", \"custom\": {...}}, ... }", "title": "1. Format of attributes"}, {"location": "script-catalog/person_authentication/person-authentication/#2-sample-data", "text": "jansExtUid: [hotp:S9dO_qKQoOcpPk9GuStlNO9seoA=, cert:totp, duo:Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=] jansAuthenticator: { \"S9dO_qKQoOcpPk9GuStlNO9seoA=\": { \"id\": \"S9dO_qKQoOcpPk9GuStlNO9seoA=\", \"type\": \"hotp\", \"custom\": { \"movingFactor\": 3 } }, \"Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=\": { \"id\": \"Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=\", \"type\": \"totp\" } }", "title": "2. Sample data:"}, {"location": "script-catalog/person_authentication/person-authentication/#2-access-jansauthenticator-and-jansextuid-from-generic-bean", "text": "For both attributes there are get/set methods in User entry. After loading user object script can call these methods to get required data. ... @AttributeName(name = \"jansExtUid\") private String[] externalUid; @JsonObject @AttributeName(name = \"jansAuthenticator\") private UserAuthenticatorList authenticator ... public String[] getExternalUid() { return externalUid; } public void setExternalUid(String[] externalUid) { this.externalUid = externalUid; } public UserAuthenticatorList getAuthenticator() { return authenticator; } public void setAuthenticator(UserAuthenticatorList authenticator) { this.authenticator = authenticator; } ... UserAuthenticatorList is defined here . It contains list of UserAuthenticator objects. UserAuthenticator is defined here For convenience in 1.1.1 there is new service UserAuthenticator . See it's code here It provides next API methods: public UserAuthenticatorList getUserAuthenticatorList(SimpleUser user); public List<UserAuthenticator> getUserAuthenticatorsByType(SimpleUser user, String type); public UserAuthenticator getUserAuthenticatorById(SimpleUser user, String id); public void addUserAuthenticator(SimpleUser user, UserAuthenticator userAuthenticator); public void removeUserAuthenticator(SimpleUser user, UserAuthenticator userAuthenticator); public void removeUserAuthenticator(SimpleUser user, String type); public UserAuthenticator createUserAuthenticator(String id, String type); public UserAuthenticator createUserAuthenticator(String id, String type, Map<String, Object> custom); public String formatExternalUid(String id, String type); public boolean checkAndMigrateToAuthenticatorList(SimpleUser user); All these methods update both jansAuthenticator and jansExtUid attributes without persisting changes to DB. After calling these methods script should persist user entry. It's expected behaviour because script might update other fields too. Hence it's better to persist all changes in one update request to DB.", "title": "2. Access jansAuthenticator and jansExtUid from generic bean"}, {"location": "script-catalog/person_authentication/person-authentication/#1-default-authentication-method", "text": "default_acr : This is the default authentication mechanism exposed to all applications that send users to the Janssen Server for sign-in. Unless an app specifically requests a different form of authentication using the OpenID Connect acr_values parameter (as specified below), users will receive the form of authentication specified in this field.", "title": "1. Default authentication method:"}, {"location": "script-catalog/person_authentication/person-authentication/#usage-scenarios", "text": "", "title": "Usage scenarios"}, {"location": "script-catalog/person_authentication/person-authentication/#a-implementing-2fa-authentication-mechanisms", "text": "FIDO2 : Authentications using platform authenticators embedded into a person's device or physical USB, NFC or Bluetooth security keys that are inserted into a USB slot of a computer OTP authentication : Authentication mechanism using an app like Google authenticator , FreeOTP or Authy that implements the open standards HOTP and TOTP SMS OTP : Email OTP:", "title": "A. Implementing 2FA authentication mechanisms"}, {"location": "script-catalog/person_authentication/person-authentication/#b-implementing-multistep-authentication", "text": "Redirect to previous step : The script here an example of how the number of steps can be varied depending on the context or business requirement.", "title": "B. Implementing Multistep authentication"}, {"location": "script-catalog/person_authentication/person-authentication/#c-implementing-social-logins", "text": "You can use a PersonAuthenticationType script to allow users to sign using credentials from popular Social Identity providers or Inbound Identity Providers like Facebook, Google and Apple. After users authenticate, thier Social Identity Provider credentials are provisioned into the Jans-auth server. More on this topic in this article", "title": "C. Implementing Social logins"}, {"location": "script-catalog/person_authentication/person-authentication/#d-proactively-perform-fraud-detection", "text": "Impossible travel", "title": "D. Proactively perform fraud detection"}, {"location": "script-catalog/person_authentication/person-authentication/#testing-an-authentication-flow", "text": "An example of a complete URL looks like this - ``` https://<your.jans.server>/jans-auth/authorize.htm? \\ response_type=code&redirect_uri=https://<your.jans.server>/admin \\ &client_id=17b8b82e-b3ec-42a2-bd90-097028a37f3 \\ &scope=openid+profile+email+user_name \\ &state=faad2cdjfdddjfkdf&nonce=dajdffdfsdcfff ``` To test , enter the complete URL for authorization in a browser or create a simple webmapage with a link that simulates the user sign-in attempt. If the server is configured properly, the first page for the selected authentication method will be displayed to the user.", "title": "Testing an authentication flow"}, {"location": "script-catalog/person_authentication/person-authentication/#faqs", "text": "", "title": "FAQs"}, {"location": "script-catalog/person_authentication/person-authentication/#1-how-can-error-messages-be-displayed-on-a-web-page", "text": "FacesMessage bean is used for this purpose. from org.jans.jsf2.message import FacesMessages from org.jans.service.cdi.util import CdiUtil from javax.faces.application import FacesMessage ... facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Please enter a valid username\") The error will appear in the associated template using the following markup: ... <h:messages /> ... See an example here", "title": "1. How can error messages be displayed on a web page?"}, {"location": "script-catalog/person_authentication/person-authentication/#2-how-is-redirection-to-a-third-party-application-for-authentication-handled-in-a-script", "text": "For user authentication or consent gathering, there might be a need to redirect to a third party application to perform some operation and return the control back to authentication steps of the custom script. Please apply these steps to a person authentication script in such a scenario: Return from def getPageForStep(self, step, context), a page /auth/method_name/redirect.html ; with content similar to the code snippet below - def getPageForStep(self, step, context): return \"/auth/method_name/redirect.html\" Contents of redirect.xhtml should take the flow to prepareForStep method ... <f:metadata> <f:viewAction action=\"#{authenticator.prepareForStep}\" if=\"#{not identity.loggedIn}\" /> </f:metadata> In method prepareForStep prepare data needed for redirect and perform the redirection to the external service. def prepareForStep(self, step, context): ..... facesService = CdiUtil.bean(FacesService) facesService.redirectToExternalURL(third_party_URL ) return True In order to resume flow after the redirection, invoke a similar URL to https://my.gluu.server/postlogin.htm?param=123 from the third party app which takes the flow back to the authenticate method of the custom script. So create an xhtml page postlogin.xhtml which will look like this : <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> <html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:f=\"http://xmlns.jcp.org/jsf/core\"> <f:view transient=\"true\" contentType=\"text/html\"> <f:metadata> <f:viewAction action=\"#{authenticator.authenticateWithOutcome}\" /> </f:metadata> </f:view> </html> The <f:viewAction action=\"#{authenticator.authenticateWithOutcome}\" /> in step 4 takes us to the authenticate method inside the custom script def authenticate(self, configurationAttributes, requestParameters, step): . Here you can use parameters from request param = ServerUtil.getFirstValue(requestParameters, \"param-name\")) perform the state check (state : Opaque value used to maintain state between the request and the callback.) finally, return true or false from this method.", "title": "2. How is redirection to a third party application for authentication handled in a script?"}, {"location": "script-catalog/post_authn/post-authentication/", "tags": ["administration", "developer", "script-catalog", "PostAuthn"], "text": "Overview # After the browser has a session, if a person visits the website, the requesting party can obtain a code without the user having to authenticate or authorize. In some cases, it is desirable to insert custom business logic before granting the code or tokens from the authorization endpoint. Post Authentication script allows to force re-authentication or re-authorization (even if client is \"Pre-authorized\" or client authorization persistence is on). Interface # The post authentication script implements the PostAuthnType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def forceReAuthentication(self, context) This method is called during Authorization Request at Authorization Endpoint. If True is returned, session is set as unauthenticated and user is send for authentication. def forceAuthorization(self, context) This method is called during Authorization Request at Authorization Endpoint. If True is returned user is send for Authorization. By default if client is \"Pre-Authorized\" or \"Client Persist Authorizations\" is on, authorization is skipped. This script has higher priority and can cancel Pre-Authorization and persisted authorizations. Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference Use case: Dummy Post Authentication script (does not force re-authentication) # This was adapted from Gluu Post Authentication script example . Script Type: Python # from io.jans.model.custom.script.type.postauthn import PostAuthnType class PostAuthn ( PostAuthnType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Post Authn script. Initializing ...\" print \"Post Authn script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Post Authn script. Destroying ...\" print \"Post Authn script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def forceReAuthentication ( self , context ): return False def forceAuthorization ( self , context ): return False Script Type: Java # import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.postauthn.PostAuthnType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class PostAuthn implements PostAuthnType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Initializing...\" ); log . info ( \"Post Authentication. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Initializing...\" ); log . info ( \"Post Authentication. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Destroying...\" ); log . info ( \"Post Authentication. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean forceReAuthentication ( Object context ) { return false ; } @Override public boolean forceAuthorization ( Object context ) { return false ; } }", "title": "Post Authentication"}, {"location": "script-catalog/post_authn/post-authentication/#overview", "text": "After the browser has a session, if a person visits the website, the requesting party can obtain a code without the user having to authenticate or authorize. In some cases, it is desirable to insert custom business logic before granting the code or tokens from the authorization endpoint. Post Authentication script allows to force re-authentication or re-authorization (even if client is \"Pre-authorized\" or client authorization persistence is on).", "title": "Overview"}, {"location": "script-catalog/post_authn/post-authentication/#interface", "text": "The post authentication script implements the PostAuthnType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/post_authn/post-authentication/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/post_authn/post-authentication/#new-methods", "text": "Method header Method description def forceReAuthentication(self, context) This method is called during Authorization Request at Authorization Endpoint. If True is returned, session is set as unauthenticated and user is send for authentication. def forceAuthorization(self, context) This method is called during Authorization Request at Authorization Endpoint. If True is returned user is send for Authorization. By default if client is \"Pre-Authorized\" or \"Client Persist Authorizations\" is on, authorization is skipped. This script has higher priority and can cancel Pre-Authorization and persisted authorizations.", "title": "New Methods"}, {"location": "script-catalog/post_authn/post-authentication/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/post_authn/post-authentication/#use-case-dummy-post-authentication-script-does-not-force-re-authentication", "text": "This was adapted from Gluu Post Authentication script example .", "title": "Use case: Dummy Post Authentication script (does not force re-authentication)"}, {"location": "script-catalog/post_authn/post-authentication/#script-type-python", "text": "from io.jans.model.custom.script.type.postauthn import PostAuthnType class PostAuthn ( PostAuthnType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Post Authn script. Initializing ...\" print \"Post Authn script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Post Authn script. Destroying ...\" print \"Post Authn script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def forceReAuthentication ( self , context ): return False def forceAuthorization ( self , context ): return False", "title": "Script Type: Python"}, {"location": "script-catalog/post_authn/post-authentication/#script-type-java", "text": "import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.postauthn.PostAuthnType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class PostAuthn implements PostAuthnType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Initializing...\" ); log . info ( \"Post Authentication. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Initializing...\" ); log . info ( \"Post Authentication. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Destroying...\" ); log . info ( \"Post Authentication. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean forceReAuthentication ( Object context ) { return false ; } @Override public boolean forceAuthorization ( Object context ) { return false ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/", "tags": ["administration", "developer", "script-catalog", "ResourceOwnerPasswordCredentials"], "text": "Overview # Resource Owner Password Credentials script allows modifying the behavior of Resource Owner Password Credentials Grant ( RFC 6749 ). The script is invoked after normal authentication and can either leave current result or change it - authenticate if not authenticated - it should return True and optionally set user (via context.setUser(user) ). Interface # The ROPC script implements the ResourceOwnerPasswordCredentialsType interface. This extends methods from the base script type in addition to adding new method: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def authenticate(self, context) This method is called after normal ROPC authentication. This method can cancel normal authentication if it returns false and sets context.setUser(null) Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference Use case: Basic ROPC authentication script # This script has been adapted from the Gluu Server sample ROPC script Main usage of script is at Token Endpoint. However sometimes it can be useful to use ROPC custom script at Authorization Endpoint to avoid redirects and pages. By default it is not enabled but it can be enabled if set forceRopcInAuthorizationEndpoint AS configuration property to true . Also it is required to set user in context in custom script ( context.setUser(<user>) ). Without it authorization will go on in normal way (with pages and redirects). Script Type: Python # from io.jans.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType from io.jans.as.server.service import AuthenticationService from io.jans.service.cdi.util import CdiUtil from java.lang import String class ResourceOwnerPasswordCredentials ( ResourceOwnerPasswordCredentialsType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"ROPC script. Initializing ...\" self . usernameParamName = \"username\" self . passwordParamName = \"password\" print \"ROPC script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"ROPC script. Destroying ...\" print \"ROPC script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns True and set user into context when user authenticated succesfully # Returns False when user not authenticated or it's needed to cancel notmal flow def authenticate ( self , context ): print \"ROPC script. Authenticate\" deviceIdParam = context . getHttpRequest () . getParameterValues ( \"device_id\" ) if deviceIdParam != None and ( deviceIdParam . length > 0 ): result = deviceIdParam [ 0 ] == \"device_id_1\" if not result : return False # Set authenticated user in context # context.setUser(user) return True # Do generic authentication in other cases authService = CdiUtil . bean ( AuthenticationService ) username = context . getHttpRequest () . getParameter ( self . usernameParamName ) password = context . getHttpRequest () . getParameter ( self . passwordParamName ) result = authService . authenticate ( username , password ) if not result : print \"ROPC script. Authenticate. Could not authenticate user ' %s ' \" % username return False context . setUser ( authService . getAuthenticatedUser ()) return True Script Type: Java # import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.owner.ResourceOwnerPasswordCredentialsType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.AuthenticationService ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.as.server.service.external.context.ExternalResourceOwnerPasswordCredentialsContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class ResourceOwnerPasswordCredentials implements ResourceOwnerPasswordCredentialsType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); private final String usernameParamName = \"username\" ; private final String passwordParamName = \"password\" ; @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Destroying...\" ); log . info ( \"ROPC Script. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean authenticate ( Object context ) { log . info ( \"ROPC script. Authenticate\" ); ExternalResourceOwnerPasswordCredentialsContext ropcContext = ( ExternalResourceOwnerPasswordCredentialsContext ) context ; String [] deviceIdParam = ropcContext . getHttpRequest (). getParameterValues ( \"device_id\" ); if ( deviceIdParam != null && deviceIdParam . length > 0 ) { boolean result = deviceIdParam [ 0 ] == \"device_id_1\" ; if ( ! result ) { return false ; } // Set authenticated user in context // context.setUser(user) return true ; } // generic authentication in other cases AuthenticationService authService = CdiUtil . bean ( AuthenticationService . class ); String username = ropcContext . getHttpRequest (). getParameter ( usernameParamName ); String password = ropcContext . getHttpRequest (). getParameter ( passwordParamName ); boolean result = authService . authenticate ( username , password ); if ( ! result ) { log . info ( \"ROPC script. Authenticate. Could not authenticate \" + username ); return false ; } ropcContext . setUser ( authService . getAuthenticatedUser ()); return true ; } } Sample Scripts # Super Gluu ROPW Script 3 Step ROPW Script", "title": "Resource Owner Password Credentials"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#overview", "text": "Resource Owner Password Credentials script allows modifying the behavior of Resource Owner Password Credentials Grant ( RFC 6749 ). The script is invoked after normal authentication and can either leave current result or change it - authenticate if not authenticated - it should return True and optionally set user (via context.setUser(user) ).", "title": "Overview"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#interface", "text": "The ROPC script implements the ResourceOwnerPasswordCredentialsType interface. This extends methods from the base script type in addition to adding new method:", "title": "Interface"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#new-methods", "text": "Method header Method description def authenticate(self, context) This method is called after normal ROPC authentication. This method can cancel normal authentication if it returns false and sets context.setUser(null)", "title": "New Methods"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#use-case-basic-ropc-authentication-script", "text": "This script has been adapted from the Gluu Server sample ROPC script Main usage of script is at Token Endpoint. However sometimes it can be useful to use ROPC custom script at Authorization Endpoint to avoid redirects and pages. By default it is not enabled but it can be enabled if set forceRopcInAuthorizationEndpoint AS configuration property to true . Also it is required to set user in context in custom script ( context.setUser(<user>) ). Without it authorization will go on in normal way (with pages and redirects).", "title": "Use case: Basic ROPC authentication script"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#script-type-python", "text": "from io.jans.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType from io.jans.as.server.service import AuthenticationService from io.jans.service.cdi.util import CdiUtil from java.lang import String class ResourceOwnerPasswordCredentials ( ResourceOwnerPasswordCredentialsType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"ROPC script. Initializing ...\" self . usernameParamName = \"username\" self . passwordParamName = \"password\" print \"ROPC script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"ROPC script. Destroying ...\" print \"ROPC script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns True and set user into context when user authenticated succesfully # Returns False when user not authenticated or it's needed to cancel notmal flow def authenticate ( self , context ): print \"ROPC script. Authenticate\" deviceIdParam = context . getHttpRequest () . getParameterValues ( \"device_id\" ) if deviceIdParam != None and ( deviceIdParam . length > 0 ): result = deviceIdParam [ 0 ] == \"device_id_1\" if not result : return False # Set authenticated user in context # context.setUser(user) return True # Do generic authentication in other cases authService = CdiUtil . bean ( AuthenticationService ) username = context . getHttpRequest () . getParameter ( self . usernameParamName ) password = context . getHttpRequest () . getParameter ( self . passwordParamName ) result = authService . authenticate ( username , password ) if not result : print \"ROPC script. Authenticate. Could not authenticate user ' %s ' \" % username return False context . setUser ( authService . getAuthenticatedUser ()) return True", "title": "Script Type: Python"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#script-type-java", "text": "import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.owner.ResourceOwnerPasswordCredentialsType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.AuthenticationService ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.as.server.service.external.context.ExternalResourceOwnerPasswordCredentialsContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class ResourceOwnerPasswordCredentials implements ResourceOwnerPasswordCredentialsType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); private final String usernameParamName = \"username\" ; private final String passwordParamName = \"password\" ; @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Destroying...\" ); log . info ( \"ROPC Script. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean authenticate ( Object context ) { log . info ( \"ROPC script. Authenticate\" ); ExternalResourceOwnerPasswordCredentialsContext ropcContext = ( ExternalResourceOwnerPasswordCredentialsContext ) context ; String [] deviceIdParam = ropcContext . getHttpRequest (). getParameterValues ( \"device_id\" ); if ( deviceIdParam != null && deviceIdParam . length > 0 ) { boolean result = deviceIdParam [ 0 ] == \"device_id_1\" ; if ( ! result ) { return false ; } // Set authenticated user in context // context.setUser(user) return true ; } // generic authentication in other cases AuthenticationService authService = CdiUtil . bean ( AuthenticationService . class ); String username = ropcContext . getHttpRequest (). getParameter ( usernameParamName ); String password = ropcContext . getHttpRequest (). getParameter ( passwordParamName ); boolean result = authService . authenticate ( username , password ); if ( ! result ) { log . info ( \"ROPC script. Authenticate. Could not authenticate \" + username ); return false ; } ropcContext . setUser ( authService . getAuthenticatedUser ()); return true ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#sample-scripts", "text": "Super Gluu ROPW Script 3 Step ROPW Script", "title": "Sample Scripts"}, {"location": "script-catalog/revoke_token/revoke-token/", "tags": ["administration", "developer", "script-catalog", "RevokeToken"], "text": "Overview # Revoke Token scripts allow injecting custom logic during token revocation. Interface # The revoke token script implements the RevokeTokenType interface. This extends methods from the base script type in addition to adding new method: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def revoke(self, context) Token is revoked if this method returns True, skipped otherwise Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Reference Use Case: Basic Token Revocation # This script has been adapted from the Gluu Server sample revoke token script . Script Type: Python # from io.jans.model.custom.script.type.revoke import RevokeTokenType from java.lang import String class RevokeToken ( RevokeTokenType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Revoke Token script. Initializing ...\" print \"Revoke Token script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Revoke Token script. Destroying ...\" print \"Revoke Token script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # This method is called during Revoke Token call. # If True is returned, token is revoked. If False is returned, revoking is skipped. def revoke ( self , context ): return True Script Type: Java # import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.revoke.RevokeTokenType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class RevokeToken implements RevokeTokenType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Initializing...\" ); log . info ( \"Token Revoke. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Initializing...\" ); log . info ( \"Token Revoke. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Destroying...\" ); log . info ( \"Token Revoke. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean revoke ( Object context ) { return true ; } } This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Revoke Token"}, {"location": "script-catalog/revoke_token/revoke-token/#overview", "text": "Revoke Token scripts allow injecting custom logic during token revocation.", "title": "Overview"}, {"location": "script-catalog/revoke_token/revoke-token/#interface", "text": "The revoke token script implements the RevokeTokenType interface. This extends methods from the base script type in addition to adding new method:", "title": "Interface"}, {"location": "script-catalog/revoke_token/revoke-token/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/revoke_token/revoke-token/#new-methods", "text": "Method header Method description def revoke(self, context) Token is revoked if this method returns True, skipped otherwise", "title": "New Methods"}, {"location": "script-catalog/revoke_token/revoke-token/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Reference", "title": "Objects"}, {"location": "script-catalog/revoke_token/revoke-token/#use-case-basic-token-revocation", "text": "This script has been adapted from the Gluu Server sample revoke token script .", "title": "Use Case: Basic Token Revocation"}, {"location": "script-catalog/revoke_token/revoke-token/#script-type-python", "text": "from io.jans.model.custom.script.type.revoke import RevokeTokenType from java.lang import String class RevokeToken ( RevokeTokenType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Revoke Token script. Initializing ...\" print \"Revoke Token script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Revoke Token script. Destroying ...\" print \"Revoke Token script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # This method is called during Revoke Token call. # If True is returned, token is revoked. If False is returned, revoking is skipped. def revoke ( self , context ): return True", "title": "Script Type: Python"}, {"location": "script-catalog/revoke_token/revoke-token/#script-type-java", "text": "import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.revoke.RevokeTokenType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class RevokeToken implements RevokeTokenType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Initializing...\" ); log . info ( \"Token Revoke. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Initializing...\" ); log . info ( \"Token Revoke. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Destroying...\" ); log . info ( \"Token Revoke. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean revoke ( Object context ) { return true ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/revoke_token/revoke-token/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/revoke_token/revoke-token/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/revoke_token/revoke-token/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/scim/scim/", "tags": ["administration", "developer", "script-catalog"], "text": "SCIM Guide # Overview # SCIM script allows you to execute custom logic when certain SCIM API operations are invoked. With SCIM scripts, custom business logic can be executed when several of the SCIM API operations are invoked. This is useful in many situations, for example: Trigger notifications to external systems when certain resources are deleted Alter the actual responses the service produces Attach additional information to resources when they are created or updated Implement a fine-grained level of access to resources so different callers have permission to handle only a restricted number of resources Notes: # In this document, the term resources refer to those \"entities\" the service can manage, for instance, users or groups The term operation refers to any SCIM functionality accessible through its HTTP endpoints Basic development skills are assumed. Some grasp of Java and Python are required as well as understanding of the SCIM protocol. Interface # Methods # API Overview Custom scripts adhere to a simple API (ie. a well-defined collection of methods/routines) that is described in the following. It is advised to check the dummy script provided here as you read this section. Scripts' config properties All methods contain a configurationAttributes parameter, this gives access to the configuration properties of the script itself. This is a relevant aspect of Gluu scripts: they are all parameterizable!. configurationAttributes is a java.util.Map<String, SimpleCustomProperty> and here is how SimpleCustomProperty looks. Basic Methods These are methods not related to SCIM operations but still play key roles: |Method Name|Description|Return Value| |:---|:---|:---| | init |Called when the (SCIM) service starts and every time the script properties or code changes|A boolean value describing success or failure| | destroy |Called every time the script properties or code changes (called before init )|A boolean value describing success or failure| | getApiVersion |Determines what methods are effectively called when SCIM endpoints are invoked|A positive integer| Pre-resource Modification They are called when the resource is about to be persisted. The second parameter in these methods hold the object that will be persisted to permanent storage, thus any change or manipulation upon the object will be reflected in the underlying database (as well as in the output of the SCIM operation call itself). These methods are called regardless of the API version used. Names are self explanatory: Methods 2nd param 2nd param Class/Link createUser , updateUser , deleteUser user ScimCustomPerson createGroup , updateGroup , deleteGroup group GluuGroup Pre-resource modification methods return a boolean. A False value aborts the corresponding SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that update* methods are called for both SCIM PUT and PATCH operations. Post-resource Modification They are called after the resource is persisted. The second parameter in these methods hold the object that was saved. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 2. Methods 2nd param 2nd param Class/Link postCreateUser , postUpdateUser , postDeleteUser user ScimCustomPerson postCreateGroup , postUpdateGroup , postDeleteGroup group GluuGroup Post-resource modification methods return a boolean. A False value aborts the corresponding SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that postUpdate* methods are called for both SCIM PUT and PATCH operations. Single Resource Retrieval These apply for SCIM operations that retrieve a resource by ID. They are called after the resource has been obtained from the database. The second parameter in these methods hold a reference to such object. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 3. Methods 2nd param 2nd param Class/Link getUser user ScimCustomPerson getGroup group GluuGroup Single resource retrieval methods return a boolean. A False value aborts the whole SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Multiple Resources Retrieval These apply for SCIM search operations. They are called after the results have been obtained from the database. The second parameter in these methods hold a reference to such result set. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 4. Methods 2nd param 2nd param Class/Link postSearchUsers results PagedResult postSearchGroups results PagedResult Multiple resources retrieval methods return a boolean. A False value aborts the whole SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that searching using the root .search SCIM endpoint will trigger calls to both of the methods listed. Advanced control These are alternative methods that allow to tweak the response the service produces. They can be employed to introduce complex business rules when operations are executed. These methods are called if getApiVersion returns a number >= 5. Methods manageResourceOperation manageSearchOperation Example: Modifying Search Results # SCIM spec defines the concept of attribute returnability where some attributes should never be part of a response (like passwords), always be returned (like resource identifiers), or be returned by default unless otherwise stated by the excludedAttributes parameter. Assume you are maintaining a user base of secret agents that work for your company and need to avoid exposing information such as their physical addresses for safety reasons. To keep it simple let's restrict the scope to user searches only. In practice you should take steps to hide this data on user retrieval and update. Let's alter postSearchUsers 's second parameter ( results ) to ensure addresses are not leaked: for user in results . getEntries () : user . setAttribute ( \"jansAddress\" , None ) This is very straightforward code except for the usage of jansAddress . Shouldn't it be simply addresses as the known SCIM attribute? Scripts work with entities that are about to be persisted or have already been saved so they kind of resemble the database structure (schema in MySQL terms). It turns out that database attribute names rarely match with SCIM names. While it is easy to know the SCIM name of a database attribute, the converse requires checking the code, however since you already have the skill this shouldn't be a problem: in this Java class you'll find the representation of a user resource in SCIM spec terms. Pay attention to the addresses field and its associated StoreReference annotation that contains the attribute where addresses are actually stored. With that said, save your modifications. You may like the idea of adding some prints for enlightment like: print \"%d entries returned of %d\" % ( results . getEntriesCount () , results . getTotalEntriesCount ()) for user in results . getEntries () : print \"Flushing addresses for user %s\" % user . getUid () user . setAttribute ( \"jansAddress\" , None ) Ensure no addresses are returned anymore in your SCIM user searches. Happy testing! Controlling execution of SCIM operations # With the manageResourceOperation and manageSearchOperation methods you can make complex decisions on how processing should take place based on contextual data and the incoming payload. manageResourceOperation This method is invoked when any following operations are executed: resource creation, modification, removal and retrieval by ID. In case of bulks, the method is called for every operation that fits into these categories. Parameters are described in the table below: Name Description Class/Link context Provides contextual information about the SCIM operation being called such as type of resource involved, HTTP verb, request headers, query params, etc. OperationContext entity A non-null object representing the resource involved A descendant of Entry . If the resource is a user, it will be an instance of ScimCustomPerson . In case of a group, it will be a GluuGroup payload The payload sent in the invocation; null when the operation is removal or retrieval by ID The datatype depends on the operation called. Check the interface that suits best and inspect the first parameter's datatype. The class will belong to some subpackage inside io.jans.scim.model.scim2 This method is expected to return an instance of javax.ws.rs.core.Response that supersedes the output of the operation itself. In other words, the actual processing of the operation is skipped in favor of the code supplied here. However note that minor validations may take place in the payload before your code is actually called. Returning None transfers the control of the operation for normal processing (default Jans implementation). If the method execution crashes at runtime, a 500 HTTP error is sent. Notes: Possible values for context.getResourceType() are: User, Group, FidoDevice, Fido2Device context.getTokenDetails().getValue() is a shortcut that will give you the access token the caller employed to issue the service call Both context.getTokenDetails().getTokenType() and context.getTokenDetails().getScope() return non null values when the protection mechanism of the API is OAuth or test mode Note that for resource creation operation, entity basically contains the same data supplied in the POST payload . In this case, entity has not originated from the database and has not been persisted either For the case of modification, retrieval and removal, entity contains the data currently stored in the database for the resource in question Since many values come from Java code, you can always do getClass().getName() to get an idea of what type of variables you are dealing with To build custom error responses your can reuse some of the getErrorResponse methods of class BaseScimWebService This method offers a high degree of flexibility. Perform careful testing of your code and account all potential scenarios. manageSearchOperation This method is invoked when resource searches are performed. Parameters are described in the table below: name Description Class/Link context Provides contextual information about the SCIM operation being called such as type of resource involved, HTTP verb, request headers, query params, etc. OperationContext searchRequest An object representing the search parameters provided in the call (applies for both GET and POST) SearchRequest Unlike manageResourceOperation , no entity parameter is passed. This is so because making decisions based on already executed searches would have a performance impact. Instead you can use context.setFilterPrepend(...) to help restrict the search against the database: here you can pass a String value that will be interpreted as an SCIM filter expression (see section 3.4.2.2 of RFC 7644). When the search being performed already contains a search filter (i.e. searchRequest.getFilter() is non-empty), a new filter is created by appending both \"subfilters\" with an and operator. As in the case of manageResourceOperation this method is expected to return an instance of javax.ws.rs.core.Response . Returning None transfers the control of the operation for normal processing (the Jans implementation). If the method execution crashes at runtime, a 500 HTTP error is sent. The same recommendations given for manageResourceOperation apply here. If you build filter expressions in your method, ensure they are syntactically valid to avoid your callers getting unexpected \"invalidFilter\" 400 errors. Example: segmenting the user base Let's assume you make use of the SCIM attribute userType so that your user base is partitioned into three disjoint segments according to such attribute and you have designated its possible values to be: Contractor, Employee, or Intern. Suppose your company has three different applications that make management of users in every category, that is, only one application is devoted to manage contractors, another employees, and other interns. You are interested in consistently granting access so that no application can create, query or modify users that don't belong to its focus. To properly handle this multi-tenancy scenario, you decide to use the contextual information coming from every request to determine if the operation should be allowed or not. For this purpose you communicate every application developer to send an additional HTTP header in their call with a value that only you (the administrator) and the developer knows. Let's call it the \"secret\". For the sake of simplicity let's assume developers are external to the company and only you know their identities. They don't know each other so they cannot exchange secrets. The strategy to implement segmentation is rather simple: Alter the default SCIM script by supplying a custom implementation for the methods that control execution Make the HTTP header name be a configuration property of the script so that it is not hard-coded Add a configuration property that contains the mapping of userType value vs. expected header value in JSON format Adding and parsing config properties Using Jans Config CLI update the SCIM script and add properties: custom_header with value USER-SEGMENT-SECRET access_map with value { \"<random_string>\":\"Contractor\", \"<random_string>\":\"Employee\", \"<random_string>\":\"Intern\" } Save the changes. In the init method this properties should be parsed. To start, let's add some imports: from io.jans.scim.ws.rs.scim2 import BaseScimWebService import json Here is how init would look like: def init ( self , configurationAttributes ): self . custom_header = configurationAttributes . get ( \"custom_header\" ) . getValue2 () access_map_json = configurationAttributes . get ( \"access_map\" ) . getValue2 () self . access_map = json . loads ( access_map_json ) print \"ScimEventHandler (init): Initialized successfully\" return True Note no validations took place here: we assumed the script contains the properties, that they are non empty and have sensible values. Allow/Deny resource operations The first step is to know the kind of application that is calling our service. For this purpose let's create a method that given incoming request headers returns the matching userType # headers params is an instance of javax . ws . rs . core . MultivaluedMap < String , String > def getUserType ( self , headers ) : secret = headers . getFirst ( self . custom_header ) if secret in self . access_map : return self . access_map [ secret ] else : return None Now let's code manageResourceOperation . We should allow access only under the following conditions: The getUserType method does not return None The entity object ( ScimCustomPerson instance) has a proper userType value. This means that for user creation, the incoming payload comes with a matching userType and for the other cases, the already stored attribute matches as well Assume that if the operation invoked is not user-related, we should allow access freely. Here is how the implementation might look: def manageResourceOperation ( self , context , entity , payload , configurationAttributes ): print \"manageResourceOperation. SCIM endpoint invoked is %s (HTTP %s )\" % ( context . getPath (), context . getMethod ()) if context . getResourceType () != \"User\" : return None expected_user_type = self . getUserType ( context . getRequestHeaders ()) if expected_user_type != None and entity . getAttribute ( \"jansUsrTyp\" ) == expected_user_type : return None else : return BaseScimWebService . getErrorResponse ( 403 , None , \"Attempt to handle a not allowed user type\" ) Note no usage of the payload took place. A case you may like to evaluate is where mistakenly using an update operation, the userType is set to an unexpected value. Allow/Deny searches This time instead of inspecting an entity, we ought to make a filter expression to restrict the search when the database is queried. For your reference, a valid filter expression is for instance userType eq \"Contractor\" . def manageSearchOperation ( self , context , searchRequest , configurationAttributes ) : print \"manageSearchOperation. SCIM endpoint invoked is %s (HTTP %s)\" % ( context . getPath () , context . getMethod ()) resource_type = context . getResourceType () print \"manageSearchOperation. This is a search over %s resources\" % resource_type if resource_type != \"User\" : return None expected_user_type = self . getUserType ( context . getRequestHeaders ()) if expected_user_type != None : context . setFilterPrepend ( \"userType eq \\\" % s \\ \"\" % expected_user_type ) return None else : return BaseScimWebService . getErrorResponse ( 403 , None , \"Attempt to handle a not allowed user type\" ) The manageSearchOperation must return a javax.ws.rs.core.Response . A None value makes continue the operation processing normally. Working with more than one script # You may have already noticed that it is possible to have several scripts under the SCIM type. This is how execution takes place when there are several scripts enabled: The applicable method is called in the first script. If the return value was True , the method is called again but this time in the subsequent script. If at any point a False return value is encountered, the SCIM operation is aborted with error 500. This means that a normal operation execution requires all involved methods across different scripts to be successful. There is an important exception to the above and is related to the manage* methods. In this case, only one script takes effect (the first script found). Note that in most cases having a single SCIM script suffices for all needs. Common Use Cases # Script Type: Python # Custom SCIM Event Handler # Find the script here The sample code snippet shows how to - 1. Modify Search Results 2. Segment the user base 3. Allow/Deny resource operations 4. Allow/Deny searches Script Type: Java # Custom SCIM Event Handler # Find the code here The sample code snippet shows how to - 1. Modify Search Results 2. Segment the user base 3. Allow/Deny resource operations 4. Allow/Deny searches", "title": "SCIM"}, {"location": "script-catalog/scim/scim/#scim-guide", "text": "", "title": "SCIM Guide"}, {"location": "script-catalog/scim/scim/#overview", "text": "SCIM script allows you to execute custom logic when certain SCIM API operations are invoked. With SCIM scripts, custom business logic can be executed when several of the SCIM API operations are invoked. This is useful in many situations, for example: Trigger notifications to external systems when certain resources are deleted Alter the actual responses the service produces Attach additional information to resources when they are created or updated Implement a fine-grained level of access to resources so different callers have permission to handle only a restricted number of resources", "title": "Overview"}, {"location": "script-catalog/scim/scim/#notes", "text": "In this document, the term resources refer to those \"entities\" the service can manage, for instance, users or groups The term operation refers to any SCIM functionality accessible through its HTTP endpoints Basic development skills are assumed. Some grasp of Java and Python are required as well as understanding of the SCIM protocol.", "title": "Notes:"}, {"location": "script-catalog/scim/scim/#interface", "text": "", "title": "Interface"}, {"location": "script-catalog/scim/scim/#methods", "text": "API Overview Custom scripts adhere to a simple API (ie. a well-defined collection of methods/routines) that is described in the following. It is advised to check the dummy script provided here as you read this section. Scripts' config properties All methods contain a configurationAttributes parameter, this gives access to the configuration properties of the script itself. This is a relevant aspect of Gluu scripts: they are all parameterizable!. configurationAttributes is a java.util.Map<String, SimpleCustomProperty> and here is how SimpleCustomProperty looks. Basic Methods These are methods not related to SCIM operations but still play key roles: |Method Name|Description|Return Value| |:---|:---|:---| | init |Called when the (SCIM) service starts and every time the script properties or code changes|A boolean value describing success or failure| | destroy |Called every time the script properties or code changes (called before init )|A boolean value describing success or failure| | getApiVersion |Determines what methods are effectively called when SCIM endpoints are invoked|A positive integer| Pre-resource Modification They are called when the resource is about to be persisted. The second parameter in these methods hold the object that will be persisted to permanent storage, thus any change or manipulation upon the object will be reflected in the underlying database (as well as in the output of the SCIM operation call itself). These methods are called regardless of the API version used. Names are self explanatory: Methods 2nd param 2nd param Class/Link createUser , updateUser , deleteUser user ScimCustomPerson createGroup , updateGroup , deleteGroup group GluuGroup Pre-resource modification methods return a boolean. A False value aborts the corresponding SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that update* methods are called for both SCIM PUT and PATCH operations. Post-resource Modification They are called after the resource is persisted. The second parameter in these methods hold the object that was saved. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 2. Methods 2nd param 2nd param Class/Link postCreateUser , postUpdateUser , postDeleteUser user ScimCustomPerson postCreateGroup , postUpdateGroup , postDeleteGroup group GluuGroup Post-resource modification methods return a boolean. A False value aborts the corresponding SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that postUpdate* methods are called for both SCIM PUT and PATCH operations. Single Resource Retrieval These apply for SCIM operations that retrieve a resource by ID. They are called after the resource has been obtained from the database. The second parameter in these methods hold a reference to such object. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 3. Methods 2nd param 2nd param Class/Link getUser user ScimCustomPerson getGroup group GluuGroup Single resource retrieval methods return a boolean. A False value aborts the whole SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Multiple Resources Retrieval These apply for SCIM search operations. They are called after the results have been obtained from the database. The second parameter in these methods hold a reference to such result set. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 4. Methods 2nd param 2nd param Class/Link postSearchUsers results PagedResult postSearchGroups results PagedResult Multiple resources retrieval methods return a boolean. A False value aborts the whole SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that searching using the root .search SCIM endpoint will trigger calls to both of the methods listed. Advanced control These are alternative methods that allow to tweak the response the service produces. They can be employed to introduce complex business rules when operations are executed. These methods are called if getApiVersion returns a number >= 5. Methods manageResourceOperation manageSearchOperation", "title": "Methods"}, {"location": "script-catalog/scim/scim/#example-modifying-search-results", "text": "SCIM spec defines the concept of attribute returnability where some attributes should never be part of a response (like passwords), always be returned (like resource identifiers), or be returned by default unless otherwise stated by the excludedAttributes parameter. Assume you are maintaining a user base of secret agents that work for your company and need to avoid exposing information such as their physical addresses for safety reasons. To keep it simple let's restrict the scope to user searches only. In practice you should take steps to hide this data on user retrieval and update. Let's alter postSearchUsers 's second parameter ( results ) to ensure addresses are not leaked: for user in results . getEntries () : user . setAttribute ( \"jansAddress\" , None ) This is very straightforward code except for the usage of jansAddress . Shouldn't it be simply addresses as the known SCIM attribute? Scripts work with entities that are about to be persisted or have already been saved so they kind of resemble the database structure (schema in MySQL terms). It turns out that database attribute names rarely match with SCIM names. While it is easy to know the SCIM name of a database attribute, the converse requires checking the code, however since you already have the skill this shouldn't be a problem: in this Java class you'll find the representation of a user resource in SCIM spec terms. Pay attention to the addresses field and its associated StoreReference annotation that contains the attribute where addresses are actually stored. With that said, save your modifications. You may like the idea of adding some prints for enlightment like: print \"%d entries returned of %d\" % ( results . getEntriesCount () , results . getTotalEntriesCount ()) for user in results . getEntries () : print \"Flushing addresses for user %s\" % user . getUid () user . setAttribute ( \"jansAddress\" , None ) Ensure no addresses are returned anymore in your SCIM user searches. Happy testing!", "title": "Example: Modifying Search Results"}, {"location": "script-catalog/scim/scim/#controlling-execution-of-scim-operations", "text": "With the manageResourceOperation and manageSearchOperation methods you can make complex decisions on how processing should take place based on contextual data and the incoming payload. manageResourceOperation This method is invoked when any following operations are executed: resource creation, modification, removal and retrieval by ID. In case of bulks, the method is called for every operation that fits into these categories. Parameters are described in the table below: Name Description Class/Link context Provides contextual information about the SCIM operation being called such as type of resource involved, HTTP verb, request headers, query params, etc. OperationContext entity A non-null object representing the resource involved A descendant of Entry . If the resource is a user, it will be an instance of ScimCustomPerson . In case of a group, it will be a GluuGroup payload The payload sent in the invocation; null when the operation is removal or retrieval by ID The datatype depends on the operation called. Check the interface that suits best and inspect the first parameter's datatype. The class will belong to some subpackage inside io.jans.scim.model.scim2 This method is expected to return an instance of javax.ws.rs.core.Response that supersedes the output of the operation itself. In other words, the actual processing of the operation is skipped in favor of the code supplied here. However note that minor validations may take place in the payload before your code is actually called. Returning None transfers the control of the operation for normal processing (default Jans implementation). If the method execution crashes at runtime, a 500 HTTP error is sent. Notes: Possible values for context.getResourceType() are: User, Group, FidoDevice, Fido2Device context.getTokenDetails().getValue() is a shortcut that will give you the access token the caller employed to issue the service call Both context.getTokenDetails().getTokenType() and context.getTokenDetails().getScope() return non null values when the protection mechanism of the API is OAuth or test mode Note that for resource creation operation, entity basically contains the same data supplied in the POST payload . In this case, entity has not originated from the database and has not been persisted either For the case of modification, retrieval and removal, entity contains the data currently stored in the database for the resource in question Since many values come from Java code, you can always do getClass().getName() to get an idea of what type of variables you are dealing with To build custom error responses your can reuse some of the getErrorResponse methods of class BaseScimWebService This method offers a high degree of flexibility. Perform careful testing of your code and account all potential scenarios. manageSearchOperation This method is invoked when resource searches are performed. Parameters are described in the table below: name Description Class/Link context Provides contextual information about the SCIM operation being called such as type of resource involved, HTTP verb, request headers, query params, etc. OperationContext searchRequest An object representing the search parameters provided in the call (applies for both GET and POST) SearchRequest Unlike manageResourceOperation , no entity parameter is passed. This is so because making decisions based on already executed searches would have a performance impact. Instead you can use context.setFilterPrepend(...) to help restrict the search against the database: here you can pass a String value that will be interpreted as an SCIM filter expression (see section 3.4.2.2 of RFC 7644). When the search being performed already contains a search filter (i.e. searchRequest.getFilter() is non-empty), a new filter is created by appending both \"subfilters\" with an and operator. As in the case of manageResourceOperation this method is expected to return an instance of javax.ws.rs.core.Response . Returning None transfers the control of the operation for normal processing (the Jans implementation). If the method execution crashes at runtime, a 500 HTTP error is sent. The same recommendations given for manageResourceOperation apply here. If you build filter expressions in your method, ensure they are syntactically valid to avoid your callers getting unexpected \"invalidFilter\" 400 errors. Example: segmenting the user base Let's assume you make use of the SCIM attribute userType so that your user base is partitioned into three disjoint segments according to such attribute and you have designated its possible values to be: Contractor, Employee, or Intern. Suppose your company has three different applications that make management of users in every category, that is, only one application is devoted to manage contractors, another employees, and other interns. You are interested in consistently granting access so that no application can create, query or modify users that don't belong to its focus. To properly handle this multi-tenancy scenario, you decide to use the contextual information coming from every request to determine if the operation should be allowed or not. For this purpose you communicate every application developer to send an additional HTTP header in their call with a value that only you (the administrator) and the developer knows. Let's call it the \"secret\". For the sake of simplicity let's assume developers are external to the company and only you know their identities. They don't know each other so they cannot exchange secrets. The strategy to implement segmentation is rather simple: Alter the default SCIM script by supplying a custom implementation for the methods that control execution Make the HTTP header name be a configuration property of the script so that it is not hard-coded Add a configuration property that contains the mapping of userType value vs. expected header value in JSON format Adding and parsing config properties Using Jans Config CLI update the SCIM script and add properties: custom_header with value USER-SEGMENT-SECRET access_map with value { \"<random_string>\":\"Contractor\", \"<random_string>\":\"Employee\", \"<random_string>\":\"Intern\" } Save the changes. In the init method this properties should be parsed. To start, let's add some imports: from io.jans.scim.ws.rs.scim2 import BaseScimWebService import json Here is how init would look like: def init ( self , configurationAttributes ): self . custom_header = configurationAttributes . get ( \"custom_header\" ) . getValue2 () access_map_json = configurationAttributes . get ( \"access_map\" ) . getValue2 () self . access_map = json . loads ( access_map_json ) print \"ScimEventHandler (init): Initialized successfully\" return True Note no validations took place here: we assumed the script contains the properties, that they are non empty and have sensible values. Allow/Deny resource operations The first step is to know the kind of application that is calling our service. For this purpose let's create a method that given incoming request headers returns the matching userType # headers params is an instance of javax . ws . rs . core . MultivaluedMap < String , String > def getUserType ( self , headers ) : secret = headers . getFirst ( self . custom_header ) if secret in self . access_map : return self . access_map [ secret ] else : return None Now let's code manageResourceOperation . We should allow access only under the following conditions: The getUserType method does not return None The entity object ( ScimCustomPerson instance) has a proper userType value. This means that for user creation, the incoming payload comes with a matching userType and for the other cases, the already stored attribute matches as well Assume that if the operation invoked is not user-related, we should allow access freely. Here is how the implementation might look: def manageResourceOperation ( self , context , entity , payload , configurationAttributes ): print \"manageResourceOperation. SCIM endpoint invoked is %s (HTTP %s )\" % ( context . getPath (), context . getMethod ()) if context . getResourceType () != \"User\" : return None expected_user_type = self . getUserType ( context . getRequestHeaders ()) if expected_user_type != None and entity . getAttribute ( \"jansUsrTyp\" ) == expected_user_type : return None else : return BaseScimWebService . getErrorResponse ( 403 , None , \"Attempt to handle a not allowed user type\" ) Note no usage of the payload took place. A case you may like to evaluate is where mistakenly using an update operation, the userType is set to an unexpected value. Allow/Deny searches This time instead of inspecting an entity, we ought to make a filter expression to restrict the search when the database is queried. For your reference, a valid filter expression is for instance userType eq \"Contractor\" . def manageSearchOperation ( self , context , searchRequest , configurationAttributes ) : print \"manageSearchOperation. SCIM endpoint invoked is %s (HTTP %s)\" % ( context . getPath () , context . getMethod ()) resource_type = context . getResourceType () print \"manageSearchOperation. This is a search over %s resources\" % resource_type if resource_type != \"User\" : return None expected_user_type = self . getUserType ( context . getRequestHeaders ()) if expected_user_type != None : context . setFilterPrepend ( \"userType eq \\\" % s \\ \"\" % expected_user_type ) return None else : return BaseScimWebService . getErrorResponse ( 403 , None , \"Attempt to handle a not allowed user type\" ) The manageSearchOperation must return a javax.ws.rs.core.Response . A None value makes continue the operation processing normally.", "title": "Controlling execution of SCIM operations"}, {"location": "script-catalog/scim/scim/#working-with-more-than-one-script", "text": "You may have already noticed that it is possible to have several scripts under the SCIM type. This is how execution takes place when there are several scripts enabled: The applicable method is called in the first script. If the return value was True , the method is called again but this time in the subsequent script. If at any point a False return value is encountered, the SCIM operation is aborted with error 500. This means that a normal operation execution requires all involved methods across different scripts to be successful. There is an important exception to the above and is related to the manage* methods. In this case, only one script takes effect (the first script found). Note that in most cases having a single SCIM script suffices for all needs.", "title": "Working with more than one script"}, {"location": "script-catalog/scim/scim/#common-use-cases", "text": "", "title": "Common Use Cases"}, {"location": "script-catalog/scim/scim/#script-type-python", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/scim/scim/#custom-scim-event-handler", "text": "Find the script here The sample code snippet shows how to - 1. Modify Search Results 2. Segment the user base 3. Allow/Deny resource operations 4. Allow/Deny searches", "title": "Custom SCIM Event Handler"}, {"location": "script-catalog/scim/scim/#script-type-java", "text": "", "title": "Script Type: Java"}, {"location": "script-catalog/scim/scim/#custom-scim-event-handler_1", "text": "Find the code here The sample code snippet shows how to - 1. Modify Search Results 2. Segment the user base 3. Allow/Deny resource operations 4. Allow/Deny searches", "title": "Custom SCIM Event Handler"}, {"location": "script-catalog/select_account/select-account/", "tags": ["administration", "developer", "script-catalog", "SelectAccount"], "text": "Overview # A person may have several accounts on a single Jans Auth Server instance. For example, it is common to have several Gmail accounts. Jans Auth Server uses two cookies to track which accounts are associated with a browser: session_id and current_sessions . Please check Multiple Sessions In One Browser Overview Select Account interception script can be used to customize account selection behavior. E.g. redirect to external page or change text representation of sessions on page. Interface # The select account script implements the SelectAccountType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def getSelectAccountPage(self, context) This method is called to return path to custom select account page (e.g. /customs/page/path/myselectaccount.xhtml) def prepare(self, context) This method is called before select account page is loaded. It can be used to prevent loading or redirect to external url. def getAccountDisplayName(self, context) This method is used to customize text representation of the session shown on the page. Returns display name for given session id (https://github.com/JanssenProject/jans/blob/main/jans-auth-server/common/src/main/java/io/jans/as/common/model/session/SessionId.java). def onSelect(self, context) This method is called on session selection and can be used to forbid selection. Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Execution Context Reference Use case: Dummy Select Account example script (does not have impact on built-in account selection) # Select Account script example . Script Type: Python # # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2020, Janssen # # Author: Yuriy Z # from io.jans.model.custom.script.type.selectaccount import SelectAccountType from java.lang import String class SelectAccount ( SelectAccountType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"SelectAccount script. Initializing ...\" print \"SelectAccount script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"SelectAccount script. Destroying ...\" print \"SelectAccount script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns path to select account page (e.g. /customs/page/path/myselectaccount.xhtml) # If none or empty string is returned, AS uses built-in page. # (Note: Custom page can be also put into `custom/pages/selectAccount.xhtml` and used without custom script.) # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def getSelectAccountPage ( self , context ): return \"\" # This method is called before select account page is loaded. # It is good place to make preparation processing. # E.g. check whether it is ok to land on select account page or maybe redirect to external page. # Return True - continue loading of the page # Return False - stop loading and show error page # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def prepare ( self , context ): return True # Returns display name for given session id (https://github.com/JanssenProject/jans/blob/main/jans-auth-server/common/src/main/java/io/jans/as/common/model/session/SessionId.java). # Session can be accessed via context.getSessionId() # Typical use is: context.getSessionId().getUser().getAttribute(\"myDisplayName\") # Returns string. If blank string is returned, AS will return built-in implementation to return display name # which is context.getSessionId().getUser().getAttribute(\"displayName\") # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def getAccountDisplayName ( self , context ): return \"\" # This method is called on session selection. # Selected session can be accessed as context.getSessionId() # Return True - continue session selection # Return False - stop session selection (forbid it) # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def onSelect ( self , context ): return True Script Type: Java # import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import java.util.Map ; /** * @author Yuriy Z */ public class DummySelectAccountType implements SelectAccountType { @Override public String getSelectAccountPage ( Object context ) { return \"\" ; } @Override public boolean prepare ( Object context ) { return true ; } @Override public String getAccountDisplayName ( Object context ) { return \"\" ; } @Override public boolean onSelect ( Object context ) { return false ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public int getApiVersion () { return 1 ; } }", "title": "Select Account"}, {"location": "script-catalog/select_account/select-account/#overview", "text": "A person may have several accounts on a single Jans Auth Server instance. For example, it is common to have several Gmail accounts. Jans Auth Server uses two cookies to track which accounts are associated with a browser: session_id and current_sessions . Please check Multiple Sessions In One Browser Overview Select Account interception script can be used to customize account selection behavior. E.g. redirect to external page or change text representation of sessions on page.", "title": "Overview"}, {"location": "script-catalog/select_account/select-account/#interface", "text": "The select account script implements the SelectAccountType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/select_account/select-account/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/select_account/select-account/#new-methods", "text": "Method header Method description def getSelectAccountPage(self, context) This method is called to return path to custom select account page (e.g. /customs/page/path/myselectaccount.xhtml) def prepare(self, context) This method is called before select account page is loaded. It can be used to prevent loading or redirect to external url. def getAccountDisplayName(self, context) This method is used to customize text representation of the session shown on the page. Returns display name for given session id (https://github.com/JanssenProject/jans/blob/main/jans-auth-server/common/src/main/java/io/jans/as/common/model/session/SessionId.java). def onSelect(self, context) This method is called on session selection and can be used to forbid selection.", "title": "New Methods"}, {"location": "script-catalog/select_account/select-account/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Execution Context Reference", "title": "Objects"}, {"location": "script-catalog/select_account/select-account/#use-case-dummy-select-account-example-script-does-not-have-impact-on-built-in-account-selection", "text": "Select Account script example .", "title": "Use case: Dummy Select Account example script (does not have impact on built-in account selection)"}, {"location": "script-catalog/select_account/select-account/#script-type-python", "text": "# oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2020, Janssen # # Author: Yuriy Z # from io.jans.model.custom.script.type.selectaccount import SelectAccountType from java.lang import String class SelectAccount ( SelectAccountType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"SelectAccount script. Initializing ...\" print \"SelectAccount script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"SelectAccount script. Destroying ...\" print \"SelectAccount script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns path to select account page (e.g. /customs/page/path/myselectaccount.xhtml) # If none or empty string is returned, AS uses built-in page. # (Note: Custom page can be also put into `custom/pages/selectAccount.xhtml` and used without custom script.) # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def getSelectAccountPage ( self , context ): return \"\" # This method is called before select account page is loaded. # It is good place to make preparation processing. # E.g. check whether it is ok to land on select account page or maybe redirect to external page. # Return True - continue loading of the page # Return False - stop loading and show error page # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def prepare ( self , context ): return True # Returns display name for given session id (https://github.com/JanssenProject/jans/blob/main/jans-auth-server/common/src/main/java/io/jans/as/common/model/session/SessionId.java). # Session can be accessed via context.getSessionId() # Typical use is: context.getSessionId().getUser().getAttribute(\"myDisplayName\") # Returns string. If blank string is returned, AS will return built-in implementation to return display name # which is context.getSessionId().getUser().getAttribute(\"displayName\") # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def getAccountDisplayName ( self , context ): return \"\" # This method is called on session selection. # Selected session can be accessed as context.getSessionId() # Return True - continue session selection # Return False - stop session selection (forbid it) # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def onSelect ( self , context ): return True", "title": "Script Type: Python"}, {"location": "script-catalog/select_account/select-account/#script-type-java", "text": "import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import java.util.Map ; /** * @author Yuriy Z */ public class DummySelectAccountType implements SelectAccountType { @Override public String getSelectAccountPage ( Object context ) { return \"\" ; } @Override public boolean prepare ( Object context ) { return true ; } @Override public String getAccountDisplayName ( Object context ) { return \"\" ; } @Override public boolean onSelect ( Object context ) { return false ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public int getApiVersion () { return 1 ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/", "tags": ["administration", "developer", "script-catalog"], "text": "Interface # The Spontaneous scope script implements the SpontaneousScopeType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def manipulateScopes(self, context) This method is called before spontaneous scope is persisted. It's possible to disable persistence via context.setAllowSpontaneousScopePersistence(false) Also it's possible to manipulated already granted scopes, e.g. context.getGrantedScopes().remove(\"transaction:456\") Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference Script Type: Python # # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2020, Janssen # # Author: Yuriy Z # from io.jans.model.custom.script.type.spontaneous import SpontaneousScopeType from java.lang import String class SpontaneousScope ( SpontaneousScopeType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Spontaneous scope script. Initializing ...\" print \"Spontaneous scope script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Spontaneous scope script. Destroying ...\" print \"Spontaneous scope script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # This method is called before spontaneous scope is persisted. It's possible to disable persistence via context.setAllowSpontaneousScopePersistence(false) # Also it's possible to manipulated already granted scopes, e.g. context.getGrantedScopes().remove(\"transaction:456\") # Note : # context is reference of io.jans.as.service.external.context.SpontaneousScopeExternalContext(in https://github.com/JanssenFederation/oxauth project, ) def manipulateScopes ( self , context ): return This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Spontaneous Scope"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#interface", "text": "The Spontaneous scope script implements the SpontaneousScopeType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#new-methods", "text": "Method header Method description def manipulateScopes(self, context) This method is called before spontaneous scope is persisted. It's possible to disable persistence via context.setAllowSpontaneousScopePersistence(false) Also it's possible to manipulated already granted scopes, e.g. context.getGrantedScopes().remove(\"transaction:456\")", "title": "New Methods"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference", "title": "Objects"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#script-type-python", "text": "# oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2020, Janssen # # Author: Yuriy Z # from io.jans.model.custom.script.type.spontaneous import SpontaneousScopeType from java.lang import String class SpontaneousScope ( SpontaneousScopeType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Spontaneous scope script. Initializing ...\" print \"Spontaneous scope script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Spontaneous scope script. Destroying ...\" print \"Spontaneous scope script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # This method is called before spontaneous scope is persisted. It's possible to disable persistence via context.setAllowSpontaneousScopePersistence(false) # Also it's possible to manipulated already granted scopes, e.g. context.getGrantedScopes().remove(\"transaction:456\") # Note : # context is reference of io.jans.as.service.external.context.SpontaneousScopeExternalContext(in https://github.com/JanssenFederation/oxauth project, ) def manipulateScopes ( self , context ): return", "title": "Script Type: Python"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/", "tags": ["administration", "developer", "script-catalog"], "text": "Interface # The UmaClaimsGathering script implements the UmaClaimsGatheringType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def gather(self, step, context): Main gather method. Must return True (if gathering performed successfully) or False (if fail). Method must set claim into context (via context.putClaim('name', value)) in order to persist it (otherwise it will be lost). All user entered values can be access via Map context.getPageClaims() def prepareForStep(self, step, context) ... def getNextStep(self, step, context) ... def getPageForStep(self, step, context) ... Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference Script Type: Python # from io.jans.model.custom.script.type.uma import UmaClaimsGatheringType class UmaClaimsGathering ( UmaClaimsGatheringType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Claims-Gathering. Initializing ...\" print \"Claims-Gathering. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Claims-Gathering. Destroying ...\" print \"Claims-Gathering. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Main gather method. Must return True (if gathering performed successfully) or False (if fail). # Method must set claim into context (via context.putClaim('name', value)) in order to persist it (otherwise it will be lost). # All user entered values can be access via Map<String, String> context.getPageClaims() def gather ( self , step , context ): # context is reference of io.jans.as.uma.authorization.UmaGatherContext print \"Claims-Gathering. Gathering ...\" if step == 1 : if ( context . getPageClaims () . containsKey ( \"country\" )): country = context . getPageClaims () . get ( \"country\" ) print \"Country: \" + country context . putClaim ( \"country\" , country ) return True print \"Claims-Gathering. 'country' is not provided on step 1.\" return False elif step == 2 : if ( context . getPageClaims () . containsKey ( \"city\" )): city = context . getPageClaims () . get ( \"city\" ) print \"City: \" + city context . putClaim ( \"city\" , city ) print \"Claims-Gathering. 'city' is not provided on step 2.\" return True return False def getNextStep ( self , step , context ): return - 1 def prepareForStep ( self , step , context ): if step == 10 and not context . isAuthenticated (): # user is not authenticated, so we are redirecting user to authorization endpoint # client_id is specified via configuration attribute. # Make sure that given client has redirect_uri to Claims-Gathering Endpoint with parameter authentication=true # Sample https://sample.com/restv1/uma/gather_claims?authentication=true # If redirect to external url is performated, make sure that viewAction has onPostback=\"true\" (otherwise redirect will not work) # After user is authenticated then within the script it's possible to get user attributes as # context.getUser(\"uid\", \"sn\") # If user is authenticated to current AS (to the same server, not external one) then it's possible to # access Connect session attributes directly (no need to obtain id_token after redirect with 'code'). # To fetch attributes please use getConnectSessionAttributes() method. print \"User is not authenticated. Redirect for authentication ...\" clientId = context . getConfigurationAttributes () . get ( \"client_id\" ) . getValue2 () redirectUri = context . getClaimsGatheringEndpoint () + \"?authentication=true\" # without authentication=true parameter it will not work authorizationUrl = context . getAuthorizationEndpoint () + \"?client_id=\" + clientId + \"&redirect_uri=\" + redirectUri + \"&scope=openid&response_type=code\" context . redirectToExternalUrl ( authorizationUrl ) # redirect to external url return False if step == 10 and context . isAuthenticated (): # example how to get session attribute if user is authenticated to same AS arc = context . getConnectSessionAttributes () . get ( \"acr\" ) return True def getStepsCount ( self , context ): return 2 def getPageForStep ( self , step , context ): if step == 1 : return \"/uma2/sample/country.xhtml\" elif step == 2 : return \"/uma2/sample/city.xhtml\" return \"\" This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "UMA Claims Gathering (Web Flow)"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#interface", "text": "The UmaClaimsGathering script implements the UmaClaimsGatheringType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#new-methods", "text": "Method header Method description def gather(self, step, context): Main gather method. Must return True (if gathering performed successfully) or False (if fail). Method must set claim into context (via context.putClaim('name', value)) in order to persist it (otherwise it will be lost). All user entered values can be access via Map context.getPageClaims() def prepareForStep(self, step, context) ... def getNextStep(self, step, context) ... def getPageForStep(self, step, context) ...", "title": "New Methods"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference", "title": "Objects"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#script-type-python", "text": "from io.jans.model.custom.script.type.uma import UmaClaimsGatheringType class UmaClaimsGathering ( UmaClaimsGatheringType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Claims-Gathering. Initializing ...\" print \"Claims-Gathering. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Claims-Gathering. Destroying ...\" print \"Claims-Gathering. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Main gather method. Must return True (if gathering performed successfully) or False (if fail). # Method must set claim into context (via context.putClaim('name', value)) in order to persist it (otherwise it will be lost). # All user entered values can be access via Map<String, String> context.getPageClaims() def gather ( self , step , context ): # context is reference of io.jans.as.uma.authorization.UmaGatherContext print \"Claims-Gathering. Gathering ...\" if step == 1 : if ( context . getPageClaims () . containsKey ( \"country\" )): country = context . getPageClaims () . get ( \"country\" ) print \"Country: \" + country context . putClaim ( \"country\" , country ) return True print \"Claims-Gathering. 'country' is not provided on step 1.\" return False elif step == 2 : if ( context . getPageClaims () . containsKey ( \"city\" )): city = context . getPageClaims () . get ( \"city\" ) print \"City: \" + city context . putClaim ( \"city\" , city ) print \"Claims-Gathering. 'city' is not provided on step 2.\" return True return False def getNextStep ( self , step , context ): return - 1 def prepareForStep ( self , step , context ): if step == 10 and not context . isAuthenticated (): # user is not authenticated, so we are redirecting user to authorization endpoint # client_id is specified via configuration attribute. # Make sure that given client has redirect_uri to Claims-Gathering Endpoint with parameter authentication=true # Sample https://sample.com/restv1/uma/gather_claims?authentication=true # If redirect to external url is performated, make sure that viewAction has onPostback=\"true\" (otherwise redirect will not work) # After user is authenticated then within the script it's possible to get user attributes as # context.getUser(\"uid\", \"sn\") # If user is authenticated to current AS (to the same server, not external one) then it's possible to # access Connect session attributes directly (no need to obtain id_token after redirect with 'code'). # To fetch attributes please use getConnectSessionAttributes() method. print \"User is not authenticated. Redirect for authentication ...\" clientId = context . getConfigurationAttributes () . get ( \"client_id\" ) . getValue2 () redirectUri = context . getClaimsGatheringEndpoint () + \"?authentication=true\" # without authentication=true parameter it will not work authorizationUrl = context . getAuthorizationEndpoint () + \"?client_id=\" + clientId + \"&redirect_uri=\" + redirectUri + \"&scope=openid&response_type=code\" context . redirectToExternalUrl ( authorizationUrl ) # redirect to external url return False if step == 10 and context . isAuthenticated (): # example how to get session attribute if user is authenticated to same AS arc = context . getConnectSessionAttributes () . get ( \"acr\" ) return True def getStepsCount ( self , context ): return 2 def getPageForStep ( self , step , context ): if step == 1 : return \"/uma2/sample/country.xhtml\" elif step == 2 : return \"/uma2/sample/city.xhtml\" return \"\"", "title": "Script Type: Python"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/", "tags": ["administration", "developer", "script-catalog"], "text": "Interface # The UmaRptClaims script implements the UmaRptClaimsType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def modify(self, rptAsJsonObject, context) responseAsJsonObject - is org.codehaus.jettison.json.JSONObject , you can use any method to manipulate json. context is reference of io.jans.as.service.external.context.ExternalUmaRptClaimsContext (in https://github.com/JanssenFederation/oxauth project, ) Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference Script Type: Python # from io.jans.model.custom.script.type.uma import UmaRptClaimsType from java.lang import String class UmaRptClaims ( UmaRptClaimsType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"RPT Claims script. Initializing ...\" print \"RPT Claims script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"RPT Claims script. Destroying ...\" print \"RPT Claims script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply changes from script method, false - ignore it. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.service.external.context.ExternalUmaRptClaimsContext (in https://github.com/JanssenFederation/oxauth project, ) def modify ( self , rptAsJsonObject , context ): rptAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "UMA Claims (JWT Transformation)"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#interface", "text": "The UmaRptClaims script implements the UmaRptClaimsType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#new-methods", "text": "Method header Method description def modify(self, rptAsJsonObject, context) responseAsJsonObject - is org.codehaus.jettison.json.JSONObject , you can use any method to manipulate json. context is reference of io.jans.as.service.external.context.ExternalUmaRptClaimsContext (in https://github.com/JanssenFederation/oxauth project, )", "title": "New Methods"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference", "title": "Objects"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#script-type-python", "text": "from io.jans.model.custom.script.type.uma import UmaRptClaimsType from java.lang import String class UmaRptClaims ( UmaRptClaimsType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"RPT Claims script. Initializing ...\" print \"RPT Claims script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"RPT Claims script. Destroying ...\" print \"RPT Claims script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply changes from script method, false - ignore it. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.service.external.context.ExternalUmaRptClaimsContext (in https://github.com/JanssenFederation/oxauth project, ) def modify ( self , rptAsJsonObject , context ): rptAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True", "title": "Script Type: Python"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/", "tags": ["administration", "developer", "script-catalog", "UmaRptPolicy"], "text": "Overview # This is a special script for UMA. It allows an admin to protect UMA scopes with policies. It is possible to add more than one UMA policy to an UMA scope. On requesting access to a specified resource, the application should call specified UMA policies in order to grant or deny access. Interface # The UMA RPT Authorization Policy script implements the UmaRptPolicyType interface. This extends methods from the base script type in addition to adding new method: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def getRequiredClaims(self, authorizationContext) Returns required claims definitions. This method must provide definition of all claims that is used in 'authorize' method. Return empty array [] if no claims should be gathered. Note : name in both places must match. %1$s - placeholder for issuer. It uses standard Java Formatter, docs : https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html def authorize(self, authorizationContext) Main authorization method. Must return True or False. def getClaimsGatheringScriptName(self, authorizationContext) Returns name of the Claims-Gathering script which will be invoked if need_info error is returned. Return blank/empty string if claims gathering flow is not involved. Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference ClaimDefinition Reference Use case: Request Country and City Policies # This script was adapted from the Gluu Server UMA RPT Authorization Script . Script Type: Python # from io.jans.model.custom.script.type.uma import UmaRptPolicyType from io.jans.model.uma import ClaimDefinitionBuilder from java.lang import String class UmaRptPolicy ( UmaRptPolicyType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"RPT Policy. Initializing ...\" print \"RPT Policy. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"RPT Policy. Destroying ...\" print \"RPT Policy. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Returns required claims definitions. # This method must provide definition of all claims that is used in 'authorize' method. # Return empty array `[]` if no claims should be gathered. # Note : name in both places must match. # %1$s - placeholder for issuer. It uses standard Java Formatter, docs : https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html def getRequiredClaims ( self , context ): json = \"\"\"[ { \"issuer\" : [ \"%1$s\" ], \"name\" : \"country\", \"claim_token_format\" : [ \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], \"claim_type\" : \"string\", \"friendly_name\" : \"country\" }, { \"issuer\" : [ \"%1$s\" ], \"name\" : \"city\", \"claim_token_format\" : [ \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], \"claim_type\" : \"string\", \"friendly_name\" : \"city\" } ]\"\"\" context . addRedirectUserParam ( \"customUserParam1\" , \"value1\" ) # pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. return ClaimDefinitionBuilder . build ( String . format ( json , context . getIssuer ())) # Main authorization method. Must return True or False. def authorize ( self , context ): print \"RPT Policy. Authorizing ...\" if context . getClaim ( \"country\" ) == 'US' and context . getClaim ( \"city\" ) == 'NY' : print \"Authorized successfully!\" return True return False # Returns name of the Claims-Gathering script which will be invoked if need_info error is returned. Return blank/empty string if claims gathering flow is not involved. def getClaimsGatheringScriptName ( self , context ): context . addRedirectUserParam ( \"customUserParam2\" , \"value2\" ) # pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. return \"sampleClaimsGathering\" Script Type: Java # import java.util.List ; import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.uma.UmaRptPolicyType ; import io.jans.model.uma.ClaimDefinition ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.uma.authorization.UmaAuthorizationContext ; import io.jans.model.uma.ClaimDefinitionBuilder ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class UmaRptPolicy implements UmaRptPolicyType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Initializing...\" ); log . info ( \"UMA RPT Policy Authorization. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Initializing...\" ); log . info ( \"UMA RPT Policy Authorization. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Destroying...\" ); log . info ( \"UMA RPT Policy Authorization. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public List < ClaimDefinition > getRequiredClaims ( Object authorizationContext ) { /* needs to be a valid JSON string * Sample: [ { \"issuer\" : [ \"https://example.com\" ], \"name\" : * \"country\", \"claim_token_format\" : [ * \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], * \"claim_type\" : \"string\", \"friendly_name\" : \"country\" } ] * */ String json = \"\" ; UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; authContext . addRedirectUserParam ( \"customUserParam1\" , \"value1\" ); return ClaimDefinitionBuilder . build ( String . format ( json , authContext . getIssuer ())); } @Override public boolean authorize ( Object authorizationContext ) { log . info ( \"UMA RPT Policy Authorization. Authorizing...\" ); UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; if ( authContext . getClaim ( \"country\" ). equals ( \"US\" ) && authContext . getClaim ( \"city\" ). equals ( \"NY\" )) { log . info ( \"Authorized successfully!\" ); return true ; } return false ; } @Override public String getClaimsGatheringScriptName ( Object authorizationContext ) { UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; // pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. authContext . addRedirectUserParam ( \"customUserParam2\" , \"value2\" ); return \"sampleClaimsGathering\" ; } }", "title": "UMA RPT Policies"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#overview", "text": "This is a special script for UMA. It allows an admin to protect UMA scopes with policies. It is possible to add more than one UMA policy to an UMA scope. On requesting access to a specified resource, the application should call specified UMA policies in order to grant or deny access.", "title": "Overview"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#interface", "text": "The UMA RPT Authorization Policy script implements the UmaRptPolicyType interface. This extends methods from the base script type in addition to adding new method:", "title": "Interface"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#new-methods", "text": "Method header Method description def getRequiredClaims(self, authorizationContext) Returns required claims definitions. This method must provide definition of all claims that is used in 'authorize' method. Return empty array [] if no claims should be gathered. Note : name in both places must match. %1$s - placeholder for issuer. It uses standard Java Formatter, docs : https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html def authorize(self, authorizationContext) Main authorization method. Must return True or False. def getClaimsGatheringScriptName(self, authorizationContext) Returns name of the Claims-Gathering script which will be invoked if need_info error is returned. Return blank/empty string if claims gathering flow is not involved.", "title": "New Methods"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference ClaimDefinition Reference", "title": "Objects"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#use-case-request-country-and-city-policies", "text": "This script was adapted from the Gluu Server UMA RPT Authorization Script .", "title": "Use case: Request Country and City Policies"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#script-type-python", "text": "from io.jans.model.custom.script.type.uma import UmaRptPolicyType from io.jans.model.uma import ClaimDefinitionBuilder from java.lang import String class UmaRptPolicy ( UmaRptPolicyType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"RPT Policy. Initializing ...\" print \"RPT Policy. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"RPT Policy. Destroying ...\" print \"RPT Policy. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Returns required claims definitions. # This method must provide definition of all claims that is used in 'authorize' method. # Return empty array `[]` if no claims should be gathered. # Note : name in both places must match. # %1$s - placeholder for issuer. It uses standard Java Formatter, docs : https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html def getRequiredClaims ( self , context ): json = \"\"\"[ { \"issuer\" : [ \"%1$s\" ], \"name\" : \"country\", \"claim_token_format\" : [ \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], \"claim_type\" : \"string\", \"friendly_name\" : \"country\" }, { \"issuer\" : [ \"%1$s\" ], \"name\" : \"city\", \"claim_token_format\" : [ \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], \"claim_type\" : \"string\", \"friendly_name\" : \"city\" } ]\"\"\" context . addRedirectUserParam ( \"customUserParam1\" , \"value1\" ) # pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. return ClaimDefinitionBuilder . build ( String . format ( json , context . getIssuer ())) # Main authorization method. Must return True or False. def authorize ( self , context ): print \"RPT Policy. Authorizing ...\" if context . getClaim ( \"country\" ) == 'US' and context . getClaim ( \"city\" ) == 'NY' : print \"Authorized successfully!\" return True return False # Returns name of the Claims-Gathering script which will be invoked if need_info error is returned. Return blank/empty string if claims gathering flow is not involved. def getClaimsGatheringScriptName ( self , context ): context . addRedirectUserParam ( \"customUserParam2\" , \"value2\" ) # pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. return \"sampleClaimsGathering\"", "title": "Script Type: Python"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#script-type-java", "text": "import java.util.List ; import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.uma.UmaRptPolicyType ; import io.jans.model.uma.ClaimDefinition ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.uma.authorization.UmaAuthorizationContext ; import io.jans.model.uma.ClaimDefinitionBuilder ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class UmaRptPolicy implements UmaRptPolicyType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Initializing...\" ); log . info ( \"UMA RPT Policy Authorization. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Initializing...\" ); log . info ( \"UMA RPT Policy Authorization. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Destroying...\" ); log . info ( \"UMA RPT Policy Authorization. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public List < ClaimDefinition > getRequiredClaims ( Object authorizationContext ) { /* needs to be a valid JSON string * Sample: [ { \"issuer\" : [ \"https://example.com\" ], \"name\" : * \"country\", \"claim_token_format\" : [ * \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], * \"claim_type\" : \"string\", \"friendly_name\" : \"country\" } ] * */ String json = \"\" ; UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; authContext . addRedirectUserParam ( \"customUserParam1\" , \"value1\" ); return ClaimDefinitionBuilder . build ( String . format ( json , authContext . getIssuer ())); } @Override public boolean authorize ( Object authorizationContext ) { log . info ( \"UMA RPT Policy Authorization. Authorizing...\" ); UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; if ( authContext . getClaim ( \"country\" ). equals ( \"US\" ) && authContext . getClaim ( \"city\" ). equals ( \"NY\" )) { log . info ( \"Authorized successfully!\" ); return true ; } return false ; } @Override public String getClaimsGatheringScriptName ( Object authorizationContext ) { UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; // pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. authContext . addRedirectUserParam ( \"customUserParam2\" , \"value2\" ); return \"sampleClaimsGathering\" ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/update_token/update-token/", "tags": ["administration", "developer", "script-catalog"], "text": "Overview # By overriding the interface methods in UpdateTokenType inside a custom script you can Enable transformation of claims and values in id_token and Access token e.g. add a custom claim to an id_token , change a token expiry, change the sub value, or remove the nonce . Example use-case: * As per the open banking standard, the id_token should contain claim openbanking_intent_id and the same value should also reflect in the sub claim. * As specified in the FAPI Baseline Specification the sub claim should have the user id. Set a specific token lifetime Perform extra business logic like adding or removing scopes. Add an extra audit log for each token response. Flow # sequenceDiagram title UpdateToken script autonumber 1 RP->>Jans AS: Request token Jans AS->>Jans AS: Is UpdateToken script is associated with client? <br/>(or is there a script that applies to all clients? ) Jans AS->>Jans AS: do stuff note right of Jans AS: do stuff<br/>1. Enable transformation of claims and values in id_token <br/> OR 2. set token expiry <br/> or 3. add / remove scopes. <br/> or 4. perform audit logs Jans AS->>RP: return token(s) (Access token, ID token or Refresh Token) reflecting step 3 Adding the custom script to Jans server # Create cs.json with the contents of a CUSTOM script. To do that, run the following command. /opt/jans/jans-cli/config-cli.py --schema CustomScript > /tmp/cs.json Edit the file's contents to reflect the addition of the UpdateToken custom script. Set enabled flag true Configure any parameters that the script may use. name field should reflect the use case script_type should be UPDATE_TOKEN script.py can have contents similar to Sample Script ) and is present in jans-cli's host machine. { \"dn\": null, \"inum\": null, \"name\": \"update_token\", \"aliases\": [], \"description\": \"Update token custom script\", \"script\": \"_file /root/script.py\", \"scriptType\": \"UPDATE_TOKEN\", \"programmingLanguage\": \"JYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": [ { \"value1\": \"param_name\", \"value2\": \"DI3ICTTJKLL8PPPNGH7YI\", \"description\": \"This is just an example\", \"hide\": true }, { \"value1\": \"param_name_2\", \"value2\": \"eEbJdi3hg42zxyFYbHArU5RuioPP\", \"description\": \"yet another example\", \"hide\": true } ] , \"level\": \"integer\", \"revision\": 0, \"enabled\": true, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } Add the custom script. Save the response, it will contain the inum of the newly added script. /opt/jans/jans-cli/config-cli.py --operation-id post-config-scripts --data /tmp/cs.json Associate an Update Token script to a client (RP) [optional step] # \ud83d\udcdd Note: If the Update token script is not associated with a client, then it will be applicable to all clients registered in the Jans Server. Which implies that all tokens obtained using the Jans server will reflect modifications as per the script. To Associate an Update Token script to a client (RP), execute the command below with appropriate values for: - inum of the client - inum of the update_token script /opt/jans/jans-cli/config-cli.py --operation-id patch-oauth-openid-clients-by-inum --url-suffix inum:inum_of_client --data '[ { \"op\": \"add\", \"path\": \"updateTokenScriptDns\", \"value\": [\"inum={SCRIPT_ID},ou=scripts,o=jans\"] } ]' Writing an Update token script (Pseudo code for potential usecases) # Mandatory methods # class UpdateToken(UpdateTokenType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): return True def destroy(self, configurationAttributes): return True def getApiVersion(self): return 11 modifyIdToken () : Used to modify claims in an ID token # Pseudocode and example : # Returns boolean, true - indicates that script applied changes # jsonWebResponse - is JwtHeader, you can use any method to manipulate JWT # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyIdToken(self, jsonWebResponse, context): # header claims jsonWebResponse.getHeader().setClaim(\"header_name\", \"header_value\") #custom claims jsonWebResponse.getClaims().setClaim(\"openbanking_intent_id\", openbanking_intent_id_value) #regular claims jsonWebResponse.getClaims().setClaim(\"sub\", claimValue) return True modifyAccessToken() # Granularity of access control # An UpdateTokenType script is great for adding scopes or removing scopes to/from the Access token. By doing so you can tailor build the granularity of access control according to business need. context.overwriteAccessTokenScopes is ready to use method of the context variable def modifyAccessToken(self, accessToken, context): context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"openid\", \"mynewscope\")) Perform business check before returning AT # Pseudocode and example - Issue Access token only if account balance is greater than 0 # Returns boolean, true - indicates that script applied changes # accessToken - is JwtHeader, you can use any method to manipulate JWT # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence org_id = sessionId.getSessionAttributes().get(\"org_id\") balance = thirdPartyApi.checkBalance(org_id) if balance > 0 : return True else: return False # forbid the creation of AT Modify claims in an access token # # Returns boolean, true - indicates that script applied changes. If false is returned token will not be created. # accessToken is reference of io.jans.as.server.model.common.AccessToken (note authorization grant can be taken as context.getGrant()) # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyAccessToken(self, accessToken, context): # header claims context.getHeader().setClaim(\"header_name\", \"header_value\") #custom claims context.getClaims().setClaim(\"claim_name\", \"claimValue\") #regular claims context.getClaims().setClaim(\"sub\", claimValue) return True Modify a specific token lifetime based on the context # Refresh token lifetime: def getRefreshTokenLifetimeInSeconds(self, context): return 24 * 60 * 60 # one day ID token lifetime: def getIdTokenLifetimeInSeconds(self, context): return 10 * 60 * 60 # 10 hours Access token lifetime: def getAccessTokenLifetimeInSeconds(self, context): return 10 * 60 * 60 # 10 hours Access token lifetime from script has highest priority (it wins from client's access token lifetime configuration). modifyRefreshToken() : # Used to modify claims in a Refresh Token # Returns boolean, true - indicates that script applied changes. If false is returned token will not be created. # refreshToken is reference of io.jans.as.server.model.common.RefreshToken (note authorization grant can be taken as context.getGrant()) # context is reference of io.jans.as.server.service.external.context.ExternalUpdateTokenContext (in https://github.com/JanssenProject/jans-auth-server project, ) def modifyRefreshToken(self, refreshToken, context): return True IntrospectionType script vs UpdateTokenType script # IntrospectionType UpdateTokenType Client configuration parameter Introspection script is invoked only when accessTokenAsJwt = true Update token script is invoked irrespective of whether accessTokenAsJwt is true or false Core Purpose Used to return access token meta information like current validity, approved scopes, and information about the context in which the token was issued when a Resource Server which queries the Introspection endpoint used to enable transformation of claims and values in id_token and Access token, set a specific token lifetime, change granularity of access control (up-scoping, down-scoping), audit logging for each token response, forbid the creation of AT based on a criteria. Functionality 1. Can be used to modify claims of an Access token as JWT, however this it is recommended to use UpdateToken script instead. 1. Used to modify id_token, refresh token and access token 2. Introspection script cannot change scope of AT 2. UpdateToken can change scope of AT and modify AT object in persistence irrespective of the value of accessTokenAsJwt as true or false Script Invocation sequence 2. After an Access token is generated 2. Before the creation of AT, id_token and refresh_token Testing # Use this: Reference for testing Inspect the tokens. Use jwt.io to inspect the contents of a JWT. FAQ # How can I add a dict type object as a claim value? from io.jans.as.model.uti import JwtUtil from org.json import JSONObject; def modifyIdToken(self, jsonWebResponse, context): datas = {'country': 'ID', 'sponsor': '7022952467', 'role': 'BusinessOwner', 'salesplanaff': '220', 'acctsubtype': 'BusinessOwner', 'accttype': 'AmBCBusiness', 'abo': '7022953754', 'aboname': 'NEW', 'lclpartyid': '119700175', 'email': None, 'status': 'Active'} string_rep = json.dumps(datas) jsonObject = JwtUtil.fromJson(string_rep) jsonWebResponse.getClaims().setClaim(\"test\", jsonObject) print \"Update token script. Modify idToken: %s\" % jsonWebResponse return True 2. How can I set integer value in id token claim? jsonWebResponse.getClaims().setClaim(\"claimY\", Integer.valueOf(124456191)) Get it as integer, via getClaims().getClaimAsInteger(\"claimY\")", "title": "Update Token"}, {"location": "script-catalog/update_token/update-token/#overview", "text": "By overriding the interface methods in UpdateTokenType inside a custom script you can Enable transformation of claims and values in id_token and Access token e.g. add a custom claim to an id_token , change a token expiry, change the sub value, or remove the nonce . Example use-case: * As per the open banking standard, the id_token should contain claim openbanking_intent_id and the same value should also reflect in the sub claim. * As specified in the FAPI Baseline Specification the sub claim should have the user id. Set a specific token lifetime Perform extra business logic like adding or removing scopes. Add an extra audit log for each token response.", "title": "Overview"}, {"location": "script-catalog/update_token/update-token/#flow", "text": "sequenceDiagram title UpdateToken script autonumber 1 RP->>Jans AS: Request token Jans AS->>Jans AS: Is UpdateToken script is associated with client? <br/>(or is there a script that applies to all clients? ) Jans AS->>Jans AS: do stuff note right of Jans AS: do stuff<br/>1. Enable transformation of claims and values in id_token <br/> OR 2. set token expiry <br/> or 3. add / remove scopes. <br/> or 4. perform audit logs Jans AS->>RP: return token(s) (Access token, ID token or Refresh Token) reflecting step 3", "title": "Flow"}, {"location": "script-catalog/update_token/update-token/#adding-the-custom-script-to-jans-server", "text": "Create cs.json with the contents of a CUSTOM script. To do that, run the following command. /opt/jans/jans-cli/config-cli.py --schema CustomScript > /tmp/cs.json Edit the file's contents to reflect the addition of the UpdateToken custom script. Set enabled flag true Configure any parameters that the script may use. name field should reflect the use case script_type should be UPDATE_TOKEN script.py can have contents similar to Sample Script ) and is present in jans-cli's host machine. { \"dn\": null, \"inum\": null, \"name\": \"update_token\", \"aliases\": [], \"description\": \"Update token custom script\", \"script\": \"_file /root/script.py\", \"scriptType\": \"UPDATE_TOKEN\", \"programmingLanguage\": \"JYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": [ { \"value1\": \"param_name\", \"value2\": \"DI3ICTTJKLL8PPPNGH7YI\", \"description\": \"This is just an example\", \"hide\": true }, { \"value1\": \"param_name_2\", \"value2\": \"eEbJdi3hg42zxyFYbHArU5RuioPP\", \"description\": \"yet another example\", \"hide\": true } ] , \"level\": \"integer\", \"revision\": 0, \"enabled\": true, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } Add the custom script. Save the response, it will contain the inum of the newly added script. /opt/jans/jans-cli/config-cli.py --operation-id post-config-scripts --data /tmp/cs.json", "title": "Adding the custom script to Jans server"}, {"location": "script-catalog/update_token/update-token/#associate-an-update-token-script-to-a-client-rp-optional-step", "text": "\ud83d\udcdd Note: If the Update token script is not associated with a client, then it will be applicable to all clients registered in the Jans Server. Which implies that all tokens obtained using the Jans server will reflect modifications as per the script. To Associate an Update Token script to a client (RP), execute the command below with appropriate values for: - inum of the client - inum of the update_token script /opt/jans/jans-cli/config-cli.py --operation-id patch-oauth-openid-clients-by-inum --url-suffix inum:inum_of_client --data '[ { \"op\": \"add\", \"path\": \"updateTokenScriptDns\", \"value\": [\"inum={SCRIPT_ID},ou=scripts,o=jans\"] } ]'", "title": "Associate an Update Token script to a client (RP) [optional step]"}, {"location": "script-catalog/update_token/update-token/#writing-an-update-token-script-pseudo-code-for-potential-usecases", "text": "", "title": "Writing an Update token script (Pseudo code for potential usecases)"}, {"location": "script-catalog/update_token/update-token/#mandatory-methods", "text": "class UpdateToken(UpdateTokenType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): return True def destroy(self, configurationAttributes): return True def getApiVersion(self): return 11", "title": "Mandatory methods"}, {"location": "script-catalog/update_token/update-token/#modifyidtoken-used-to-modify-claims-in-an-id-token", "text": "Pseudocode and example : # Returns boolean, true - indicates that script applied changes # jsonWebResponse - is JwtHeader, you can use any method to manipulate JWT # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyIdToken(self, jsonWebResponse, context): # header claims jsonWebResponse.getHeader().setClaim(\"header_name\", \"header_value\") #custom claims jsonWebResponse.getClaims().setClaim(\"openbanking_intent_id\", openbanking_intent_id_value) #regular claims jsonWebResponse.getClaims().setClaim(\"sub\", claimValue) return True", "title": "modifyIdToken () : Used to modify claims in an ID token"}, {"location": "script-catalog/update_token/update-token/#modifyaccesstoken", "text": "", "title": "modifyAccessToken()"}, {"location": "script-catalog/update_token/update-token/#granularity-of-access-control", "text": "An UpdateTokenType script is great for adding scopes or removing scopes to/from the Access token. By doing so you can tailor build the granularity of access control according to business need. context.overwriteAccessTokenScopes is ready to use method of the context variable def modifyAccessToken(self, accessToken, context): context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"openid\", \"mynewscope\"))", "title": "Granularity of access control"}, {"location": "script-catalog/update_token/update-token/#perform-business-check-before-returning-at", "text": "Pseudocode and example - Issue Access token only if account balance is greater than 0 # Returns boolean, true - indicates that script applied changes # accessToken - is JwtHeader, you can use any method to manipulate JWT # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence org_id = sessionId.getSessionAttributes().get(\"org_id\") balance = thirdPartyApi.checkBalance(org_id) if balance > 0 : return True else: return False # forbid the creation of AT", "title": "Perform business check before returning AT"}, {"location": "script-catalog/update_token/update-token/#modify-claims-in-an-access-token", "text": "# Returns boolean, true - indicates that script applied changes. If false is returned token will not be created. # accessToken is reference of io.jans.as.server.model.common.AccessToken (note authorization grant can be taken as context.getGrant()) # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyAccessToken(self, accessToken, context): # header claims context.getHeader().setClaim(\"header_name\", \"header_value\") #custom claims context.getClaims().setClaim(\"claim_name\", \"claimValue\") #regular claims context.getClaims().setClaim(\"sub\", claimValue) return True", "title": "Modify claims in an access token"}, {"location": "script-catalog/update_token/update-token/#modify-a-specific-token-lifetime-based-on-the-context", "text": "Refresh token lifetime: def getRefreshTokenLifetimeInSeconds(self, context): return 24 * 60 * 60 # one day ID token lifetime: def getIdTokenLifetimeInSeconds(self, context): return 10 * 60 * 60 # 10 hours Access token lifetime: def getAccessTokenLifetimeInSeconds(self, context): return 10 * 60 * 60 # 10 hours Access token lifetime from script has highest priority (it wins from client's access token lifetime configuration).", "title": "Modify a specific token lifetime based on the context"}, {"location": "script-catalog/update_token/update-token/#modifyrefreshtoken", "text": "Used to modify claims in a Refresh Token # Returns boolean, true - indicates that script applied changes. If false is returned token will not be created. # refreshToken is reference of io.jans.as.server.model.common.RefreshToken (note authorization grant can be taken as context.getGrant()) # context is reference of io.jans.as.server.service.external.context.ExternalUpdateTokenContext (in https://github.com/JanssenProject/jans-auth-server project, ) def modifyRefreshToken(self, refreshToken, context): return True", "title": "modifyRefreshToken() :"}, {"location": "script-catalog/update_token/update-token/#introspectiontype-script-vs-updatetokentype-script", "text": "IntrospectionType UpdateTokenType Client configuration parameter Introspection script is invoked only when accessTokenAsJwt = true Update token script is invoked irrespective of whether accessTokenAsJwt is true or false Core Purpose Used to return access token meta information like current validity, approved scopes, and information about the context in which the token was issued when a Resource Server which queries the Introspection endpoint used to enable transformation of claims and values in id_token and Access token, set a specific token lifetime, change granularity of access control (up-scoping, down-scoping), audit logging for each token response, forbid the creation of AT based on a criteria. Functionality 1. Can be used to modify claims of an Access token as JWT, however this it is recommended to use UpdateToken script instead. 1. Used to modify id_token, refresh token and access token 2. Introspection script cannot change scope of AT 2. UpdateToken can change scope of AT and modify AT object in persistence irrespective of the value of accessTokenAsJwt as true or false Script Invocation sequence 2. After an Access token is generated 2. Before the creation of AT, id_token and refresh_token", "title": "IntrospectionType script vs UpdateTokenType script"}, {"location": "script-catalog/update_token/update-token/#testing", "text": "Use this: Reference for testing Inspect the tokens. Use jwt.io to inspect the contents of a JWT.", "title": "Testing"}, {"location": "script-catalog/update_token/update-token/#faq", "text": "How can I add a dict type object as a claim value? from io.jans.as.model.uti import JwtUtil from org.json import JSONObject; def modifyIdToken(self, jsonWebResponse, context): datas = {'country': 'ID', 'sponsor': '7022952467', 'role': 'BusinessOwner', 'salesplanaff': '220', 'acctsubtype': 'BusinessOwner', 'accttype': 'AmBCBusiness', 'abo': '7022953754', 'aboname': 'NEW', 'lclpartyid': '119700175', 'email': None, 'status': 'Active'} string_rep = json.dumps(datas) jsonObject = JwtUtil.fromJson(string_rep) jsonWebResponse.getClaims().setClaim(\"test\", jsonObject) print \"Update token script. Modify idToken: %s\" % jsonWebResponse return True 2. How can I set integer value in id token claim? jsonWebResponse.getClaims().setClaim(\"claimY\", Integer.valueOf(124456191)) Get it as integer, via getClaims().getClaimAsInteger(\"claimY\")", "title": "FAQ"}]} \ No newline at end of file +{"config": {"indexing": "full", "lang": ["en"], "min_search_length": 3, "prebuild_index": false, "separator": "[\\s\\-]+"}, "docs": [{"location": "", "text": "Janssen Project Documentation # Introduction # Janssen is a distribution of open source identity components which organizations can use to build a scalable federated authentication and authorization service. This documentation is always work in progress. Please help to make it better by submitting a PR if you can think of any way to improve it! Administration Guide # Read the Administration guide to learn how to deploy, operate and maintain the Janssen components. Planning your solution using the Deployment Guide . An easy way to get started is to try Janssen on an VM, see Installation or check the other docs for Kubernetes based installation. Contribution Guide # There are many ways the community can contribute to the Janssen Project. Of course, you can contribute code. But we also need people to write documentation and guides, to help us with testing, to answer questions on the forums and chat, to review PRs, to help us with devops and CI/CD, to provide feedback on usability, and to promote the project through outreach. Also, by sharing metrics with us, we can gain valuable insights into how the software performs in the wild. Resources to get started are available here . Governance Guide # The Janssen Project is chartered under the Linux Foundation. Information about the project's governance can be found here . Script Catalog # Interception scripts (or custom scripts) allow you to define custom business logic for various features in Janssen without forking the Jans Server core project. Interceptions scripts are available for many components, including Auth Server, SCIM, FIDO, and Link. The definitive location for scripts and their documentation is the Script Catalog . Agama # Agama is a domain specific language (\"DSL\") designed for writing web flows, and a project archive format (\".gama\") which stores all the code and web assets required for deployment of an Agama project by an identity provider. Although invented by Janssen, we envision many IDP's using Agama as a cross-vendor standard for identity orchestration. Support # If you have any questions about usage, post on Jans Discussions or try community chat on Gitter . If you find a bug in a Janssen project, or you would like to suggest a new feature, you should also post on GitHub Discussions first. The Jans team will try to replicate the bug, or weigh the feature request versus current priorities. License # Most Janssen Project components are licensed under the Apache License 2.0 . Janssen has some third party components, so it's always best to check the license for each component. We won't include any component in the distribution that has a non- OSI approved license, or a commercial trademark. Looking for older documentation versions? # The Janssen Project posts the last five versions of the documentation. If you are looking for older versions, you can find them unprocessed in the docs folder. Select the version of choice from the tag dropdown in GitHub. If you want to process them you may do so following the steps here .", "title": "Janssen Project Documentation"}, {"location": "#janssen-project-documentation", "text": "", "title": "Janssen Project Documentation"}, {"location": "#introduction", "text": "Janssen is a distribution of open source identity components which organizations can use to build a scalable federated authentication and authorization service. This documentation is always work in progress. Please help to make it better by submitting a PR if you can think of any way to improve it!", "title": "Introduction"}, {"location": "#administration-guide", "text": "Read the Administration guide to learn how to deploy, operate and maintain the Janssen components. Planning your solution using the Deployment Guide . An easy way to get started is to try Janssen on an VM, see Installation or check the other docs for Kubernetes based installation.", "title": "Administration Guide"}, {"location": "#contribution-guide", "text": "There are many ways the community can contribute to the Janssen Project. Of course, you can contribute code. But we also need people to write documentation and guides, to help us with testing, to answer questions on the forums and chat, to review PRs, to help us with devops and CI/CD, to provide feedback on usability, and to promote the project through outreach. Also, by sharing metrics with us, we can gain valuable insights into how the software performs in the wild. Resources to get started are available here .", "title": "Contribution Guide"}, {"location": "#governance-guide", "text": "The Janssen Project is chartered under the Linux Foundation. Information about the project's governance can be found here .", "title": "Governance Guide"}, {"location": "#script-catalog", "text": "Interception scripts (or custom scripts) allow you to define custom business logic for various features in Janssen without forking the Jans Server core project. Interceptions scripts are available for many components, including Auth Server, SCIM, FIDO, and Link. The definitive location for scripts and their documentation is the Script Catalog .", "title": "Script Catalog"}, {"location": "#agama", "text": "Agama is a domain specific language (\"DSL\") designed for writing web flows, and a project archive format (\".gama\") which stores all the code and web assets required for deployment of an Agama project by an identity provider. Although invented by Janssen, we envision many IDP's using Agama as a cross-vendor standard for identity orchestration.", "title": "Agama"}, {"location": "#support", "text": "If you have any questions about usage, post on Jans Discussions or try community chat on Gitter . If you find a bug in a Janssen project, or you would like to suggest a new feature, you should also post on GitHub Discussions first. The Jans team will try to replicate the bug, or weigh the feature request versus current priorities.", "title": "Support"}, {"location": "#license", "text": "Most Janssen Project components are licensed under the Apache License 2.0 . Janssen has some third party components, so it's always best to check the license for each component. We won't include any component in the distribution that has a non- OSI approved license, or a commercial trademark.", "title": "License"}, {"location": "#looking-for-older-documentation-versions", "text": "The Janssen Project posts the last five versions of the documentation. If you are looking for older versions, you can find them unprocessed in the docs folder. Select the version of choice from the tag dropdown in GitHub. If you want to process them you may do so following the steps here .", "title": "Looking for older documentation versions?"}, {"location": "CODE_OF_CONDUCT/", "text": "Janssen Code of Conduct v1.0 # Our Pledge # In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. Our Standards # Examples of behavior that contributes to creating a positive environment include: Using welcoming and inclusive language Being respectful of differing viewpoints and experiences Gracefully accepting constructive criticism Focusing on what is best for the community Showing empathy towards other community members Examples of unacceptable behavior by participants include: The use of sexualized language or imagery and unwelcome sexual attention or advances Trolling, insulting/derogatory comments, and personal or political attacks Public or private harassment Publishing others\u2019 private information, such as a physical or electronic address, without explicit permission Other conduct which could reasonably be considered inappropriate in a professional setting Our Responsibilities # Janssen Project members, project participants and contributors (collectively, \"participants\") are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. The Technical Steering Committee (\"TSC\") of the Janssen Project has the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any participant for other behaviors that they deem inappropriate, threatening, offensive, or harmful. All participants have determined that The Linux Foundation is the most optimal organization to shepherd the development of this project. Participants acknowledge and agree to The Linux Foundation's exclusive right to use \"Janssen Project\" and any other names and trademarks associated with the open source project and Janssen Project and to authorize others\u2019 use of the marks, establish guidelines for such use, and to delegate these responsibilities. Participants agree not to take any action inconsistent with such rights and to cooperate in any action which The Linux Foundation deems necessary or desirable to prevent confusion or establish or preserve these rights. Participants will not independently adopt, use, or attempt to register any trademarks or trade names that are confusingly similar to these names. Scope # This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. Enforcement # Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Executive Director, or, if the complaint involves the Executive Director, a member of the steering committee. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Participants who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by the steering committee. Attribution # This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html . For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq", "title": "Code of Conduct"}, {"location": "CODE_OF_CONDUCT/#janssen-code-of-conduct-v10", "text": "", "title": "Janssen Code of Conduct v1.0"}, {"location": "CODE_OF_CONDUCT/#our-pledge", "text": "In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.", "title": "Our Pledge"}, {"location": "CODE_OF_CONDUCT/#our-standards", "text": "Examples of behavior that contributes to creating a positive environment include: Using welcoming and inclusive language Being respectful of differing viewpoints and experiences Gracefully accepting constructive criticism Focusing on what is best for the community Showing empathy towards other community members Examples of unacceptable behavior by participants include: The use of sexualized language or imagery and unwelcome sexual attention or advances Trolling, insulting/derogatory comments, and personal or political attacks Public or private harassment Publishing others\u2019 private information, such as a physical or electronic address, without explicit permission Other conduct which could reasonably be considered inappropriate in a professional setting", "title": "Our Standards"}, {"location": "CODE_OF_CONDUCT/#our-responsibilities", "text": "Janssen Project members, project participants and contributors (collectively, \"participants\") are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. The Technical Steering Committee (\"TSC\") of the Janssen Project has the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any participant for other behaviors that they deem inappropriate, threatening, offensive, or harmful. All participants have determined that The Linux Foundation is the most optimal organization to shepherd the development of this project. Participants acknowledge and agree to The Linux Foundation's exclusive right to use \"Janssen Project\" and any other names and trademarks associated with the open source project and Janssen Project and to authorize others\u2019 use of the marks, establish guidelines for such use, and to delegate these responsibilities. Participants agree not to take any action inconsistent with such rights and to cooperate in any action which The Linux Foundation deems necessary or desirable to prevent confusion or establish or preserve these rights. Participants will not independently adopt, use, or attempt to register any trademarks or trade names that are confusingly similar to these names.", "title": "Our Responsibilities"}, {"location": "CODE_OF_CONDUCT/#scope", "text": "This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.", "title": "Scope"}, {"location": "CODE_OF_CONDUCT/#enforcement", "text": "Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Executive Director, or, if the complaint involves the Executive Director, a member of the steering committee. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Participants who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by the steering committee.", "title": "Enforcement"}, {"location": "CODE_OF_CONDUCT/#attribution", "text": "This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html . For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq", "title": "Attribution"}, {"location": "CONTRIBUTING/", "text": "Contributing to Janssen Project # Purpose of this guide is to provide necessary information and resources to community in order to make successful contribution to the Janssen Project. There are many ways you can contribute. Of course you can contribute code. But we also need people to write documentation and guides, to help us with testing, to answer questions on the forums and chat, to review PR's, to help us with devops and CI/CD, to provide feedback on usability, and to promote the project through outreach. Also, by sharing metrics with us, we can gain valuable insights into how the software performs in the wild. Join the Community First Time Contributors Contribution Guidelines Code of Conduct About Issues Triaging Code Conventions and Guidelines Commits Branches PRs Issues Contributing to the documentation Contribution Workflow Find Something To Work On Start a Discussion Implement the Change Document Raise a PR Follow Through Join the Community # Repo : Watch and Star Janssen repository on Github Discussions : Join interesting discussions at Github Discussions Chat : We have an active community chat on Gitter . You can register for free their with your Github identity. Tweet : Janssen is on Twitter too. Follow us there to stay up to date on release announcements and news around Janssen. First Time Contributors # In case you are first-time contributor, then you can start with our good first issues list These are issues where you can easily contribute and community members will guide and support your contribution as always. If you need Janssen installation to test out your fix, here are the steps . Contribution Guidelines # We are really glad you are reading this, because we need volunteer developers to help this project come to fruition. Code of Conduct Issues Triaging Coding Conventions Code of Conduct # Janssen project has a Code of Conduct to which all contributors must adhere, please read it before interacting with the repository or the community in any way. About Issues # There are four kinds of issues you can open: Bug report : you believe you found a problem in a project and you want to discuss and get it fixed, creating an issue with the bug report template is the best way to do so. Feature Request : any kind of new feature need to be discussed in this kind of issue, do you want a new rule or a new feature? This is the kind of issue you want to open. Be very good at explaining your intent, it's always important that others can understand what you mean in order to discuss, be open and collaborative in letting others help you getting this done! Security Vulnerability : If you identify a security problem, please report it immediately, providing details about the nature, and if applicable, how to reproduce it. If you want to report an issue privately, you can email security@gluu.org Failing tests : you noticed a flaky test or a problem with a build? This is the kind of issue to triage that! The best way to get involved in the project is through issues, you can help in many ways: Issues triaging: participating in the discussion and adding details to open issues is always a good thing, sometimes issues need to be verified, you could be the one writing a test case to fix a bug! Fix an issue: you can help in getting issue fixed in many ways. More often by opening a pull request. In case you are first-time contributor, then you can start with our good first issues list These are issues where you can easily contribute and community members will guide and support your contribution as always. Triaging # Triage is a process of evaluating issues and PRs in order to determine their characteristics and take quick actions if possible. When you triage an issue, you: assess whether it has merit or not quickly close it by correctly answering a question point the reporter to a resource or documentation answering the issue tag it via labels, projects, or milestones take ownership submitting a PR for it, in case you want \ud83d\ude07 Here is how we continously triage new issues and PRs so that contributors can contribute faster and better. Code Conventions and Guidelines # Commits # Janssen Project mandates all commits to follow guidelines as below. Commit messages As commit convention, we adopt Conventional Commits v1.0.0 , we have an history of commits that do not adopt the convention but any new commit must follow it to be eligible for merge. Add GPG signature to your commit To ensure that contribution is coming for a trusted source, all commits should be signed using GPG key and verified by Github. If you have GPG key setup already then just use -S switch with you commit to sign it. If you need to setup your GPG key and verification, then you can find detailed instructions here Add DCO sign-off The Developer Certificate of Origin (DCO) is a lightweight way for contributors to certify that they wrote or otherwise have the right to submit the code they are contributing to the project. Contributors to the Janssen project sign-off that they adhere to these requirements by adding a Signed-off-by line to commit messages. This is a commit message Signed-off-by: Foo Bar <foobar@spam.org> Git even has a -s command line option to append this automatically to your commit message: $ git commit -s -m 'This is my commit message' In all, if you have your GPG verification setup, your commit command should look like git commit -S -s -m 'message that follows conventional commit style' Branches # Branch name should have component name as prefix, eg jans-core-mybranch PRs # PR titles should also follow Conventional Commits v1.0.0 . This will help in keeping merge commit messages inline with commit message standards Squash commits into small number of cohesive commits before raising a PR PR should be rebased on main branch so that there are minimal or no conflicts at the time of merge PR should only have changes related to target feature or issue. Create a separate PR for formatting or other quick bug fixes PR should include relevent documentaton changes PR should include unit and integration tests Issues # Issue titles should follow Conventional Commits v1.0.0 Backport changes to a different version # Backport changes are now supported through a workflow through labels prefixed with backport/ . For-example to backport changes in a certain PR to version v1.0.0 a label to that PR matching the version must be added i.e backport/v1.0.0 . The flow consists of creating a new branch, cherry-picking the changes of the original PR and creating a new PR to merge them. License Header # The Janssen Project uses Apache-2.0 license. Any existing or new code file has to start with the license header as shown below: /* * This software is available under the Apache-2.0 license. * See https://www.apache.org/licenses/LICENSE-2.0.txt for full text. * * Copyright (c) 2024, Gluu, Inc. */ If the developers sign a CLA(Contributor License Agreement) they can retain the copyright. Once the CLA has been signed, contributions can be accepted from the contributor with the License header as below. Make sure to replace [github-username] with contributor's GitHub username: /* * This software is available under the Apache-2.0 license. * See https://www.apache.org/licenses/LICENSE-2.0.txt for full text. * * Copyright (c) 2024, [github-username]. */ Signing the CLA # The current version of CLA can be found here . This is just for your reference. This same CLA will be signed digitally by following the steps below: The contributor sends an e-mail expressing willingness to contribute and sign the CLA. In the email, mention your GitHub account username from which the contributions will be made. If contributions will be made on behalf of an organization, then along with the GitHub username, mention the job title and organization's name in the email. Contributor receives an email with CLA and instructions on how to sign digitally. Follow the instructions and complete the signing process. Contributing to the documentation # Great documentation is a reflection of software's maturity and the great community that stands behind it. Contributing to the Janssen Project documentation is the easiest way to learn about the Janssen Project and to get involved in the community process. In order to ensure consistency of style, language, format, and terminology across all documents, please follow the guidelines below: Glossary of terms # This glossary helps to keep terms and their meanings consistent across documentation. Janssen Project or Jans : Refers to the official project name under Linux Foundation that seeks to build the world\u2019s fastest and most comprehensive cloud native identity and access management software platform Janssen Server : Refers to a set of software components developed under the Janssen Project . Components of the Janssen Server include client and server implementations of the OAuth, OpenID Connect, SCIM and FIDO standards. The term Janssen Server is used to refer to these components as a group. jans-auth-server : Refers to a module within the Janssen Server named jans-auth-server . This is one of the significant modules of the Janssen Server that has an implementation for OAuth and OpenId Connect. Janssen Server module names: For correct naming of other modules of the Janssen Server, please refer to README Documentation Style Guide # Janssen Project documentation uses Markdown. Guidelines below are intended to bring consistency in writing and formatting documents. Testing Janssen Project documentation site is published using MkDocs. Markdown parsers used by Github and the one used by MkDocs may have slight variations in how they generate HTML. So, for a small number of cases, document may look different between Github and Janssen Project documentation site . Hence it is critical to test documentation changes locally before pushing to repository. This will ensure that final HTML rendering of documents by MkDocs is as desired. Document Title # The document title summarises what the document aims to achieve and at the same time, it plays a critical role in making the document easy to find via search. Below are a few guidelines to write good titles for documents. Every document must start with a title. Meaning, #<space><title text> Title should summarise what the document is trying to achieve. For examples: Integrating with the Apache mod_auth_openidc module , Integrating DUO's Universal Prompt as an authentication method , Install using Ubuntu Linux Package Title should include its context. For example, the document under Installation > VM Installation > Ubuntu should not be titled as just Ubuntu but it should have a more detailed title similar to Install using Ubuntu Linux Package . When required, to keep the title from becoming too long, assume that Janssen Server is already understood as context. Titles should be written using title case Document Tags # Janssen Project documentation uses tags to make the search more accurate and add context to search results. Following are guidelines and examples to follow while adding tags to a document. Maximum 6 tags First three should establish the context of the section hierarchy under which the document belongs. See the example below. Remaining tags can be based on the content of the document. Each tag should be a single word (no spaces, hyphens or commas, etc) All tags should be in lowercase Example: Let's look at how to add tags to a document that is located on documentation site at path Administration -> Installation -> VM installation . Also, assume that the document describes the steps to install Janssen Project on the Ubuntu platform. Tags below would be recommended: --- ta gs : - admi n is trat io n - i nstallat io n - vm - ubu ntu --- Referencing Janssen Project Release in Documents # We often need to reference release numbers in the documentation. For example, Ubuntu package installation guide . In this guide, the following command is documented: wget https://github.com/JanssenProject/jans/releases/download/v1.1.4/jans_1.1.4.ubuntu20.04_amd64.deb -P /tmp Above command contains references to the release number at two places. v1.1.4 in the URL and 1.1.4 as part of the file name. There are many such places throughout the documentation when release numbers need to be mentioned. Whenever we make a new release, these numbers need to change as they point to the latest release number. This becomes a manual task. To avoid this manual, error-prone approach the Janssen Project uses a release marker, replace-janssen-version instead of writing actual release numbers in the head (latest) documentation branch. So, when there is a need to mention the release number, instead of writing the actual release number, use the release marker. Let's see how to document the above command (at the head version) so that it stays up-to-date release after release. wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version.ubuntu20.04_amd64.deb -P /tmp Warning head version of documentation may contain the release marker at various places. URLs, commands etc. So, URLs, and commands might not work as it is. Users will have to manually replace the marker or use the most recent stable release documentation. Release marker should be used only when contributing to the latest documentation. Not when updating documentation for previous releases. General Text # Allow long lines to wrap, rather than manually breaking them. For example, the Introduction paragraph is a single line Keep explanations short and clear Use complete sentences when possible To make text italicised , put an _ on each side, like this: _word_ To bold text, put a double * on each end, like this: **word** Leave a blank line between paragraphs. Count a header as a paragraph for this purpose Avoid passive voice as much as possible. It's clearer to say that a subject does something than to say a result was done Avoid using you in statements as much as possible. For example, instead of saying You can navigate to... simply say Navigate to... Page Setup # Start your page with a title on the first line Follow with a concise overview of the document / product's purpose Organize the information in the document from least technical to most technical if possible. Start conceptual, then get detailed Lists # Leave a blank line between text and first item in the list Only use a numbered list if the order of the list matters A line of a list should not end with a period. If it's multiple sentences, like this one, drop the last period Start each item in the list with a capital letter End each item in the list with at least three spaces. This makes sure the line breaks properly To make a bulleted list, start each line with - To make a numbered list, start each line with 1. For example: 1. This is the first item 1. This is the second item 1. This is the third item It will look like this: 1. This is the first item 2. This is the second item 3. This is the third item To include additional lines in a list item, start the sub-line with four spaces. For example: 1. This is the first item in a list There are four spaces to start this line Another four spaces here This keeps all text inside the numbered list item, before starting... 1. The following list item It will look like this: This is the first item in a list There are four spaces to start this line Another four spaces here This keeps all text inside the list, before starting... The following list item Other formatting considerations # Admonitions cannot be nested inside a list. They must be aligned all the way left. Inserting them within a list will break the list sequence (starting back over from 1). Nesting a fenced block of code in a numbered list is more challenging, as the list and code block syntaxes clash. To nest a code block into a list, insert four spaces to the left of all lines of the formatting. For example: 1. This is the first item ``` This is code This is also code. ``` 1. This is the second item It will look like this: This is the first item This is code This is also code. This is the second item Headings # Headings should be in title format. All important words should be capitalized The main title of the page should start with a single # , then each level of subheading should add one. For example, the first subheading should start with ## , a subheading of that should use ### , and so on Code Formatting # To format text as code within a line of normal text, surround the code with a single backtick (`). If the code is to be on its own line, it should be a fenced code block. To make a fenced code block, make a line before and after the code with three backticks: ``` This is code ``` We use the SuperFences plugin to enhance this functionality. Examples & Navigation # When possible, provide an example in the form of code output or a screenshot To instruct a user to click a button, or navigate to a certain page or through a menu, use the following style: Navigate to `Configuration` > `Authentication` and click the `Passport` tab It will look like this: Navigate to Configuration > Authentication and click the Passport tab Linking # We recommend using relative linking syntax when linking to other artifacts in repository. Linking to a page within the same repo use this format: [text for the link](../where/the/link/goes.md) - You must link to the .md file on GitHub for it to work properly - As an example, to make text this link link to a Markdown document named example.md in the same directory, you'd type it as [this link](./example.md) Service Commands # The Janssen Server supports many different Operating Systems (e.g. Ubuntu, SUSE etc.). Service commands can vary. Rather than \"hard coding\" service commands into documentation, please instead reference the dedicated documentation page for Service Commands . In documenting a process that involves a service restart, the Service Command documentation is linked: ## Add the attribute to MySQL - Add custom attribute - [Restart](https://jans.io/docs/vm-ops/restarting-services/) the `jans-auth.service` service. The word Restart is simply linked to the dedicated doc for Service Commands. Tables # Try to make tables visually readable by spacing to make distinct columns The header for each column must be separated by at least three dashes Use outer pipes for consistency If an entry is too long to fit in the neat boxes, that's fine, just try to keep it legible An example table follows: |This |Is |A |Table | |--------|-------|------|---------| |1 |2 |3 |4 | |Word |Code |Text |Table | It looks like this: This Is A Table 1 2 3 4 Word Code Text Table Help On Technical Writing # It is essential for everyone in the community to actively participate in the documentation. At the same time, not everyone is formally trained or experienced in writing technical documents. To help everyone understand the basics of good technical writing, we have listed a few resources below. Going through these resources will not take a lot of time and will help in writing better technical documents. Introduction to Technical Writing (part-1) Introduction to Technical Writing (part-2) Contribution Workflow # Find something to work on # Best place to find something to work on is to look at currently open issues . If you are a first time contributor then starting with list of good first issues is best. Start a discussion # Start a Github Discussion about what you are planning to contribute. Explain the feature or issue that you are planning to contribute and what your solution or implementation approach. Janssen is a community driven project and it'll be helpful to get community's view about it. Create an issue # Take your time to write a proper issue including a good summary and description. Outcome of Github discussion about your contribution can help you create good content for the issue. As a first step when creating a new issue, an issue template has to be selected. Select appropriate issue template and it'll help you create an issue with right content. Remember that issue may be the first thing a reviewer of your PR will look at to get an idea of what you are proposing. It will also be used by the community in the future to find about what new features and enhancements are included in new releases. Implement the change # All contributions to Janssen Project should be made via Github pull requests(PR). New to PR workflow?? Learn and practice it at first-contributions Create a Fork # Fork Janssen repository . And create a clone. Implement the Change # Start working on changes as required. Make sure the code conventions are being followed. Use static code analysis and linting tools to make sure the code is high-quality. Write tests first and then code. Ensure that integration tests that cover your code are appropriately updated and reviewed. Create PR early and push often. Janssen uses Github actions to run automated checks on PR changes. Ensure that these checks are passing with every push. Engage PR reviewers at the start so that they can continue to reivew code as it is developed and in small chunks. For a change that is non-trivial(an enhancement or a new feature), design should be reviewed. This should be done via PR by adding appropriate code owners. Document # PR should include changes in relevant documentation along with code changes. PR is checked by bot to have either one of the following : A commit that follows commit guidelines with docs: message Changes in artifacts under jans/docs If PR does not need any documentation changes, then the developer needs to acknowledge that in one of two ways: Add an empty commit to the PR (using --allow-empty git flag) with docs: message (i.e docs: no doc changes required ) Add footer to the commit message of one of the code commits with docs: message e.g fix: typo on class name More details here. docs: no docs modification Raise a PR # Make sure that PR title follows these guidelines Janssen uses Github PR template. Template provides helpful instructions to ensure new PRs are complete in details and easy to review. Github will populate new PR's description with these instructions. You can edit PR description as per your requirements. When PR is raised, Github will automatically assign reviewer to the PR based changed files and CODEOWNERS list. Once PR is raised, ensure that PR passes all the mandatory Github actions checks available on Github PR page. Github will not allow PR to be merged if any of the mandatory check is failing. Follow Through # Once the PR is raised, wait for reviewers to start review. Reviewers will start review at the first opportunity available. If you want to draw attention, give a gentle reminder in PR comments. But please be patient. Follow activities on your PR closely till the time PR is merged. PR reviewer may want to suggest a change or may need to ask a question to get more clarity. Make sure you are actively collaborating. Once Reviewer has completed the review and approved the changes, the PR will be merged. Thats it!! Congratulations on successful contribution. \ud83e\udd73 \ud83e\udd1f", "title": "Contribution Guidelines"}, {"location": "CONTRIBUTING/#contributing-to-janssen-project", "text": "Purpose of this guide is to provide necessary information and resources to community in order to make successful contribution to the Janssen Project. There are many ways you can contribute. Of course you can contribute code. But we also need people to write documentation and guides, to help us with testing, to answer questions on the forums and chat, to review PR's, to help us with devops and CI/CD, to provide feedback on usability, and to promote the project through outreach. Also, by sharing metrics with us, we can gain valuable insights into how the software performs in the wild. Join the Community First Time Contributors Contribution Guidelines Code of Conduct About Issues Triaging Code Conventions and Guidelines Commits Branches PRs Issues Contributing to the documentation Contribution Workflow Find Something To Work On Start a Discussion Implement the Change Document Raise a PR Follow Through", "title": "Contributing to Janssen Project"}, {"location": "CONTRIBUTING/#join-the-community", "text": "Repo : Watch and Star Janssen repository on Github Discussions : Join interesting discussions at Github Discussions Chat : We have an active community chat on Gitter . You can register for free their with your Github identity. Tweet : Janssen is on Twitter too. Follow us there to stay up to date on release announcements and news around Janssen.", "title": "Join the Community"}, {"location": "CONTRIBUTING/#first-time-contributors", "text": "In case you are first-time contributor, then you can start with our good first issues list These are issues where you can easily contribute and community members will guide and support your contribution as always. If you need Janssen installation to test out your fix, here are the steps .", "title": "First Time Contributors"}, {"location": "CONTRIBUTING/#contribution-guidelines", "text": "We are really glad you are reading this, because we need volunteer developers to help this project come to fruition. Code of Conduct Issues Triaging Coding Conventions", "title": "Contribution Guidelines"}, {"location": "CONTRIBUTING/#code-of-conduct", "text": "Janssen project has a Code of Conduct to which all contributors must adhere, please read it before interacting with the repository or the community in any way.", "title": "Code of Conduct"}, {"location": "CONTRIBUTING/#about-issues", "text": "There are four kinds of issues you can open: Bug report : you believe you found a problem in a project and you want to discuss and get it fixed, creating an issue with the bug report template is the best way to do so. Feature Request : any kind of new feature need to be discussed in this kind of issue, do you want a new rule or a new feature? This is the kind of issue you want to open. Be very good at explaining your intent, it's always important that others can understand what you mean in order to discuss, be open and collaborative in letting others help you getting this done! Security Vulnerability : If you identify a security problem, please report it immediately, providing details about the nature, and if applicable, how to reproduce it. If you want to report an issue privately, you can email security@gluu.org Failing tests : you noticed a flaky test or a problem with a build? This is the kind of issue to triage that! The best way to get involved in the project is through issues, you can help in many ways: Issues triaging: participating in the discussion and adding details to open issues is always a good thing, sometimes issues need to be verified, you could be the one writing a test case to fix a bug! Fix an issue: you can help in getting issue fixed in many ways. More often by opening a pull request. In case you are first-time contributor, then you can start with our good first issues list These are issues where you can easily contribute and community members will guide and support your contribution as always.", "title": "About Issues"}, {"location": "CONTRIBUTING/#triaging", "text": "Triage is a process of evaluating issues and PRs in order to determine their characteristics and take quick actions if possible. When you triage an issue, you: assess whether it has merit or not quickly close it by correctly answering a question point the reporter to a resource or documentation answering the issue tag it via labels, projects, or milestones take ownership submitting a PR for it, in case you want \ud83d\ude07 Here is how we continously triage new issues and PRs so that contributors can contribute faster and better.", "title": "Triaging"}, {"location": "CONTRIBUTING/#code-conventions-and-guidelines", "text": "", "title": "Code Conventions and Guidelines"}, {"location": "CONTRIBUTING/#commits", "text": "Janssen Project mandates all commits to follow guidelines as below. Commit messages As commit convention, we adopt Conventional Commits v1.0.0 , we have an history of commits that do not adopt the convention but any new commit must follow it to be eligible for merge. Add GPG signature to your commit To ensure that contribution is coming for a trusted source, all commits should be signed using GPG key and verified by Github. If you have GPG key setup already then just use -S switch with you commit to sign it. If you need to setup your GPG key and verification, then you can find detailed instructions here Add DCO sign-off The Developer Certificate of Origin (DCO) is a lightweight way for contributors to certify that they wrote or otherwise have the right to submit the code they are contributing to the project. Contributors to the Janssen project sign-off that they adhere to these requirements by adding a Signed-off-by line to commit messages. This is a commit message Signed-off-by: Foo Bar <foobar@spam.org> Git even has a -s command line option to append this automatically to your commit message: $ git commit -s -m 'This is my commit message' In all, if you have your GPG verification setup, your commit command should look like git commit -S -s -m 'message that follows conventional commit style'", "title": "Commits"}, {"location": "CONTRIBUTING/#branches", "text": "Branch name should have component name as prefix, eg jans-core-mybranch", "title": "Branches"}, {"location": "CONTRIBUTING/#prs", "text": "PR titles should also follow Conventional Commits v1.0.0 . This will help in keeping merge commit messages inline with commit message standards Squash commits into small number of cohesive commits before raising a PR PR should be rebased on main branch so that there are minimal or no conflicts at the time of merge PR should only have changes related to target feature or issue. Create a separate PR for formatting or other quick bug fixes PR should include relevent documentaton changes PR should include unit and integration tests", "title": "PRs"}, {"location": "CONTRIBUTING/#issues", "text": "Issue titles should follow Conventional Commits v1.0.0", "title": "Issues"}, {"location": "CONTRIBUTING/#backport-changes-to-a-different-version", "text": "Backport changes are now supported through a workflow through labels prefixed with backport/ . For-example to backport changes in a certain PR to version v1.0.0 a label to that PR matching the version must be added i.e backport/v1.0.0 . The flow consists of creating a new branch, cherry-picking the changes of the original PR and creating a new PR to merge them.", "title": "Backport changes to a different version"}, {"location": "CONTRIBUTING/#license-header", "text": "The Janssen Project uses Apache-2.0 license. Any existing or new code file has to start with the license header as shown below: /* * This software is available under the Apache-2.0 license. * See https://www.apache.org/licenses/LICENSE-2.0.txt for full text. * * Copyright (c) 2024, Gluu, Inc. */ If the developers sign a CLA(Contributor License Agreement) they can retain the copyright. Once the CLA has been signed, contributions can be accepted from the contributor with the License header as below. Make sure to replace [github-username] with contributor's GitHub username: /* * This software is available under the Apache-2.0 license. * See https://www.apache.org/licenses/LICENSE-2.0.txt for full text. * * Copyright (c) 2024, [github-username]. */", "title": "License Header"}, {"location": "CONTRIBUTING/#signing-the-cla", "text": "The current version of CLA can be found here . This is just for your reference. This same CLA will be signed digitally by following the steps below: The contributor sends an e-mail expressing willingness to contribute and sign the CLA. In the email, mention your GitHub account username from which the contributions will be made. If contributions will be made on behalf of an organization, then along with the GitHub username, mention the job title and organization's name in the email. Contributor receives an email with CLA and instructions on how to sign digitally. Follow the instructions and complete the signing process.", "title": "Signing the CLA"}, {"location": "CONTRIBUTING/#contributing-to-the-documentation", "text": "Great documentation is a reflection of software's maturity and the great community that stands behind it. Contributing to the Janssen Project documentation is the easiest way to learn about the Janssen Project and to get involved in the community process. In order to ensure consistency of style, language, format, and terminology across all documents, please follow the guidelines below:", "title": "Contributing to the documentation"}, {"location": "CONTRIBUTING/#glossary-of-terms", "text": "This glossary helps to keep terms and their meanings consistent across documentation. Janssen Project or Jans : Refers to the official project name under Linux Foundation that seeks to build the world\u2019s fastest and most comprehensive cloud native identity and access management software platform Janssen Server : Refers to a set of software components developed under the Janssen Project . Components of the Janssen Server include client and server implementations of the OAuth, OpenID Connect, SCIM and FIDO standards. The term Janssen Server is used to refer to these components as a group. jans-auth-server : Refers to a module within the Janssen Server named jans-auth-server . This is one of the significant modules of the Janssen Server that has an implementation for OAuth and OpenId Connect. Janssen Server module names: For correct naming of other modules of the Janssen Server, please refer to README", "title": "Glossary of terms"}, {"location": "CONTRIBUTING/#documentation-style-guide", "text": "Janssen Project documentation uses Markdown. Guidelines below are intended to bring consistency in writing and formatting documents. Testing Janssen Project documentation site is published using MkDocs. Markdown parsers used by Github and the one used by MkDocs may have slight variations in how they generate HTML. So, for a small number of cases, document may look different between Github and Janssen Project documentation site . Hence it is critical to test documentation changes locally before pushing to repository. This will ensure that final HTML rendering of documents by MkDocs is as desired.", "title": "Documentation Style Guide"}, {"location": "CONTRIBUTING/#document-title", "text": "The document title summarises what the document aims to achieve and at the same time, it plays a critical role in making the document easy to find via search. Below are a few guidelines to write good titles for documents. Every document must start with a title. Meaning, #<space><title text> Title should summarise what the document is trying to achieve. For examples: Integrating with the Apache mod_auth_openidc module , Integrating DUO's Universal Prompt as an authentication method , Install using Ubuntu Linux Package Title should include its context. For example, the document under Installation > VM Installation > Ubuntu should not be titled as just Ubuntu but it should have a more detailed title similar to Install using Ubuntu Linux Package . When required, to keep the title from becoming too long, assume that Janssen Server is already understood as context. Titles should be written using title case", "title": "Document Title"}, {"location": "CONTRIBUTING/#document-tags", "text": "Janssen Project documentation uses tags to make the search more accurate and add context to search results. Following are guidelines and examples to follow while adding tags to a document. Maximum 6 tags First three should establish the context of the section hierarchy under which the document belongs. See the example below. Remaining tags can be based on the content of the document. Each tag should be a single word (no spaces, hyphens or commas, etc) All tags should be in lowercase Example: Let's look at how to add tags to a document that is located on documentation site at path Administration -> Installation -> VM installation . Also, assume that the document describes the steps to install Janssen Project on the Ubuntu platform. Tags below would be recommended: --- ta gs : - admi n is trat io n - i nstallat io n - vm - ubu ntu ---", "title": "Document Tags"}, {"location": "CONTRIBUTING/#referencing-janssen-project-release-in-documents", "text": "We often need to reference release numbers in the documentation. For example, Ubuntu package installation guide . In this guide, the following command is documented: wget https://github.com/JanssenProject/jans/releases/download/v1.1.4/jans_1.1.4.ubuntu20.04_amd64.deb -P /tmp Above command contains references to the release number at two places. v1.1.4 in the URL and 1.1.4 as part of the file name. There are many such places throughout the documentation when release numbers need to be mentioned. Whenever we make a new release, these numbers need to change as they point to the latest release number. This becomes a manual task. To avoid this manual, error-prone approach the Janssen Project uses a release marker, replace-janssen-version instead of writing actual release numbers in the head (latest) documentation branch. So, when there is a need to mention the release number, instead of writing the actual release number, use the release marker. Let's see how to document the above command (at the head version) so that it stays up-to-date release after release. wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version.ubuntu20.04_amd64.deb -P /tmp Warning head version of documentation may contain the release marker at various places. URLs, commands etc. So, URLs, and commands might not work as it is. Users will have to manually replace the marker or use the most recent stable release documentation. Release marker should be used only when contributing to the latest documentation. Not when updating documentation for previous releases.", "title": "Referencing Janssen Project Release in Documents"}, {"location": "CONTRIBUTING/#general-text", "text": "Allow long lines to wrap, rather than manually breaking them. For example, the Introduction paragraph is a single line Keep explanations short and clear Use complete sentences when possible To make text italicised , put an _ on each side, like this: _word_ To bold text, put a double * on each end, like this: **word** Leave a blank line between paragraphs. Count a header as a paragraph for this purpose Avoid passive voice as much as possible. It's clearer to say that a subject does something than to say a result was done Avoid using you in statements as much as possible. For example, instead of saying You can navigate to... simply say Navigate to...", "title": "General Text"}, {"location": "CONTRIBUTING/#page-setup", "text": "Start your page with a title on the first line Follow with a concise overview of the document / product's purpose Organize the information in the document from least technical to most technical if possible. Start conceptual, then get detailed", "title": "Page Setup"}, {"location": "CONTRIBUTING/#lists", "text": "Leave a blank line between text and first item in the list Only use a numbered list if the order of the list matters A line of a list should not end with a period. If it's multiple sentences, like this one, drop the last period Start each item in the list with a capital letter End each item in the list with at least three spaces. This makes sure the line breaks properly To make a bulleted list, start each line with - To make a numbered list, start each line with 1. For example: 1. This is the first item 1. This is the second item 1. This is the third item It will look like this: 1. This is the first item 2. This is the second item 3. This is the third item To include additional lines in a list item, start the sub-line with four spaces. For example: 1. This is the first item in a list There are four spaces to start this line Another four spaces here This keeps all text inside the numbered list item, before starting... 1. The following list item It will look like this: This is the first item in a list There are four spaces to start this line Another four spaces here This keeps all text inside the list, before starting... The following list item", "title": "Lists"}, {"location": "CONTRIBUTING/#other-formatting-considerations", "text": "Admonitions cannot be nested inside a list. They must be aligned all the way left. Inserting them within a list will break the list sequence (starting back over from 1). Nesting a fenced block of code in a numbered list is more challenging, as the list and code block syntaxes clash. To nest a code block into a list, insert four spaces to the left of all lines of the formatting. For example: 1. This is the first item ``` This is code This is also code. ``` 1. This is the second item It will look like this: This is the first item This is code This is also code. This is the second item", "title": "Other formatting considerations"}, {"location": "CONTRIBUTING/#headings", "text": "Headings should be in title format. All important words should be capitalized The main title of the page should start with a single # , then each level of subheading should add one. For example, the first subheading should start with ## , a subheading of that should use ### , and so on", "title": "Headings"}, {"location": "CONTRIBUTING/#code-formatting", "text": "To format text as code within a line of normal text, surround the code with a single backtick (`). If the code is to be on its own line, it should be a fenced code block. To make a fenced code block, make a line before and after the code with three backticks: ``` This is code ``` We use the SuperFences plugin to enhance this functionality.", "title": "Code Formatting"}, {"location": "CONTRIBUTING/#examples-navigation", "text": "When possible, provide an example in the form of code output or a screenshot To instruct a user to click a button, or navigate to a certain page or through a menu, use the following style: Navigate to `Configuration` > `Authentication` and click the `Passport` tab It will look like this: Navigate to Configuration > Authentication and click the Passport tab", "title": "Examples & Navigation"}, {"location": "CONTRIBUTING/#linking", "text": "We recommend using relative linking syntax when linking to other artifacts in repository. Linking to a page within the same repo use this format: [text for the link](../where/the/link/goes.md) - You must link to the .md file on GitHub for it to work properly - As an example, to make text this link link to a Markdown document named example.md in the same directory, you'd type it as [this link](./example.md)", "title": "Linking"}, {"location": "CONTRIBUTING/#service-commands", "text": "The Janssen Server supports many different Operating Systems (e.g. Ubuntu, SUSE etc.). Service commands can vary. Rather than \"hard coding\" service commands into documentation, please instead reference the dedicated documentation page for Service Commands . In documenting a process that involves a service restart, the Service Command documentation is linked: ## Add the attribute to MySQL - Add custom attribute - [Restart](https://jans.io/docs/vm-ops/restarting-services/) the `jans-auth.service` service. The word Restart is simply linked to the dedicated doc for Service Commands.", "title": "Service Commands"}, {"location": "CONTRIBUTING/#tables", "text": "Try to make tables visually readable by spacing to make distinct columns The header for each column must be separated by at least three dashes Use outer pipes for consistency If an entry is too long to fit in the neat boxes, that's fine, just try to keep it legible An example table follows: |This |Is |A |Table | |--------|-------|------|---------| |1 |2 |3 |4 | |Word |Code |Text |Table | It looks like this: This Is A Table 1 2 3 4 Word Code Text Table", "title": "Tables"}, {"location": "CONTRIBUTING/#help-on-technical-writing", "text": "It is essential for everyone in the community to actively participate in the documentation. At the same time, not everyone is formally trained or experienced in writing technical documents. To help everyone understand the basics of good technical writing, we have listed a few resources below. Going through these resources will not take a lot of time and will help in writing better technical documents. Introduction to Technical Writing (part-1) Introduction to Technical Writing (part-2)", "title": "Help On Technical Writing"}, {"location": "CONTRIBUTING/#contribution-workflow", "text": "", "title": "Contribution Workflow"}, {"location": "CONTRIBUTING/#find-something-to-work-on", "text": "Best place to find something to work on is to look at currently open issues . If you are a first time contributor then starting with list of good first issues is best.", "title": "Find something to work on"}, {"location": "CONTRIBUTING/#start-a-discussion", "text": "Start a Github Discussion about what you are planning to contribute. Explain the feature or issue that you are planning to contribute and what your solution or implementation approach. Janssen is a community driven project and it'll be helpful to get community's view about it.", "title": "Start a discussion"}, {"location": "CONTRIBUTING/#create-an-issue", "text": "Take your time to write a proper issue including a good summary and description. Outcome of Github discussion about your contribution can help you create good content for the issue. As a first step when creating a new issue, an issue template has to be selected. Select appropriate issue template and it'll help you create an issue with right content. Remember that issue may be the first thing a reviewer of your PR will look at to get an idea of what you are proposing. It will also be used by the community in the future to find about what new features and enhancements are included in new releases.", "title": "Create an issue"}, {"location": "CONTRIBUTING/#implement-the-change", "text": "All contributions to Janssen Project should be made via Github pull requests(PR). New to PR workflow?? Learn and practice it at first-contributions", "title": "Implement the change"}, {"location": "CONTRIBUTING/#create-a-fork", "text": "Fork Janssen repository . And create a clone.", "title": "Create a Fork"}, {"location": "CONTRIBUTING/#implement-the-change_1", "text": "Start working on changes as required. Make sure the code conventions are being followed. Use static code analysis and linting tools to make sure the code is high-quality. Write tests first and then code. Ensure that integration tests that cover your code are appropriately updated and reviewed. Create PR early and push often. Janssen uses Github actions to run automated checks on PR changes. Ensure that these checks are passing with every push. Engage PR reviewers at the start so that they can continue to reivew code as it is developed and in small chunks. For a change that is non-trivial(an enhancement or a new feature), design should be reviewed. This should be done via PR by adding appropriate code owners.", "title": "Implement the Change"}, {"location": "CONTRIBUTING/#document", "text": "PR should include changes in relevant documentation along with code changes. PR is checked by bot to have either one of the following : A commit that follows commit guidelines with docs: message Changes in artifacts under jans/docs If PR does not need any documentation changes, then the developer needs to acknowledge that in one of two ways: Add an empty commit to the PR (using --allow-empty git flag) with docs: message (i.e docs: no doc changes required ) Add footer to the commit message of one of the code commits with docs: message e.g fix: typo on class name More details here. docs: no docs modification", "title": "Document"}, {"location": "CONTRIBUTING/#raise-a-pr", "text": "Make sure that PR title follows these guidelines Janssen uses Github PR template. Template provides helpful instructions to ensure new PRs are complete in details and easy to review. Github will populate new PR's description with these instructions. You can edit PR description as per your requirements. When PR is raised, Github will automatically assign reviewer to the PR based changed files and CODEOWNERS list. Once PR is raised, ensure that PR passes all the mandatory Github actions checks available on Github PR page. Github will not allow PR to be merged if any of the mandatory check is failing.", "title": "Raise a PR"}, {"location": "CONTRIBUTING/#follow-through", "text": "Once the PR is raised, wait for reviewers to start review. Reviewers will start review at the first opportunity available. If you want to draw attention, give a gentle reminder in PR comments. But please be patient. Follow activities on your PR closely till the time PR is merged. PR reviewer may want to suggest a change or may need to ask a question to get more clarity. Make sure you are actively collaborating. Once Reviewer has completed the review and approved the changes, the PR will be merged. Thats it!! Congratulations on successful contribution. \ud83e\udd73 \ud83e\udd1f", "title": "Follow Through"}, {"location": "agama/execution-rules/", "tags": ["administration", "developer", "agama"], "text": "Flows execution rules # This document regards flow execution details. Engines implementing the Agama framework must account these aspects fully. Important The concept of \" top-level \" flow is used in several places throughout this page. It refers to a flow which has been directly launched from the user browser and hence has no parents (no callers). Flows lifecycle # From a programming perspective, a flow is a lot like a function or subroutine in a regular program. Once a flow is triggered, it must be executed from top to bottom until a Finish statement is encountered. There are no special requirements on flow initialization or flow structure either. In some cases, the Finish instruction is not reached because the flow: has crashed has been cancelled has timed out More on these conditions below. Otherwise, the flow is said to have finished and depending on the actual arguments passed to Finish , it can be said the flow finished successfully or the flow failed . Successful flows # When a flow finishes successfully, control returns to the caller (parent flow) and execution continues. In the case of a top-level flow, it is up to the concrete engine what to do next. Normally, the arguments passed to the Finish directive will drive the specific behavior, which could for instance authenticate a person. Failed flows # When a flow fails, control returns to the caller (parent flow) and execution continues. In the case of a top-level flow, it is up to the concrete engine what to do next. Displaying an error page would be generally appropriate. The arguments passed to the Finish directive could be of use here. Crashed flows # A flow is said to have crashed if any of the below occur: Invalid code (syntactically wrong) was tried to be executed The last instruction was reached and Finish was not encountered An attempt to access a property or index of a null variable was made The invocation of a foreign routine, i.e. through Call , raised an error condition, and the error was not caught Any unexpected runtime error was raised When a flow crashes, the caller flow (if any) is said to have crashed too if it did not catch the given error. This rule applies recursively until the top-level flow is reached. When a top-level flow crashes, engines must: Show an error with a concise descriptive error description Append a fuller error message to whatever logging system is in place Terminate the flow execution to allow the user start again the flow later in a safe manner Flows timeout # The Timeout directive specifies a maximum allowable execution time for a top-level flow. When a flow exceeds this execution time, engines should display an error page accordingly. Cancelled flows # Cancellation allows a flow to early interrupt the execution of a given subflow thus enabling the implementation of alternative routing without the need of re-writing subflows. It can only take place upon the execution of a given RRF instruction part of a subflow that has been Trigger ed. This feature is better understood via examples - note the link provided is specific to the Janssen Server engine only. Other engines may implement cancellation in a different way, the only requirement is to preserve the convention that the returned value of a cancelled flow must be of the form: { aborted: true, data: ..., url: ... } . Launching flows # Engines must provide specific mechanisms to launch a given flow in the user's browser and document how to pass input parameters to it and the formats allowed. Logging # Engines must maintain at least one logging destination (file, stream, etc.) to accumulate the messages passed in Log directives. Additionally, it should advertise the logging levels supported, their abbreviations if any, and the default logging level. RFAC and Callback URL # Engines must provide and maintain a fixed single URL that \"users\" of RFAC can supply to external systems in order to implement integrations with third-party sites that employ browser redirections. This URL should only be available for a given browser session while RFAC is in execution. Once the callback is visited or the flow times out (whichever occurs first), subsequent requests will respond with an HTTP 404 error. The mechanism used by the engine to make the redirect to the external site is implementation specific. Assets management # Engines must have an internal mechanism to store assets following a hierarchical (filesystem-like) structure. Such structure must have a defined \"root\" that in conjunction with a flow Basepath will allow the engine to resolve (locate) the paths to specific flow assets. Engines may support one or more templating technologies and file formats for rendering the UI pages. Foreign calls # Languages support # At least one programming language should be supported by an engine. This feature is critical because Agama DSL was designed to force developers use a distinct, more powerful language when the task at hand cannot be implemented by simple data manipulation or comparison of values. Routines lookup # Engines should define a clear mechanism to lookup the specific routine to be invoked when using the Call directive. Actually, the syntax of Call fits well into an object-oriented style. The table bellow illustrates this fact: Example Potential semantics Call a B c d On object instance a , invoke method B passing c and d as parameters Call x.y.z#S d Invoke method S belonging to class x.y.z passing d as parameter. This variant maps to a \"static\" method invocation, where S does not require a specific instance to run on In OOP, it is not uncommon to have a method S with several different signatures. The lookup mechanism should account disambiguation techniques, if possible. Errors # In the execution of the call, if an error occurs, the engine should raise an error catchable in Agama code. The structure or data type of this error is an engine-specific detail. Ideally the error should be easily inspected in Agama code so any required further processing is feasible in a flow. Types compatibility # The arguments conversion/compatibility is also an important topic. Most likely Agama types will not match the (foreign) target language types. This means passing a \"native\" Agama value as parameter in a method Call requires some form of compatibility with the target type in the routine (method) signature. When compatibility does not make sense, seems too complex, or impossible, invocation should \"crash\" by raising some form of error. The same analysis has to be done in the other direction: from the target language to Agama. This is for the case where the Call returns a value. Such value should be \"manipulable\" in Agama code. Other considerations # Engine implementers may consider to offer the ability for developers to supply routines without the need of engine restarts. This aims for an agile development experience.", "title": "Execution rules"}, {"location": "agama/execution-rules/#flows-execution-rules", "text": "This document regards flow execution details. Engines implementing the Agama framework must account these aspects fully. Important The concept of \" top-level \" flow is used in several places throughout this page. It refers to a flow which has been directly launched from the user browser and hence has no parents (no callers).", "title": "Flows execution rules"}, {"location": "agama/execution-rules/#flows-lifecycle", "text": "From a programming perspective, a flow is a lot like a function or subroutine in a regular program. Once a flow is triggered, it must be executed from top to bottom until a Finish statement is encountered. There are no special requirements on flow initialization or flow structure either. In some cases, the Finish instruction is not reached because the flow: has crashed has been cancelled has timed out More on these conditions below. Otherwise, the flow is said to have finished and depending on the actual arguments passed to Finish , it can be said the flow finished successfully or the flow failed .", "title": "Flows lifecycle"}, {"location": "agama/execution-rules/#successful-flows", "text": "When a flow finishes successfully, control returns to the caller (parent flow) and execution continues. In the case of a top-level flow, it is up to the concrete engine what to do next. Normally, the arguments passed to the Finish directive will drive the specific behavior, which could for instance authenticate a person.", "title": "Successful flows"}, {"location": "agama/execution-rules/#failed-flows", "text": "When a flow fails, control returns to the caller (parent flow) and execution continues. In the case of a top-level flow, it is up to the concrete engine what to do next. Displaying an error page would be generally appropriate. The arguments passed to the Finish directive could be of use here.", "title": "Failed flows"}, {"location": "agama/execution-rules/#crashed-flows", "text": "A flow is said to have crashed if any of the below occur: Invalid code (syntactically wrong) was tried to be executed The last instruction was reached and Finish was not encountered An attempt to access a property or index of a null variable was made The invocation of a foreign routine, i.e. through Call , raised an error condition, and the error was not caught Any unexpected runtime error was raised When a flow crashes, the caller flow (if any) is said to have crashed too if it did not catch the given error. This rule applies recursively until the top-level flow is reached. When a top-level flow crashes, engines must: Show an error with a concise descriptive error description Append a fuller error message to whatever logging system is in place Terminate the flow execution to allow the user start again the flow later in a safe manner", "title": "Crashed flows"}, {"location": "agama/execution-rules/#flows-timeout", "text": "The Timeout directive specifies a maximum allowable execution time for a top-level flow. When a flow exceeds this execution time, engines should display an error page accordingly.", "title": "Flows timeout"}, {"location": "agama/execution-rules/#cancelled-flows", "text": "Cancellation allows a flow to early interrupt the execution of a given subflow thus enabling the implementation of alternative routing without the need of re-writing subflows. It can only take place upon the execution of a given RRF instruction part of a subflow that has been Trigger ed. This feature is better understood via examples - note the link provided is specific to the Janssen Server engine only. Other engines may implement cancellation in a different way, the only requirement is to preserve the convention that the returned value of a cancelled flow must be of the form: { aborted: true, data: ..., url: ... } .", "title": "Cancelled flows"}, {"location": "agama/execution-rules/#launching-flows", "text": "Engines must provide specific mechanisms to launch a given flow in the user's browser and document how to pass input parameters to it and the formats allowed.", "title": "Launching flows"}, {"location": "agama/execution-rules/#logging", "text": "Engines must maintain at least one logging destination (file, stream, etc.) to accumulate the messages passed in Log directives. Additionally, it should advertise the logging levels supported, their abbreviations if any, and the default logging level.", "title": "Logging"}, {"location": "agama/execution-rules/#rfac-and-callback-url", "text": "Engines must provide and maintain a fixed single URL that \"users\" of RFAC can supply to external systems in order to implement integrations with third-party sites that employ browser redirections. This URL should only be available for a given browser session while RFAC is in execution. Once the callback is visited or the flow times out (whichever occurs first), subsequent requests will respond with an HTTP 404 error. The mechanism used by the engine to make the redirect to the external site is implementation specific.", "title": "RFAC and Callback URL"}, {"location": "agama/execution-rules/#assets-management", "text": "Engines must have an internal mechanism to store assets following a hierarchical (filesystem-like) structure. Such structure must have a defined \"root\" that in conjunction with a flow Basepath will allow the engine to resolve (locate) the paths to specific flow assets. Engines may support one or more templating technologies and file formats for rendering the UI pages.", "title": "Assets management"}, {"location": "agama/execution-rules/#foreign-calls", "text": "", "title": "Foreign calls"}, {"location": "agama/execution-rules/#languages-support", "text": "At least one programming language should be supported by an engine. This feature is critical because Agama DSL was designed to force developers use a distinct, more powerful language when the task at hand cannot be implemented by simple data manipulation or comparison of values.", "title": "Languages support"}, {"location": "agama/execution-rules/#routines-lookup", "text": "Engines should define a clear mechanism to lookup the specific routine to be invoked when using the Call directive. Actually, the syntax of Call fits well into an object-oriented style. The table bellow illustrates this fact: Example Potential semantics Call a B c d On object instance a , invoke method B passing c and d as parameters Call x.y.z#S d Invoke method S belonging to class x.y.z passing d as parameter. This variant maps to a \"static\" method invocation, where S does not require a specific instance to run on In OOP, it is not uncommon to have a method S with several different signatures. The lookup mechanism should account disambiguation techniques, if possible.", "title": "Routines lookup"}, {"location": "agama/execution-rules/#errors", "text": "In the execution of the call, if an error occurs, the engine should raise an error catchable in Agama code. The structure or data type of this error is an engine-specific detail. Ideally the error should be easily inspected in Agama code so any required further processing is feasible in a flow.", "title": "Errors"}, {"location": "agama/execution-rules/#types-compatibility", "text": "The arguments conversion/compatibility is also an important topic. Most likely Agama types will not match the (foreign) target language types. This means passing a \"native\" Agama value as parameter in a method Call requires some form of compatibility with the target type in the routine (method) signature. When compatibility does not make sense, seems too complex, or impossible, invocation should \"crash\" by raising some form of error. The same analysis has to be done in the other direction: from the target language to Agama. This is for the case where the Call returns a value. Such value should be \"manipulable\" in Agama code.", "title": "Types compatibility"}, {"location": "agama/execution-rules/#other-considerations", "text": "Engine implementers may consider to offer the ability for developers to supply routines without the need of engine restarts. This aims for an agile development experience.", "title": "Other considerations"}, {"location": "agama/gama-format/", "tags": ["administration", "developer", "agama"], "text": "The .gama file format # In practice, a web flow will make use of a bunch of artifacts, like UI pages, images, stylesheets, and source code. Actually, to solve a real-world problem several flows are needed to be able to keep flexibility and complexity at acceptable levels. Here is where the concept project emerges. A project can be thought of as a container to hold all flows and related assets aimed at solving a particular problem - including metadata of the project itself. The idea of defining a standard way to specify projects brings several benefits: Provide a uniform conceptual scheme for community actors to interchange flows Provide Agama engine implementors common ground for the materialization of flows deployment Serve as reference for developers interested in coding tools such as an Agama IDE Anatomy of a project # The below shows the structure of an Agama project: \u251c\u2500\u2500 code/ \u251c\u2500\u2500 lib/ \u251c\u2500\u2500 web/ \u251c\u2500\u2500 project.json \u251c\u2500\u2500 LICENSE \u2514\u2500\u2500 README.md code directory holds all flows part of the project. Every flow - implemented in Agama language - has to reside in a separate file with extension flow and with file name matching the qualified name of the flow in question. This directory can have nested folders if desired lib may contain source code files in languages other than Agama and binary libraries required by the project, if any. Every engine can make use of the contents of this folder as needed web is expected to hold all UI templates plus required web assets (stylesheets, images, localization strings, etc.) that all flows in this project may use project.json file contains metadata about this project. More on this later README.md file may contain extra documentation in markdown format LICENSE file may contain legal-related information Except for code and web directories, all elements in the file structure above are optional. Note that files in web must follow a directory structure that is consistent with respect to Basepath and RRF directives found in the included flows. Metadata # project.json file is expected to contain metadata about the contents of the project in JSON format. Field Description data type projectName A unique name that will be associated to this project string version Project's version. It is recommended to use semantic versioning format string author A user handle that identifies the author of the project string license A reference to applicable license terms string description string configs Object containing exemplifying configuration properties for flows that may need them. The keys of this field, if any, are qualified flow names already part of the project json object noDirectLaunch An array holding zero or more qualified flow names. This list is used to prevent certain flows to be launched directly from a web browser. It's a security measure to avoid end-users triggering flows at will array All fields are optional and more can be added if desired. Below is an example of a project.json file: { \"projectName\": \"biometric-auth\", \"version\": \"2.0.3\", \"author\": \"avgJoe123\", \"license\": \"apache-2.0\", \"description\": \"Allows users to authenticate via fingerpint and/or iris recognition\", \"configs\": { \"com.acme.bio.IrisScan\": { \"prop1\": \"secret\", \"prop2\": { \"subprop\": [1, 2, 3] } } }, \"noDirectLaunch\": [ \"com.acme.bio.TraitExtractor\" ] } Important Use the configs section wisely: .gama files must not contain real configuration properties because these files may be freely distributed; in practice, configurations hold sensitive data that should not be exposed Sample project # As an example assume you want to deliver these two flows: Flow test Basepath \"hello\" in = { name: \"John\" } RRF \"templates/index.htm\" in Log \"Done!\" Finish \"john_doe\" Flow com.foods.sweet Basepath \"recipes/desserts\" ... choice = RRF \"selection.htm\" list = Call com.foods.RecipeUtils#retrieveIngredients choice.meal ... Here is how the project folder might look like: \u251c\u2500\u2500 code/ \u2502 \u2514\u2500\u2500 test.flow \u2502 \u2514\u2500\u2500 com.foods.sweet.flow \u251c\u2500\u2500 web/ \u2502 \u251c\u2500\u2500 hello/ | | \u2514\u2500\u2500 templates/ \u2502 | \u2514\u2500\u2500 index.htm \u2502 | \u2514\u2500\u2500 js/ \u2502 | \u2514\u2500\u2500 font-awesome.js | \u2514\u2500\u2500 recipes/ \u2502 \u2514\u2500\u2500 desserts/ \u2502 \u2514\u2500\u2500 selection.htm \u2502 \u2514\u2500\u2500 logo.png \u251c\u2500\u2500 lib/ \u2502 \u2514\u2500\u2500 com/ \u2502 \u2514\u2500\u2500 foods/ \u2502 \u2514\u2500\u2500 RecipeUtils.java \u2514\u2500\u2500 project.json .gama file # Dealing with a folder this way can be awkward for sharing and other tasks. Instead, if the project contents are compressed using the ZIP file format, we have what is known as .gama file. Thus, a .gama file is a project archive that can be shared and deployed to an Agama engine. Project deployment # The actual \"deployment\" of an Agama project is an engine-specific detail. Engines must offer mechanisms for administrators and developers to \"install\" .gama files.", "title": "gama format"}, {"location": "agama/gama-format/#the-gama-file-format", "text": "In practice, a web flow will make use of a bunch of artifacts, like UI pages, images, stylesheets, and source code. Actually, to solve a real-world problem several flows are needed to be able to keep flexibility and complexity at acceptable levels. Here is where the concept project emerges. A project can be thought of as a container to hold all flows and related assets aimed at solving a particular problem - including metadata of the project itself. The idea of defining a standard way to specify projects brings several benefits: Provide a uniform conceptual scheme for community actors to interchange flows Provide Agama engine implementors common ground for the materialization of flows deployment Serve as reference for developers interested in coding tools such as an Agama IDE", "title": "The .gama file format"}, {"location": "agama/gama-format/#anatomy-of-a-project", "text": "The below shows the structure of an Agama project: \u251c\u2500\u2500 code/ \u251c\u2500\u2500 lib/ \u251c\u2500\u2500 web/ \u251c\u2500\u2500 project.json \u251c\u2500\u2500 LICENSE \u2514\u2500\u2500 README.md code directory holds all flows part of the project. Every flow - implemented in Agama language - has to reside in a separate file with extension flow and with file name matching the qualified name of the flow in question. This directory can have nested folders if desired lib may contain source code files in languages other than Agama and binary libraries required by the project, if any. Every engine can make use of the contents of this folder as needed web is expected to hold all UI templates plus required web assets (stylesheets, images, localization strings, etc.) that all flows in this project may use project.json file contains metadata about this project. More on this later README.md file may contain extra documentation in markdown format LICENSE file may contain legal-related information Except for code and web directories, all elements in the file structure above are optional. Note that files in web must follow a directory structure that is consistent with respect to Basepath and RRF directives found in the included flows.", "title": "Anatomy of a project"}, {"location": "agama/gama-format/#metadata", "text": "project.json file is expected to contain metadata about the contents of the project in JSON format. Field Description data type projectName A unique name that will be associated to this project string version Project's version. It is recommended to use semantic versioning format string author A user handle that identifies the author of the project string license A reference to applicable license terms string description string configs Object containing exemplifying configuration properties for flows that may need them. The keys of this field, if any, are qualified flow names already part of the project json object noDirectLaunch An array holding zero or more qualified flow names. This list is used to prevent certain flows to be launched directly from a web browser. It's a security measure to avoid end-users triggering flows at will array All fields are optional and more can be added if desired. Below is an example of a project.json file: { \"projectName\": \"biometric-auth\", \"version\": \"2.0.3\", \"author\": \"avgJoe123\", \"license\": \"apache-2.0\", \"description\": \"Allows users to authenticate via fingerpint and/or iris recognition\", \"configs\": { \"com.acme.bio.IrisScan\": { \"prop1\": \"secret\", \"prop2\": { \"subprop\": [1, 2, 3] } } }, \"noDirectLaunch\": [ \"com.acme.bio.TraitExtractor\" ] } Important Use the configs section wisely: .gama files must not contain real configuration properties because these files may be freely distributed; in practice, configurations hold sensitive data that should not be exposed", "title": "Metadata"}, {"location": "agama/gama-format/#sample-project", "text": "As an example assume you want to deliver these two flows: Flow test Basepath \"hello\" in = { name: \"John\" } RRF \"templates/index.htm\" in Log \"Done!\" Finish \"john_doe\" Flow com.foods.sweet Basepath \"recipes/desserts\" ... choice = RRF \"selection.htm\" list = Call com.foods.RecipeUtils#retrieveIngredients choice.meal ... Here is how the project folder might look like: \u251c\u2500\u2500 code/ \u2502 \u2514\u2500\u2500 test.flow \u2502 \u2514\u2500\u2500 com.foods.sweet.flow \u251c\u2500\u2500 web/ \u2502 \u251c\u2500\u2500 hello/ | | \u2514\u2500\u2500 templates/ \u2502 | \u2514\u2500\u2500 index.htm \u2502 | \u2514\u2500\u2500 js/ \u2502 | \u2514\u2500\u2500 font-awesome.js | \u2514\u2500\u2500 recipes/ \u2502 \u2514\u2500\u2500 desserts/ \u2502 \u2514\u2500\u2500 selection.htm \u2502 \u2514\u2500\u2500 logo.png \u251c\u2500\u2500 lib/ \u2502 \u2514\u2500\u2500 com/ \u2502 \u2514\u2500\u2500 foods/ \u2502 \u2514\u2500\u2500 RecipeUtils.java \u2514\u2500\u2500 project.json", "title": "Sample project"}, {"location": "agama/gama-format/#gama-file", "text": "Dealing with a folder this way can be awkward for sharing and other tasks. Instead, if the project contents are compressed using the ZIP file format, we have what is known as .gama file. Thus, a .gama file is a project archive that can be shared and deployed to an Agama engine.", "title": ".gama file"}, {"location": "agama/gama-format/#project-deployment", "text": "The actual \"deployment\" of an Agama project is an engine-specific detail. Engines must offer mechanisms for administrators and developers to \"install\" .gama files.", "title": "Project deployment"}, {"location": "agama/introduction/", "tags": ["administration", "developer", "agama"], "text": "Agama overview # Agama is a framework that consists of: A DSL (domain-specific language) purposedly designed for writing web flows A set of rules that drive the behavior of such flows when they are executed The specification of a file format - known as .gama - useful for sharing Agama flows. Flows have the .flow file extension. Here, a web flow is understood as a process composed by one or more stages, where at each stage an actor - normally a person - provides some kind of data or response by using a web browser or similar client. Throughout the process only a single actor is involved. DSL # About the Agama language is worth to mention that: It helps depicting the structure of web flows in a natural way It is closer to human language than general-purpose programming languages It has a clean, concise, non-distracting syntax It has limited computational power by design, forcing computations to occur in a more formal, general-purpose language like Java, C++, etc. Intrinsic properties of the language include: It follows the imperative paradigm mainly and assumes a traditional sequential execution. It only makes use of a few declarative elements Flows can be treated as functions (reusable routines with well-defined inputs) It provides dedicated contructs for common patterns in web flows like: \"show a page\" and \"retrieve the data user provided in that page\" \"redirect a user to an external site\" and later \"retrieve the data provided at a callback URL\" It supports typical language elements like assignments, conditionals, loops, etc. Find the complete Agama DSL reference here . Behavioral rules of execution # These are aspects that concrete implementations of the framework must adhere to. Rules may include for instance: How and when a flow terminates If and how errors are handled in a flow How flows' assets, i.e. UI pages, images, stylesheets, etc., are organized or laid out How delegation of business logic execution occur in a language other than Agama A \"concrete implementation\" as referred above is known as an engine : a software component capable of running flows written in Agama DSL. More information on execution rules can be found here . .gama file format # Check this page for more information.", "title": "Introduction"}, {"location": "agama/introduction/#agama-overview", "text": "Agama is a framework that consists of: A DSL (domain-specific language) purposedly designed for writing web flows A set of rules that drive the behavior of such flows when they are executed The specification of a file format - known as .gama - useful for sharing Agama flows. Flows have the .flow file extension. Here, a web flow is understood as a process composed by one or more stages, where at each stage an actor - normally a person - provides some kind of data or response by using a web browser or similar client. Throughout the process only a single actor is involved.", "title": "Agama overview"}, {"location": "agama/introduction/#dsl", "text": "About the Agama language is worth to mention that: It helps depicting the structure of web flows in a natural way It is closer to human language than general-purpose programming languages It has a clean, concise, non-distracting syntax It has limited computational power by design, forcing computations to occur in a more formal, general-purpose language like Java, C++, etc. Intrinsic properties of the language include: It follows the imperative paradigm mainly and assumes a traditional sequential execution. It only makes use of a few declarative elements Flows can be treated as functions (reusable routines with well-defined inputs) It provides dedicated contructs for common patterns in web flows like: \"show a page\" and \"retrieve the data user provided in that page\" \"redirect a user to an external site\" and later \"retrieve the data provided at a callback URL\" It supports typical language elements like assignments, conditionals, loops, etc. Find the complete Agama DSL reference here .", "title": "DSL"}, {"location": "agama/introduction/#behavioral-rules-of-execution", "text": "These are aspects that concrete implementations of the framework must adhere to. Rules may include for instance: How and when a flow terminates If and how errors are handled in a flow How flows' assets, i.e. UI pages, images, stylesheets, etc., are organized or laid out How delegation of business logic execution occur in a language other than Agama A \"concrete implementation\" as referred above is known as an engine : a software component capable of running flows written in Agama DSL. More information on execution rules can be found here .", "title": "Behavioral rules of execution"}, {"location": "agama/introduction/#gama-file-format", "text": "Check this page for more information.", "title": ".gama file format"}, {"location": "agama/language-reference/", "tags": ["developer", "agama"], "text": "Agama DSL reference # This document surveys the different constructs of the Agama domain-specific language. Code comments # There is support for single line comments only (no block comments). Use // to start a comment. Comments can start anywhere in a line. Data types # In practice, values would fit into any of: string , boolean , number , list or map . Since routines implemented in other languages can be invoked (more on this later), returned values might not match up exactly with these categories, however this is not too relevant because there is no strict type enforcement in Agama. Literals # Strings # They are surrounded by double quotes. Examples: \"Agama\" , \"blah\" , \"\" (empty string) Backslash can be used to escape chars, like \"Hello\\nGluu\" (line feed), \"Hi\\u0040\" (unicode character) Including double quotes in strings requires unicode escaping, like \"\\u0022\" . Using \"\\\"\" won't work Booleans # Only true or false allowed (notice they are lowercased) Numbers # They are expressed in base 10 only Can be signed or unsigned, with or without decimal: 0 , -1 , 2.0 , 2.3 , -3.000001 , etc. No exponential notation allowed (e.g. 1E-05 ) The following are not valid: .1 , -.1 , +1 . These are their OK equivalents: 0.1 , -0.1 , 1 Null # The \u201cspecial\u201d value null can be used (responsibly) to represent the absence of a value. It is a direct consequence of supporting the integration of other languages in the DSL. Lists # They are finite sequences. Elements are separated by commas Examples: [ 1, 2, 3 ] , [ \"bah!\", \"humbug\" ] , [ ] (empty list) Elements of a list do not have to be of the same type: [ false, [ 0, 1], \"?\" ] is legal but generally discouraged Commas can be surrounded by any combination of spaces and new lines. This is handy when a list takes up some space. This is legal: [ \"no\", \"such\", \"thing\" , \"as\", \"a\", \"stupid\",\"question\"] Maps # They are in essence associative arrays (a.k.a. dictionaries): unordered collections of key/value pairs Example: { brand: \"Ford\", color: null, model: 1963, overhaulsIn: [ 1979, 1999 ] } . This map keys are brand , color , model , and overhaulsIn In literal notation, keys names must follow the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* so these are all valid key names: a , Agama , b_a , a0_0 ; on the contrary, _a , 9 , -a , and \"aha\" are invalid key names As with lists, commas can be surrounded by any combination of spaces and new lines Variables # Variable names follow the pattern: [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* camelCase naming is recommended Variables are not declared, just used freely. Variables are always global in a given flow They can be assigned a value using the equal sign. Example: colors = [ \"red\", \"blue\" ] They can be assigned several times in the same flow Accessing and mutating data in variables # Strings # Suppose x is a string. Individual characters can be accessed by zero-based indexes: x[0] , x[1] , etc. and they are themselves considered strings of size 1 x.length returns the string size (number of characters in it). Strings are not modifiable (neither size nor individual characters can be altered) Lists # Suppose x is a list. Elements can be accessed by zero-based indexes: x[0] , x[1] , etc. Elements of a list can be assigned (and re-assigned) using indexes too. Example: x[2] = false x.length returns the list size. This value can be updated in order to shrink or grow a list (e.g. x.length = 10 ). When extending a list beyond its current length, the \u201cgap\u201d created is filled with null values An attempt to access an index position greater than or equal to the list size returns null (most general-purpose languages would raise a runtime error in this situation) Using expressions for indexing is not allowed, like x[person.age] , x[y[0]] Click here to learn more about access in lists Maps # Suppose x is map. Values can be accessed by using \u201cdot notation\u201d Say x = { brand: \"Ford\", color: null, model: 1963, overhaulsIn: [ 1979, 1999 ] } , then x.model evaluates to 1963 , and x.overhaulsIn[1] evaluates to 1999 Setting the color would be like x.color = \"white\" A new key/value pair can be appended too: x.maxSpeed = 90 Access of an unknown property evaluates to null : x.owner If a key name does not follow the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* an alternative notation must be employed to retrieve or modify the associated value. Click here to learn more Flow structure # A flow written in Agama consists of a header and one or more statements following. Header basics # A header is declarative by nature. It starts with the Flow keyword followed by the qualified name of the flow, e.g. Flow com.acme.FoodSurvey . A qualified name is a sequence of one or more fragments separated by dot ( . ) where a fragment follows the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* . By convention, qualified names shall adhere to a reverse Internet domain name notation. In a header, at minimum, a base path literal string must be provided (in an indented block). This sets the location where flow assets will reside relative to the assets root: Flow com.acme.FoodSurvey Basepath \"mydir\" Here, assets refer to all elements required to build the end-user experience: UI pages, stylesheets, images, etc. The storage of these elements and location of the \"root\" are specific to the concrete Agama engine implementation used. Generally it will resemble a directory structure in a filesystem. Next, flow timeout may be specified. This is the maximum amount of time the end-user can take to fully complete a flow. For instance: Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds An unsigned integer literal value must be specified after the Timeout keyword, if present. The Configs keyword may be used to designate a variable so the flow's properties can be accessed in the code. These properties are usually provided when the flow is created - normally through an administrative tool. This process varies from engine to engine. Often flow properties are used to supply configuration parameters to the flow. As an example, suppose a flow that sends a confirmation e-mail has to be implemented. Properties are a good place to hold the configuration of the outgoing mail server to employ: name, port, authentication credentials, etc. For instance, this is how the configuration properties would be bound to variable conf : Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds Configs conf Inputs # In addition to the above, and optionally too, flows may receive inputs from their callers. Input names can be listed using the Inputs keyword: Flow com.acme.FoodSurvey Basepath \"mydir\" Inputs salutation askGender promptRealName Input names follow the same naming conventions (patterns) of variables and can be treated as such in code. Important Note the difference between properties and inputs. Properties are parameters that callers of the flow should not control or be interested in. On the other hand, inputs are parameters that callers supply explicitly to make the flow exhibit certain behaviors. Check this section to learn how callers can pass values to input parameters of a flow. Flow statements # The statements that make up a flow - body - come after the header and start at column 1, ie. aligned with the Flow keyword: Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds Configs conf Inputs salutation askGender promptRealName x = \"Hi\" y = false ... There are several types of statements: branching, looping, web interaction, etc. They will be regarded in the subsequent sections of this document. Note Agama does not support the concept of subroutines/procedures; this is not needed because functional decomposition is carried out by calling subflows . Logging # Flows can issue small messages (normally used as a form of troubleshooting) that will be appended to a log. Every message can be associated a severity level. Both the log location and available levels are engine specific. To append data to the flows log, use the Log instruction. Examples: Code Message appended Notes Log \"Hi there\" Hi there Log \"Hello\" \"world\" Hello world Log can be passed a variable number of parameters Log \"Hello\" \"world\" 0 false Hello world 0 false Log [1, 2, 3, 4, 5] 1, 2, 3, ...more Lists and maps are not traversed wholly Log \"Hell%% 0 %\" \"o\" \" world\" false Hello world 0 false Placeholders usage Log \"% % % yes\" 1 \"two\" 1 two % yes Log \"3\" \"%\" 0 3 % 0 Log \"@warn Today is Friday %th\" 13 Today is Friday 13th Message logged as warning (if the engine features a \"warning\" level) Log \"@w Today's Armageddon \\u263A\" Today's Armageddon \u263a Message logged as warning (if the engine features a \"w\" level - shortcut method) Check your engine's documentation to learn more about how statements are logged. Conditionals and branching # Keywords When and Otherwise allow to write conditionals. With and , or , is , and is not , logical (boolean) expressions can be built. Examples: car = { brand: \"Ford\", color: null, model: 1963 } When car.color is null car.color = \"pink\" ... Nested conditionals: ... When car.color is \"pink\" When car.brand is \"Ford\" Log \"Weird-looking car\" ... Use of Otherwise : ... When car.color is not null Log \"you have a regular painted car\" ... Otherwise ... Boolean expressions can span several lines: and and or can be at the start or end of a line as long as the whole expression is left-aligned with its corresponding When . Examples: //legal: When day is cloudy When there is hope and there is mercy Log \"let's rock n' roll\" ... When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... //illegal: When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... Notes: Equality is designed to work with null , numbers, strings, and boolean values only. More exactly, a number should only be compared to a number, a string to a string, etc., otherwise the equality test evaluates to false . Comparing a value with itself evaluates to true regardless of type, i.e. car is car , null is null , false is false are all truthy Comparisons are limited to equality ( is ) or inequality ( is not ). For other forms of comparison you can resort foreign routines As expected and has higher priority than or when evaluating expressions. There is no way to group expressions to override the precedence: there are no parenthesis in Agama. Assigning the result of a boolean expression to a variable is not supported. These restrictions are important when writing conditionals Advanced matching # Agama's Match ... to is a construct similar to C/Java switch . Example: car = ... x = ... y = ... // Assume x and y hold numbers z = [ 3.1416, 2.71828 ] Match car.model to x //Code in this block will be executed if car.model is equal to the value of x ... -y //Here we use minus y ... z[0] ... 1.618 //Literal values can be used too for matching ... null ... Otherwise //optional block //Instructions here are executed if there was no match at all Flow finish # Finish is used to terminate a flow's execution. A flow can finish successfully or failed. Examples: Code Meaning Finish true Shorthand for flow finished successfully Finish false Shorthand for failed flow it = { success: true, data: { userId: \"as9233Qz\", ... }} Finish it Flow finished successfully. Some relevant data attached it = { success: false, error: \"User entered a wrong password 3 times\" } Finish it Flow failed. Error description attached Finish \"as9233Qz\" Shorthand for { success: true, data: { userId: \"as9233Qz\" } } it = { nonsense: [ null ] } Finish it.nonsense This causes the flow to crash. Note this is not equivalent to Finish false (which means the flow ended with a negative outcome). Notes: Unless otherwise stated by the concrete engine implementation, a map literal should not be passed directly as argument. This means the following is illegal: Finish { success: false, error: \"spacetime singularity\" } . The examples above list several syntactically valid usages Any statement found after Finish is not reached and thus, not executed If no Finish statement is found in a flow's execution, this will degenerate in flow crash When a flow is finished and was used as subflow (part of the execution of a bigger parent flow), the parent does not terminate. Execution continues at the following instruction that triggered the subflow. More on Trigger later Using data in the Finish directive is an effective way to communicate information to callers (parent flows) Learn more about flows lifecycle here Web interaction # Web interaction constructs bring the most value to Agama. Developers can express the concepts of \u201dredirect a user to an external site and retrieve any data later provided\u201d or \u201cshow a page and grab user data after interaction\u201d using atomic instructions. RFAC # RFAC (stands for Redirect and Fetch at callback ) abstracts the process of redirecting the user's browser to an external site and then collect the data presented later at a designated callback URL. This feature is particularly useful in inbound identity scenarios (e.g. to support social login). Example Details RFAC \"https://login.twitter.com/?blah..&boo=...\" Redirects to the given location. Once the user browser is taken to the callback URL by the external site (twitter.com), the flow continues ignoring any data included map = { twitter: { loginUrl: \"https://...\", ... }, ... } result = RFAC map.twitter.loginUrl Redirects to the given location. Once the user browser is taken to the callback URL by the external site, the data included in the query string or payload is stored in result (a map) for further processing The callback URL varies depending on the engine used. Check your engine's docs. RRF # RRF (stands for Render-Reply-Fetch ) abstracts the process of rendering a UI template, send the produced markup to the browser and grab user-provided data back at the server side. Example Details RRF \"survey.htm\" Renders the template survey.htm (located in this flow's base path) and resulting markup is replied to user's browser. Data submitted by the user is ignored obj = { salutation: \"Hey!\", ... } result = RRF \"survey.htm\" obj Renders the template survey.htm by injecting the data passed in obj and the resulting markup is replied to user's browser. Data submitted by the user is stored in variable result : a map whose keys are named according to the form fields present in survey.htm Notes: The template location must be specified with a string literal only (not a variable) Where and how to store templates is an engine-specific detail as well as the file formats supported. See Assets management . Use map variables - not literal maps - for the second argument of RRF Looping # There are two constructs available for looping in Agama: Repeat and Iterate over . Repeat # Repeat was designed with the concept of attempts/retries in mind: a set of statements are executed, a condition can optionally be supplied in order to abort the loop early, and (optionally too) a block of statements can be executed before the next iteration is started if the condition evaluated to false . A loop is given a maximum number of iterations. Examples: Example Notes month = \"\u2026\" Repeat 3 times max data = RRF \"guess_birthday_month.htm\" //Quit is optional in loops Quit When data.guess is month A loop that runs 3 iterations at most. A page is shown at every iteration. If the value entered by the user matches that of month variable, the loop is aborted earlier x = \u2026 // an integer value month = \"\u2026\" obj = { error: null } Repeat x times max data = RRF \"guess_birthday_month.htm\" obj Quit When data.guess is month obj.error = \"Wrong! try again\" Similar to previous example This time the max no. of iterations is set using a variable When there is a miss a message error is set (which the UI template may potentially use) x = \u2026 // an integer value month = \"\u2026\" obj = { error: null } y = Repeat x times max data = RRF \"guess_birthday_month.htm\" obj Quit When data.guess is month obj.error = \"Wrong! try again\" Log \"Attempt number:\" idx[0] Similar to previous example After the loop finishes, variable y will contain the total number of iterations made to completion. This excludes partial iterations aborted by Quit , thus, y < = x Note the usage of implicit variable idx which holds the current (zero-based) iteration number Iterate over # Iterate over is used to traverse the items of a string, list, or the keys of a map. At every iteration, a variable is set with the current item or key name. As with Repeat , a loop may be aborted earlier, an optional block of statements can be specified after Quit , and the total number of iterations can be stored in a variable. Example Notes seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] Iterate over seasons using sn Log \"There is nothing like\" sn A loop running over a simple list. Every element visited is referenced with variable sn human = { weight: 100, height: 5.9, age: 26 } Iterate over human using attribute Log attribute \"is\" human.$attribute Iterates over the keys of the map printing both the key and its associated value. To learn about the .$ notation see Maps and dot notation seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer\", \"golf\", \"tennis\" ] Iterate over seasons using sn Iterate over sports using sport Log \"There is nothing like playing % in %\" sport sn Nested loops seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer,\" \"golf\", \"tenis\" ] Iterate over seasons using sn y = Iterate over sports using sport Log \"Shall we play % in % ?\" sport sn Quit When sn is \"winter\" Log \"yes!\" Log \"We played % sports in %\" y sn Similar to the previous example. The inner loop is aborted upon a given condition. Note the total number of complete iterations is recorded in y every time the inner loop finishes. seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer,\" \"golf\", \"tenis\" ] Iterate over seasons using sn Iterate over sports using sport Log idx[0] idx[1] Prints iteration numbers: 0 0, 0 1, 0 2, 1 0, 1 1, 1 2, ... 3 2 The index used in idx is 0 for the outermost loop and increases by one at every level of loop nesting Subflows # A flow can Trigger another flow (a.k.a subflow) and grab its response when Finish ed. This feature materializes flow composition and re-use in Agama. Example Notes Trigger jo.jo.PersonalInfoGathering Starts the flow with qualified name jo.jo.PersonalInfoGathering . Returned data is ignored outcome = Trigger jo.jo.PersonalInfoGathering null false Log \"subflow returned with success?\" outcome.success Starts a flow passing parameters (assuming PersonalInfoGathering receives two inputs). outcome will contain the map used when the subflow ended outcome | E = Trigger jo.jo.PersonalInfoGathering null false Similar to the previous example. If for some reason PersonalInfoGathering crashes, variable E will hold a reference to the error for further processing. Otherwise E evaluates to null . The type/structure of E is an engine-specific detail. The variable on the left of the pipe ( | ) can be omitted if the outcome of the flow will not be inspected userPrefs = { otp: \"...\", ... } Match userPrefs.otp to \"e-mail\" flow = \"co.acme.EmailOTP\" \"sms\" flow = \"co.acme.SmsOTP\" Trigger $flow Starts a flow whose qualified name is determined at runtime Input parameters # The values passed after the flow name in Trigger are supplied as input parameters in the order declared by the subflow's Inputs . When not enough values are passed, the unassigned inputs will hold a null value. Unless otherwise stated by the concrete engine implementation, list and map literals should not be passed as arguments to Trigger : Illegal: Trigger subflow { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] Legal: Trigger subflow x car.model list[1] null false -3 \"Sam\" Template overrides # When re-using flows, existing templates may not match the required look-and-feel or layout of the flow that is being built, or may require minor adjustments to fit better the parent's needs. These can be overcome by declaring which templates the developer would like to override for a given subflow call. Example: outcome = Trigger jo.jo.PersonalInfoGathering Override templates \"path/basic.htm\" \"\" \"path2/dir/detail.htm\" \"tmp/mydetail.htm\" Log \"subflow returned with success?\" outcome.success In an indented block using the Override templates keyword, several string literals can be provided. They specify the paths of the (subflows) templates that will be overriden by the parent and the corresponding new paths. In the example above, templates path/basic.htm and path2/dir/detail.htm rendered by flow PersonalInfoGathering (or its subflows) won't be picked from these locations but from the base path of the current (parent) flow using names basic.htm and tmp/mydetail.htm respectively. Usage of empty string denotes reusing the same file name than the original file. Alternatively, every pair of original vs. new path can be specified in a single line for more clarity, like this: outcome = Trigger jo.jo.PersonalInfoGathering Override templates \"path/basic.htm\" \"\" \"path2/dir/detail.htm\" \"tmp/mydetail.htm\" ... Note The new (overriding) templates will be injected with the same data original templates would receive. In other words, this directive only \"modifies\" the first parameter of RRF instructions. Foreign routines # Business logic implemented in languages other than Agama can be re-used by means of the Call instruction. Call plays a key role because Agama code serves fundamentally as a depiction of a flow hiding most of the internal details and low-level computations which are in turn delegated to foreign routines. The syntax of this directive is very general and actual semantics are left to the concrete engine. Roughly, here is how a Call can be structured: ( var_expr? ('|' var_name)? = )? Call alnum(.alnum)* (#alnum)? arg* where: var_name is a variable name , e.g.: x , fooBar , x_0 var_expr is a variable expression, e.g.: x , x.a , x[1].b , etc. alnum is syntactically identical to var_name but does not necessarily refer to an existing variable in the code, for instance, it may describe a path to locate a routine in a library arg is a var_expr or any string , number , boolean , null literal So the below are all syntactically valid invocations: Call apple#pear Call apple#pear \"Hi\" x 16 Call apple.banana#pear \"Hi\" abc 16 foo = Call apple.banana#pear \"Hi\" abc 16 foo | error = Call apple.banana#pear \"Hi\" abc 16 | error = Call apple.banana#pear \"Hi\" abc 16 x[0].ahoy.ahoy foo = Call street fighters true false Again, the semantics are given by the specific engine. Consult your engine documentation for examples. Unless otherwise stated by the concrete engine implementation, list and map literals should not be passed as arguments to method calls directly. This means the following is illegal: Call co.Utils#routine { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] . Advanced and special cases in variable manipulation # Indexing in lists # Accessing/modifying list elements requires providing a numeric index between the brackets, e.g. x[ 0 ] . Note variables can also be used for indexing, like x[ y ] where y is a positive integer or zero. For the below table, assume x = [ \"one\", \"two\", \"three\" ] . x[1] //\"two\" y = 1 x[y] //\"two\" x[\"1\"] //illegal x[ z[0] ] //illegal: variable expressions not allowed for indexes x[obj.property] //illegal: variable expressions not allowed for indexes Maps and dot notation # The regular \u201cdot\u201d notation is limited in the sense it is fairly static: developers have to have prior knowledge about the keys' names, in other words, about the structure of maps and nested submaps, like in person.homeAddress.postalCode . Also, there might be cases where a key name does not fit the required pattern, like in person.street-address or persona.direcci\u00f3n ; even worse, there might be cases where the actual key is only known at runtime. There are ways to overcome this: Example Notes x.\"- wow!\" Access the value associated to the key named -wow! prop = ... x.$prop Access the value associated to the key whose name is contained in the variable prop (that holds a string value). Note actual value of prop may be originated from a Java call or another form of computation propA = ... propB = ... x.$propA.c.\"d\".$propB A mix of notations is valid. For example, if x= { a: { b: 0, c: { c: true, d: { e: null, f: \"hello\" } } } } , propA is equal to \"a\" , and propB to \"f\" , the expression on the left evaluates \"hello\" Usage of .$ requires to supply a variable after the dollar sign: grouped variable expressions are not supported. Thus, it is not possible to achieve something like x.a.c.($map.mykey).f in order to obtain \"hello\" if map = { mykey: \"d\" } . Indexing in maps # For convenience, when a key name \u201clooks like\u201d a positive integer (or zero), e.g. \"2\" , \"10\" , etc., numeric values can directly be used to get/set data in a map: x = { } x.\"1\" = \"golf\" x[1] //retrieves \"golf\" x[2] = \"polo\" //adds the key/value pair \"2\" / \"polo\" Language keywords # The following is a list of reserved words and as such, cannot be used as variable names or maps keys (in literal notation). Keyword Purpose/usage Basepath header declaration Call Java interaction Configs header declaration Finish termination Flow header declaration Inputs header declaration Iterate over loops Log logging Match conditionals Otherwise conditionals Override templates web interaction Quit conditionals and loops Repeat loops RFAC web interaction RRF web interaction seconds header declaration times max loops to conditionals Timeout header declaration Trigger subflow calls using loops When conditionals Operator and is is not or Special literals true false null", "title": "Language reference"}, {"location": "agama/language-reference/#agama-dsl-reference", "text": "This document surveys the different constructs of the Agama domain-specific language.", "title": "Agama DSL reference"}, {"location": "agama/language-reference/#code-comments", "text": "There is support for single line comments only (no block comments). Use // to start a comment. Comments can start anywhere in a line.", "title": "Code comments"}, {"location": "agama/language-reference/#data-types", "text": "In practice, values would fit into any of: string , boolean , number , list or map . Since routines implemented in other languages can be invoked (more on this later), returned values might not match up exactly with these categories, however this is not too relevant because there is no strict type enforcement in Agama.", "title": "Data types"}, {"location": "agama/language-reference/#literals", "text": "", "title": "Literals"}, {"location": "agama/language-reference/#strings", "text": "They are surrounded by double quotes. Examples: \"Agama\" , \"blah\" , \"\" (empty string) Backslash can be used to escape chars, like \"Hello\\nGluu\" (line feed), \"Hi\\u0040\" (unicode character) Including double quotes in strings requires unicode escaping, like \"\\u0022\" . Using \"\\\"\" won't work", "title": "Strings"}, {"location": "agama/language-reference/#booleans", "text": "Only true or false allowed (notice they are lowercased)", "title": "Booleans"}, {"location": "agama/language-reference/#numbers", "text": "They are expressed in base 10 only Can be signed or unsigned, with or without decimal: 0 , -1 , 2.0 , 2.3 , -3.000001 , etc. No exponential notation allowed (e.g. 1E-05 ) The following are not valid: .1 , -.1 , +1 . These are their OK equivalents: 0.1 , -0.1 , 1", "title": "Numbers"}, {"location": "agama/language-reference/#null", "text": "The \u201cspecial\u201d value null can be used (responsibly) to represent the absence of a value. It is a direct consequence of supporting the integration of other languages in the DSL.", "title": "Null"}, {"location": "agama/language-reference/#lists", "text": "They are finite sequences. Elements are separated by commas Examples: [ 1, 2, 3 ] , [ \"bah!\", \"humbug\" ] , [ ] (empty list) Elements of a list do not have to be of the same type: [ false, [ 0, 1], \"?\" ] is legal but generally discouraged Commas can be surrounded by any combination of spaces and new lines. This is handy when a list takes up some space. This is legal: [ \"no\", \"such\", \"thing\" , \"as\", \"a\", \"stupid\",\"question\"]", "title": "Lists"}, {"location": "agama/language-reference/#maps", "text": "They are in essence associative arrays (a.k.a. dictionaries): unordered collections of key/value pairs Example: { brand: \"Ford\", color: null, model: 1963, overhaulsIn: [ 1979, 1999 ] } . This map keys are brand , color , model , and overhaulsIn In literal notation, keys names must follow the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* so these are all valid key names: a , Agama , b_a , a0_0 ; on the contrary, _a , 9 , -a , and \"aha\" are invalid key names As with lists, commas can be surrounded by any combination of spaces and new lines", "title": "Maps"}, {"location": "agama/language-reference/#variables", "text": "Variable names follow the pattern: [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* camelCase naming is recommended Variables are not declared, just used freely. Variables are always global in a given flow They can be assigned a value using the equal sign. Example: colors = [ \"red\", \"blue\" ] They can be assigned several times in the same flow", "title": "Variables"}, {"location": "agama/language-reference/#accessing-and-mutating-data-in-variables", "text": "", "title": "Accessing and mutating data in variables"}, {"location": "agama/language-reference/#strings_1", "text": "Suppose x is a string. Individual characters can be accessed by zero-based indexes: x[0] , x[1] , etc. and they are themselves considered strings of size 1 x.length returns the string size (number of characters in it). Strings are not modifiable (neither size nor individual characters can be altered)", "title": "Strings"}, {"location": "agama/language-reference/#lists_1", "text": "Suppose x is a list. Elements can be accessed by zero-based indexes: x[0] , x[1] , etc. Elements of a list can be assigned (and re-assigned) using indexes too. Example: x[2] = false x.length returns the list size. This value can be updated in order to shrink or grow a list (e.g. x.length = 10 ). When extending a list beyond its current length, the \u201cgap\u201d created is filled with null values An attempt to access an index position greater than or equal to the list size returns null (most general-purpose languages would raise a runtime error in this situation) Using expressions for indexing is not allowed, like x[person.age] , x[y[0]] Click here to learn more about access in lists", "title": "Lists"}, {"location": "agama/language-reference/#maps_1", "text": "Suppose x is map. Values can be accessed by using \u201cdot notation\u201d Say x = { brand: \"Ford\", color: null, model: 1963, overhaulsIn: [ 1979, 1999 ] } , then x.model evaluates to 1963 , and x.overhaulsIn[1] evaluates to 1999 Setting the color would be like x.color = \"white\" A new key/value pair can be appended too: x.maxSpeed = 90 Access of an unknown property evaluates to null : x.owner If a key name does not follow the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* an alternative notation must be employed to retrieve or modify the associated value. Click here to learn more", "title": "Maps"}, {"location": "agama/language-reference/#flow-structure", "text": "A flow written in Agama consists of a header and one or more statements following.", "title": "Flow structure"}, {"location": "agama/language-reference/#header-basics", "text": "A header is declarative by nature. It starts with the Flow keyword followed by the qualified name of the flow, e.g. Flow com.acme.FoodSurvey . A qualified name is a sequence of one or more fragments separated by dot ( . ) where a fragment follows the pattern [a-zA-Z]( _ | [a-zA-Z] | [0-9] )* . By convention, qualified names shall adhere to a reverse Internet domain name notation. In a header, at minimum, a base path literal string must be provided (in an indented block). This sets the location where flow assets will reside relative to the assets root: Flow com.acme.FoodSurvey Basepath \"mydir\" Here, assets refer to all elements required to build the end-user experience: UI pages, stylesheets, images, etc. The storage of these elements and location of the \"root\" are specific to the concrete Agama engine implementation used. Generally it will resemble a directory structure in a filesystem. Next, flow timeout may be specified. This is the maximum amount of time the end-user can take to fully complete a flow. For instance: Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds An unsigned integer literal value must be specified after the Timeout keyword, if present. The Configs keyword may be used to designate a variable so the flow's properties can be accessed in the code. These properties are usually provided when the flow is created - normally through an administrative tool. This process varies from engine to engine. Often flow properties are used to supply configuration parameters to the flow. As an example, suppose a flow that sends a confirmation e-mail has to be implemented. Properties are a good place to hold the configuration of the outgoing mail server to employ: name, port, authentication credentials, etc. For instance, this is how the configuration properties would be bound to variable conf : Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds Configs conf", "title": "Header basics"}, {"location": "agama/language-reference/#inputs", "text": "In addition to the above, and optionally too, flows may receive inputs from their callers. Input names can be listed using the Inputs keyword: Flow com.acme.FoodSurvey Basepath \"mydir\" Inputs salutation askGender promptRealName Input names follow the same naming conventions (patterns) of variables and can be treated as such in code. Important Note the difference between properties and inputs. Properties are parameters that callers of the flow should not control or be interested in. On the other hand, inputs are parameters that callers supply explicitly to make the flow exhibit certain behaviors. Check this section to learn how callers can pass values to input parameters of a flow.", "title": "Inputs"}, {"location": "agama/language-reference/#flow-statements", "text": "The statements that make up a flow - body - come after the header and start at column 1, ie. aligned with the Flow keyword: Flow com.acme.FoodSurvey Basepath \"mydir\" Timeout 100 seconds Configs conf Inputs salutation askGender promptRealName x = \"Hi\" y = false ... There are several types of statements: branching, looping, web interaction, etc. They will be regarded in the subsequent sections of this document. Note Agama does not support the concept of subroutines/procedures; this is not needed because functional decomposition is carried out by calling subflows .", "title": "Flow statements"}, {"location": "agama/language-reference/#logging", "text": "Flows can issue small messages (normally used as a form of troubleshooting) that will be appended to a log. Every message can be associated a severity level. Both the log location and available levels are engine specific. To append data to the flows log, use the Log instruction. Examples: Code Message appended Notes Log \"Hi there\" Hi there Log \"Hello\" \"world\" Hello world Log can be passed a variable number of parameters Log \"Hello\" \"world\" 0 false Hello world 0 false Log [1, 2, 3, 4, 5] 1, 2, 3, ...more Lists and maps are not traversed wholly Log \"Hell%% 0 %\" \"o\" \" world\" false Hello world 0 false Placeholders usage Log \"% % % yes\" 1 \"two\" 1 two % yes Log \"3\" \"%\" 0 3 % 0 Log \"@warn Today is Friday %th\" 13 Today is Friday 13th Message logged as warning (if the engine features a \"warning\" level) Log \"@w Today's Armageddon \\u263A\" Today's Armageddon \u263a Message logged as warning (if the engine features a \"w\" level - shortcut method) Check your engine's documentation to learn more about how statements are logged.", "title": "Logging"}, {"location": "agama/language-reference/#conditionals-and-branching", "text": "Keywords When and Otherwise allow to write conditionals. With and , or , is , and is not , logical (boolean) expressions can be built. Examples: car = { brand: \"Ford\", color: null, model: 1963 } When car.color is null car.color = \"pink\" ... Nested conditionals: ... When car.color is \"pink\" When car.brand is \"Ford\" Log \"Weird-looking car\" ... Use of Otherwise : ... When car.color is not null Log \"you have a regular painted car\" ... Otherwise ... Boolean expressions can span several lines: and and or can be at the start or end of a line as long as the whole expression is left-aligned with its corresponding When . Examples: //legal: When day is cloudy When there is hope and there is mercy Log \"let's rock n' roll\" ... When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... //illegal: When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... When day is cloudy When there is hope and // :D there is mercy or fear is null Log \"let's rock n' roll\" ... Notes: Equality is designed to work with null , numbers, strings, and boolean values only. More exactly, a number should only be compared to a number, a string to a string, etc., otherwise the equality test evaluates to false . Comparing a value with itself evaluates to true regardless of type, i.e. car is car , null is null , false is false are all truthy Comparisons are limited to equality ( is ) or inequality ( is not ). For other forms of comparison you can resort foreign routines As expected and has higher priority than or when evaluating expressions. There is no way to group expressions to override the precedence: there are no parenthesis in Agama. Assigning the result of a boolean expression to a variable is not supported. These restrictions are important when writing conditionals", "title": "Conditionals and branching"}, {"location": "agama/language-reference/#advanced-matching", "text": "Agama's Match ... to is a construct similar to C/Java switch . Example: car = ... x = ... y = ... // Assume x and y hold numbers z = [ 3.1416, 2.71828 ] Match car.model to x //Code in this block will be executed if car.model is equal to the value of x ... -y //Here we use minus y ... z[0] ... 1.618 //Literal values can be used too for matching ... null ... Otherwise //optional block //Instructions here are executed if there was no match at all", "title": "Advanced matching"}, {"location": "agama/language-reference/#flow-finish", "text": "Finish is used to terminate a flow's execution. A flow can finish successfully or failed. Examples: Code Meaning Finish true Shorthand for flow finished successfully Finish false Shorthand for failed flow it = { success: true, data: { userId: \"as9233Qz\", ... }} Finish it Flow finished successfully. Some relevant data attached it = { success: false, error: \"User entered a wrong password 3 times\" } Finish it Flow failed. Error description attached Finish \"as9233Qz\" Shorthand for { success: true, data: { userId: \"as9233Qz\" } } it = { nonsense: [ null ] } Finish it.nonsense This causes the flow to crash. Note this is not equivalent to Finish false (which means the flow ended with a negative outcome). Notes: Unless otherwise stated by the concrete engine implementation, a map literal should not be passed directly as argument. This means the following is illegal: Finish { success: false, error: \"spacetime singularity\" } . The examples above list several syntactically valid usages Any statement found after Finish is not reached and thus, not executed If no Finish statement is found in a flow's execution, this will degenerate in flow crash When a flow is finished and was used as subflow (part of the execution of a bigger parent flow), the parent does not terminate. Execution continues at the following instruction that triggered the subflow. More on Trigger later Using data in the Finish directive is an effective way to communicate information to callers (parent flows) Learn more about flows lifecycle here", "title": "Flow finish"}, {"location": "agama/language-reference/#web-interaction", "text": "Web interaction constructs bring the most value to Agama. Developers can express the concepts of \u201dredirect a user to an external site and retrieve any data later provided\u201d or \u201cshow a page and grab user data after interaction\u201d using atomic instructions.", "title": "Web interaction"}, {"location": "agama/language-reference/#rfac", "text": "RFAC (stands for Redirect and Fetch at callback ) abstracts the process of redirecting the user's browser to an external site and then collect the data presented later at a designated callback URL. This feature is particularly useful in inbound identity scenarios (e.g. to support social login). Example Details RFAC \"https://login.twitter.com/?blah..&boo=...\" Redirects to the given location. Once the user browser is taken to the callback URL by the external site (twitter.com), the flow continues ignoring any data included map = { twitter: { loginUrl: \"https://...\", ... }, ... } result = RFAC map.twitter.loginUrl Redirects to the given location. Once the user browser is taken to the callback URL by the external site, the data included in the query string or payload is stored in result (a map) for further processing The callback URL varies depending on the engine used. Check your engine's docs.", "title": "RFAC"}, {"location": "agama/language-reference/#rrf", "text": "RRF (stands for Render-Reply-Fetch ) abstracts the process of rendering a UI template, send the produced markup to the browser and grab user-provided data back at the server side. Example Details RRF \"survey.htm\" Renders the template survey.htm (located in this flow's base path) and resulting markup is replied to user's browser. Data submitted by the user is ignored obj = { salutation: \"Hey!\", ... } result = RRF \"survey.htm\" obj Renders the template survey.htm by injecting the data passed in obj and the resulting markup is replied to user's browser. Data submitted by the user is stored in variable result : a map whose keys are named according to the form fields present in survey.htm Notes: The template location must be specified with a string literal only (not a variable) Where and how to store templates is an engine-specific detail as well as the file formats supported. See Assets management . Use map variables - not literal maps - for the second argument of RRF", "title": "RRF"}, {"location": "agama/language-reference/#looping", "text": "There are two constructs available for looping in Agama: Repeat and Iterate over .", "title": "Looping"}, {"location": "agama/language-reference/#repeat", "text": "Repeat was designed with the concept of attempts/retries in mind: a set of statements are executed, a condition can optionally be supplied in order to abort the loop early, and (optionally too) a block of statements can be executed before the next iteration is started if the condition evaluated to false . A loop is given a maximum number of iterations. Examples: Example Notes month = \"\u2026\" Repeat 3 times max data = RRF \"guess_birthday_month.htm\" //Quit is optional in loops Quit When data.guess is month A loop that runs 3 iterations at most. A page is shown at every iteration. If the value entered by the user matches that of month variable, the loop is aborted earlier x = \u2026 // an integer value month = \"\u2026\" obj = { error: null } Repeat x times max data = RRF \"guess_birthday_month.htm\" obj Quit When data.guess is month obj.error = \"Wrong! try again\" Similar to previous example This time the max no. of iterations is set using a variable When there is a miss a message error is set (which the UI template may potentially use) x = \u2026 // an integer value month = \"\u2026\" obj = { error: null } y = Repeat x times max data = RRF \"guess_birthday_month.htm\" obj Quit When data.guess is month obj.error = \"Wrong! try again\" Log \"Attempt number:\" idx[0] Similar to previous example After the loop finishes, variable y will contain the total number of iterations made to completion. This excludes partial iterations aborted by Quit , thus, y < = x Note the usage of implicit variable idx which holds the current (zero-based) iteration number", "title": "Repeat"}, {"location": "agama/language-reference/#iterate-over", "text": "Iterate over is used to traverse the items of a string, list, or the keys of a map. At every iteration, a variable is set with the current item or key name. As with Repeat , a loop may be aborted earlier, an optional block of statements can be specified after Quit , and the total number of iterations can be stored in a variable. Example Notes seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] Iterate over seasons using sn Log \"There is nothing like\" sn A loop running over a simple list. Every element visited is referenced with variable sn human = { weight: 100, height: 5.9, age: 26 } Iterate over human using attribute Log attribute \"is\" human.$attribute Iterates over the keys of the map printing both the key and its associated value. To learn about the .$ notation see Maps and dot notation seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer\", \"golf\", \"tennis\" ] Iterate over seasons using sn Iterate over sports using sport Log \"There is nothing like playing % in %\" sport sn Nested loops seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer,\" \"golf\", \"tenis\" ] Iterate over seasons using sn y = Iterate over sports using sport Log \"Shall we play % in % ?\" sport sn Quit When sn is \"winter\" Log \"yes!\" Log \"We played % sports in %\" y sn Similar to the previous example. The inner loop is aborted upon a given condition. Note the total number of complete iterations is recorded in y every time the inner loop finishes. seasons = [ \"spring\", \"winter\", \"fall\", \"summer\" ] sports = [ \"soccer,\" \"golf\", \"tenis\" ] Iterate over seasons using sn Iterate over sports using sport Log idx[0] idx[1] Prints iteration numbers: 0 0, 0 1, 0 2, 1 0, 1 1, 1 2, ... 3 2 The index used in idx is 0 for the outermost loop and increases by one at every level of loop nesting", "title": "Iterate over"}, {"location": "agama/language-reference/#subflows", "text": "A flow can Trigger another flow (a.k.a subflow) and grab its response when Finish ed. This feature materializes flow composition and re-use in Agama. Example Notes Trigger jo.jo.PersonalInfoGathering Starts the flow with qualified name jo.jo.PersonalInfoGathering . Returned data is ignored outcome = Trigger jo.jo.PersonalInfoGathering null false Log \"subflow returned with success?\" outcome.success Starts a flow passing parameters (assuming PersonalInfoGathering receives two inputs). outcome will contain the map used when the subflow ended outcome | E = Trigger jo.jo.PersonalInfoGathering null false Similar to the previous example. If for some reason PersonalInfoGathering crashes, variable E will hold a reference to the error for further processing. Otherwise E evaluates to null . The type/structure of E is an engine-specific detail. The variable on the left of the pipe ( | ) can be omitted if the outcome of the flow will not be inspected userPrefs = { otp: \"...\", ... } Match userPrefs.otp to \"e-mail\" flow = \"co.acme.EmailOTP\" \"sms\" flow = \"co.acme.SmsOTP\" Trigger $flow Starts a flow whose qualified name is determined at runtime", "title": "Subflows"}, {"location": "agama/language-reference/#input-parameters", "text": "The values passed after the flow name in Trigger are supplied as input parameters in the order declared by the subflow's Inputs . When not enough values are passed, the unassigned inputs will hold a null value. Unless otherwise stated by the concrete engine implementation, list and map literals should not be passed as arguments to Trigger : Illegal: Trigger subflow { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] Legal: Trigger subflow x car.model list[1] null false -3 \"Sam\"", "title": "Input parameters"}, {"location": "agama/language-reference/#template-overrides", "text": "When re-using flows, existing templates may not match the required look-and-feel or layout of the flow that is being built, or may require minor adjustments to fit better the parent's needs. These can be overcome by declaring which templates the developer would like to override for a given subflow call. Example: outcome = Trigger jo.jo.PersonalInfoGathering Override templates \"path/basic.htm\" \"\" \"path2/dir/detail.htm\" \"tmp/mydetail.htm\" Log \"subflow returned with success?\" outcome.success In an indented block using the Override templates keyword, several string literals can be provided. They specify the paths of the (subflows) templates that will be overriden by the parent and the corresponding new paths. In the example above, templates path/basic.htm and path2/dir/detail.htm rendered by flow PersonalInfoGathering (or its subflows) won't be picked from these locations but from the base path of the current (parent) flow using names basic.htm and tmp/mydetail.htm respectively. Usage of empty string denotes reusing the same file name than the original file. Alternatively, every pair of original vs. new path can be specified in a single line for more clarity, like this: outcome = Trigger jo.jo.PersonalInfoGathering Override templates \"path/basic.htm\" \"\" \"path2/dir/detail.htm\" \"tmp/mydetail.htm\" ... Note The new (overriding) templates will be injected with the same data original templates would receive. In other words, this directive only \"modifies\" the first parameter of RRF instructions.", "title": "Template overrides"}, {"location": "agama/language-reference/#foreign-routines", "text": "Business logic implemented in languages other than Agama can be re-used by means of the Call instruction. Call plays a key role because Agama code serves fundamentally as a depiction of a flow hiding most of the internal details and low-level computations which are in turn delegated to foreign routines. The syntax of this directive is very general and actual semantics are left to the concrete engine. Roughly, here is how a Call can be structured: ( var_expr? ('|' var_name)? = )? Call alnum(.alnum)* (#alnum)? arg* where: var_name is a variable name , e.g.: x , fooBar , x_0 var_expr is a variable expression, e.g.: x , x.a , x[1].b , etc. alnum is syntactically identical to var_name but does not necessarily refer to an existing variable in the code, for instance, it may describe a path to locate a routine in a library arg is a var_expr or any string , number , boolean , null literal So the below are all syntactically valid invocations: Call apple#pear Call apple#pear \"Hi\" x 16 Call apple.banana#pear \"Hi\" abc 16 foo = Call apple.banana#pear \"Hi\" abc 16 foo | error = Call apple.banana#pear \"Hi\" abc 16 | error = Call apple.banana#pear \"Hi\" abc 16 x[0].ahoy.ahoy foo = Call street fighters true false Again, the semantics are given by the specific engine. Consult your engine documentation for examples. Unless otherwise stated by the concrete engine implementation, list and map literals should not be passed as arguments to method calls directly. This means the following is illegal: Call co.Utils#routine { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] .", "title": "Foreign routines"}, {"location": "agama/language-reference/#advanced-and-special-cases-in-variable-manipulation", "text": "", "title": "Advanced and special cases in variable manipulation"}, {"location": "agama/language-reference/#indexing-in-lists", "text": "Accessing/modifying list elements requires providing a numeric index between the brackets, e.g. x[ 0 ] . Note variables can also be used for indexing, like x[ y ] where y is a positive integer or zero. For the below table, assume x = [ \"one\", \"two\", \"three\" ] . x[1] //\"two\" y = 1 x[y] //\"two\" x[\"1\"] //illegal x[ z[0] ] //illegal: variable expressions not allowed for indexes x[obj.property] //illegal: variable expressions not allowed for indexes", "title": "Indexing in lists"}, {"location": "agama/language-reference/#maps-and-dot-notation", "text": "The regular \u201cdot\u201d notation is limited in the sense it is fairly static: developers have to have prior knowledge about the keys' names, in other words, about the structure of maps and nested submaps, like in person.homeAddress.postalCode . Also, there might be cases where a key name does not fit the required pattern, like in person.street-address or persona.direcci\u00f3n ; even worse, there might be cases where the actual key is only known at runtime. There are ways to overcome this: Example Notes x.\"- wow!\" Access the value associated to the key named -wow! prop = ... x.$prop Access the value associated to the key whose name is contained in the variable prop (that holds a string value). Note actual value of prop may be originated from a Java call or another form of computation propA = ... propB = ... x.$propA.c.\"d\".$propB A mix of notations is valid. For example, if x= { a: { b: 0, c: { c: true, d: { e: null, f: \"hello\" } } } } , propA is equal to \"a\" , and propB to \"f\" , the expression on the left evaluates \"hello\" Usage of .$ requires to supply a variable after the dollar sign: grouped variable expressions are not supported. Thus, it is not possible to achieve something like x.a.c.($map.mykey).f in order to obtain \"hello\" if map = { mykey: \"d\" } .", "title": "Maps and dot notation"}, {"location": "agama/language-reference/#indexing-in-maps", "text": "For convenience, when a key name \u201clooks like\u201d a positive integer (or zero), e.g. \"2\" , \"10\" , etc., numeric values can directly be used to get/set data in a map: x = { } x.\"1\" = \"golf\" x[1] //retrieves \"golf\" x[2] = \"polo\" //adds the key/value pair \"2\" / \"polo\"", "title": "Indexing in maps"}, {"location": "agama/language-reference/#language-keywords", "text": "The following is a list of reserved words and as such, cannot be used as variable names or maps keys (in literal notation). Keyword Purpose/usage Basepath header declaration Call Java interaction Configs header declaration Finish termination Flow header declaration Inputs header declaration Iterate over loops Log logging Match conditionals Otherwise conditionals Override templates web interaction Quit conditionals and loops Repeat loops RFAC web interaction RRF web interaction seconds header declaration times max loops to conditionals Timeout header declaration Trigger subflow calls using loops When conditionals Operator and is is not or Special literals true false null", "title": "Language keywords"}, {"location": "casa/user-guide/", "tags": ["Casa", "user guide"], "text": "Jans Casa User Guide # Jans Casa (\"Casa\") is a self-service web portal for managing account security preferences. The primary use-case for Casa is self-service 2FA, but other use cases and functionalities can be supported via Casa plugins. The options displayed in the user portal will always depend upon which settings have been enabled by the administrator. Sign in for the first time # To log in to Casa, navigate to https://<yourdomain>/jans-casa . If you have an existing account, sign in with your standard username and password. Credential Dashboard # The credential dashboard displays widgets for each type of supported 2FA credential (e.g. U2F keys, OTP apps, etc.). Each widget includes summary details of enrolled credentials and a button to add / change credentials. To manage existing credentials and enroll new credentials, click the Manage button: 2FA overview # Turn 2FA on/off # After the minimum number of credentials have been enrolled (as specified by the system admin), 2FA can be turned on by clicking the switch in the Second Factor Authentication widget: If the switch is not visible, your administrator may have configured the system so that 2FA is turned on automatically when enough credentials are available. When prompted for 2FA, the specific credential to be prompted first varies depending on the priority of credentials established by the administrator and the user's preferred method, if set. If at any time the credential prompted is unavailable, you have the option to present any other previously enrolled 2FA credential type. To turn off 2FA, click again the switch. 2FA settings and trusted devices # If enabled by the system administrator, you can set your own policy for when 2FA is enforced. To manage your settings, after enrolling credentials and turning on 2FA, click the Manage your 2FA settings button in the Preferred Authentication Mechanism widget. By default, you will be able to choose from a few 2FA policies: Always (upon every login attempt) If the location (e.g. city) detected in the login attempt is unrecognized If the device used to login is unrecognized If you opt for 2FA based on location, device, or both, a new widget will appear to display your trusted devices. 2FA best practices # Depending on the device used to get access, some credentials are more convenient to use than others. For instance, security keys may not be compatible with mobile phones or certain browsers. To reduce the chance of account lockout , enroll at least two different types of 2FA credentials -- e.g. one security key and one OTP app; or one OTP app and one SMS phone number, etc. This way, regardless which device you're using to access a protected resource, you will have a usable option for passing strong authentication. 2FA credential details & enrollment # The details page provides additional information about each enrolled credential, for instance its name and date of enrollment. Nicknames can be edited, credentials can be deleted and new credentials can be enrolled and nicknamed. Depending on administrator configurations, some of the below sections may nor may not be available, or sections not listed here may appear. Warning When a credential is deleted, it cannot be recovered. Deleting credentials may result in 2FA being turned off. FIDO 2 security keys # To add a new FIDO 2 credential, navigate to 2FA credentials > Security Keys . Insert the fido key and click Ready . Casa will prompt to press the button on the key. Add a nickname and click Add . Once added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device. Super Gluu Devices # To add a new Super Gluu device, navigate to 2FA credentials > Super Gluu Devices . The Super Gluu enrollment QR code will pop up. Scan it in the Super Gluu app and approve the enrollment. Add a nickname for the device and click Add . Once it's added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device. OTP Tokens # To add a new OTP token, navigate to 2FA credentials > OTP Tokens . To add a soft OTP token, choose the Soft token option and follow the same steps as Super Gluu . For a hard token, choose the Hard Token option. Add the key associated with the device and the 6 digit code. Add a nickname for the device and click Add . Once it's added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device. Mobile Phone Numbers # To add a new mobile phone number for one-time passcodes, navigate to 2FA credentials > Mobile Phone Numbers . Enter a phone number and click 'Send SMS' to get the passcode. Enter the code received, nickname the mobile number, and click Add . Once it's added, the new mobile number will appear in a list on the same page. Click the pencil to edit the mobile number's nickname or the trashcan to delete the mobile number. Password Reset # If enabled by the system administrator, Casa can also be used to change your password. Navigate to the Password Reset widget. Enter your current and new passwords, then click Change password . Consent Management # If the administrator has enabled the Consent Management plugin, it will appear in the navigation menu for all users. New entries are added automatically whenever the user is prompted for, and authorizes the release of their personal data to an application accessed using their Janssen Server account. Revoking consent # When a previously granted consent decision is revoked, the user will be re-prompted to authorize release of their data if/when they attempt to access the application again.", "title": "User Guide"}, {"location": "casa/user-guide/#jans-casa-user-guide", "text": "Jans Casa (\"Casa\") is a self-service web portal for managing account security preferences. The primary use-case for Casa is self-service 2FA, but other use cases and functionalities can be supported via Casa plugins. The options displayed in the user portal will always depend upon which settings have been enabled by the administrator.", "title": "Jans Casa User Guide"}, {"location": "casa/user-guide/#sign-in-for-the-first-time", "text": "To log in to Casa, navigate to https://<yourdomain>/jans-casa . If you have an existing account, sign in with your standard username and password.", "title": "Sign in for the first time"}, {"location": "casa/user-guide/#credential-dashboard", "text": "The credential dashboard displays widgets for each type of supported 2FA credential (e.g. U2F keys, OTP apps, etc.). Each widget includes summary details of enrolled credentials and a button to add / change credentials. To manage existing credentials and enroll new credentials, click the Manage button:", "title": "Credential Dashboard"}, {"location": "casa/user-guide/#2fa-overview", "text": "", "title": "2FA overview"}, {"location": "casa/user-guide/#turn-2fa-onoff", "text": "After the minimum number of credentials have been enrolled (as specified by the system admin), 2FA can be turned on by clicking the switch in the Second Factor Authentication widget: If the switch is not visible, your administrator may have configured the system so that 2FA is turned on automatically when enough credentials are available. When prompted for 2FA, the specific credential to be prompted first varies depending on the priority of credentials established by the administrator and the user's preferred method, if set. If at any time the credential prompted is unavailable, you have the option to present any other previously enrolled 2FA credential type. To turn off 2FA, click again the switch.", "title": "Turn 2FA on/off"}, {"location": "casa/user-guide/#2fa-settings-and-trusted-devices", "text": "If enabled by the system administrator, you can set your own policy for when 2FA is enforced. To manage your settings, after enrolling credentials and turning on 2FA, click the Manage your 2FA settings button in the Preferred Authentication Mechanism widget. By default, you will be able to choose from a few 2FA policies: Always (upon every login attempt) If the location (e.g. city) detected in the login attempt is unrecognized If the device used to login is unrecognized If you opt for 2FA based on location, device, or both, a new widget will appear to display your trusted devices.", "title": "2FA settings and trusted devices"}, {"location": "casa/user-guide/#2fa-best-practices", "text": "Depending on the device used to get access, some credentials are more convenient to use than others. For instance, security keys may not be compatible with mobile phones or certain browsers. To reduce the chance of account lockout , enroll at least two different types of 2FA credentials -- e.g. one security key and one OTP app; or one OTP app and one SMS phone number, etc. This way, regardless which device you're using to access a protected resource, you will have a usable option for passing strong authentication.", "title": "2FA best practices"}, {"location": "casa/user-guide/#2fa-credential-details-enrollment", "text": "The details page provides additional information about each enrolled credential, for instance its name and date of enrollment. Nicknames can be edited, credentials can be deleted and new credentials can be enrolled and nicknamed. Depending on administrator configurations, some of the below sections may nor may not be available, or sections not listed here may appear. Warning When a credential is deleted, it cannot be recovered. Deleting credentials may result in 2FA being turned off.", "title": "2FA credential details & enrollment"}, {"location": "casa/user-guide/#fido-2-security-keys", "text": "To add a new FIDO 2 credential, navigate to 2FA credentials > Security Keys . Insert the fido key and click Ready . Casa will prompt to press the button on the key. Add a nickname and click Add . Once added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device.", "title": "FIDO 2 security keys"}, {"location": "casa/user-guide/#super-gluu-devices", "text": "To add a new Super Gluu device, navigate to 2FA credentials > Super Gluu Devices . The Super Gluu enrollment QR code will pop up. Scan it in the Super Gluu app and approve the enrollment. Add a nickname for the device and click Add . Once it's added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device.", "title": "Super Gluu Devices"}, {"location": "casa/user-guide/#otp-tokens", "text": "To add a new OTP token, navigate to 2FA credentials > OTP Tokens . To add a soft OTP token, choose the Soft token option and follow the same steps as Super Gluu . For a hard token, choose the Hard Token option. Add the key associated with the device and the 6 digit code. Add a nickname for the device and click Add . Once it's added, the new device will appear in a list on the same page. Click the pencil to edit the device's nickname or the trashcan to delete the device.", "title": "OTP Tokens"}, {"location": "casa/user-guide/#mobile-phone-numbers", "text": "To add a new mobile phone number for one-time passcodes, navigate to 2FA credentials > Mobile Phone Numbers . Enter a phone number and click 'Send SMS' to get the passcode. Enter the code received, nickname the mobile number, and click Add . Once it's added, the new mobile number will appear in a list on the same page. Click the pencil to edit the mobile number's nickname or the trashcan to delete the mobile number.", "title": "Mobile Phone Numbers"}, {"location": "casa/user-guide/#password-reset", "text": "If enabled by the system administrator, Casa can also be used to change your password. Navigate to the Password Reset widget. Enter your current and new passwords, then click Change password .", "title": "Password Reset"}, {"location": "casa/user-guide/#consent-management", "text": "If the administrator has enabled the Consent Management plugin, it will appear in the navigation menu for all users. New entries are added automatically whenever the user is prompted for, and authorizes the release of their personal data to an application accessed using their Janssen Server account.", "title": "Consent Management"}, {"location": "casa/user-guide/#revoking-consent", "text": "When a previously granted consent decision is revoked, the user will be re-prompted to authorize release of their data if/when they attempt to access the application again.", "title": "Revoking consent"}, {"location": "casa/administration/2fa-basics/", "tags": ["Casa", "2FA", "two-factor"], "text": "About Two-Factor Authentication (2FA) # Note You can tailor different aspects of 2FA behavior in Casa using the plugin developed for this purpose. Availability # By default, strong (two-factor) authentication will be available to users of Casa once they have added at least two credentials. By requiring users to register two strong credentials, the number of account lockouts that require admin intervention will be greatly reduced. If one credential is lost, there will be at least one fallback mechanism available. Avoiding user lockout is important because it prevents a serious burden for IT administrators. There is no limit to the number of credentials a user can enroll, and credentials do not need to be of the same type: any combination is valid. Supported types of 2FA # Users will only be able to add credentials with a type matching one of the already enabled authentication methods in the admin console . Other methods may be supported via plugins . Resetting a user's 2FA availability # In the event a user loses access to his account, admins can revert the user's authentication method to \"password only\" by following the steps shown in the troubleshooting guide . Associated \"strength\" of credentials # When authenticating, a user with 2FA turned on, will be challenged to present the credential having the \"strongest\" authentication method (from his already available enrolled credentials). The relative strength of methods can be assigned in the authentication methods screen of the admin console. Forcing users to enroll a specific credential before 2FA is available # To further reduce the likelihood of lockouts, you can force users to initially enroll, for instance, one OTP credential before any other. OTP credentials are generally more accessible than their counterparts (like Fido) since they normally don't demand special conditions from the device used to access, like having a USB port. To do so, add a property named 2fa_requisite to the configuration of the Agama flow that backs the given authentication method, and assign true as its value. You can do this via TUI . Note this mechanism is applicable for the out-of-the box authentication methods supported by Casa. For other methods contributed via plugins, consult their respective documentation. You can flag more than one method as requisite. In this case users will be encouraged to enroll one credential associated to any of the flagged methods. If a user attempts to delete their only available credential matching the requisite method, a prompt will appear warning that doing so will disable 2FA, that is, resetting to password authentication. If you are a developer coding a plugin that adds an authentication method, you can make the method a requisite by properly implementing method mayBe2faActivationRequisite part of interface AuthnMethod . Enrolling credentials upon registration or first login # If the previous scenario is not enough for your needs, you can force users to enroll credentials and turn 2FA on before the first usage of the application. This can be done in two ways: Creating a new Agama project that takes charge of credentials enrollment and then reuses the flows bundled with the standard Agama project which performs the actual authentication. Learn more about this in the developer pages Making enrollments occur at registration time (through the application you use for this purpose)", "title": "About 2FA"}, {"location": "casa/administration/2fa-basics/#about-two-factor-authentication-2fa", "text": "Note You can tailor different aspects of 2FA behavior in Casa using the plugin developed for this purpose.", "title": "About Two-Factor Authentication (2FA)"}, {"location": "casa/administration/2fa-basics/#availability", "text": "By default, strong (two-factor) authentication will be available to users of Casa once they have added at least two credentials. By requiring users to register two strong credentials, the number of account lockouts that require admin intervention will be greatly reduced. If one credential is lost, there will be at least one fallback mechanism available. Avoiding user lockout is important because it prevents a serious burden for IT administrators. There is no limit to the number of credentials a user can enroll, and credentials do not need to be of the same type: any combination is valid.", "title": "Availability"}, {"location": "casa/administration/2fa-basics/#supported-types-of-2fa", "text": "Users will only be able to add credentials with a type matching one of the already enabled authentication methods in the admin console . Other methods may be supported via plugins .", "title": "Supported types of 2FA"}, {"location": "casa/administration/2fa-basics/#resetting-a-users-2fa-availability", "text": "In the event a user loses access to his account, admins can revert the user's authentication method to \"password only\" by following the steps shown in the troubleshooting guide .", "title": "Resetting a user's 2FA availability"}, {"location": "casa/administration/2fa-basics/#associated-strength-of-credentials", "text": "When authenticating, a user with 2FA turned on, will be challenged to present the credential having the \"strongest\" authentication method (from his already available enrolled credentials). The relative strength of methods can be assigned in the authentication methods screen of the admin console.", "title": "Associated \"strength\" of credentials"}, {"location": "casa/administration/2fa-basics/#forcing-users-to-enroll-a-specific-credential-before-2fa-is-available", "text": "To further reduce the likelihood of lockouts, you can force users to initially enroll, for instance, one OTP credential before any other. OTP credentials are generally more accessible than their counterparts (like Fido) since they normally don't demand special conditions from the device used to access, like having a USB port. To do so, add a property named 2fa_requisite to the configuration of the Agama flow that backs the given authentication method, and assign true as its value. You can do this via TUI . Note this mechanism is applicable for the out-of-the box authentication methods supported by Casa. For other methods contributed via plugins, consult their respective documentation. You can flag more than one method as requisite. In this case users will be encouraged to enroll one credential associated to any of the flagged methods. If a user attempts to delete their only available credential matching the requisite method, a prompt will appear warning that doing so will disable 2FA, that is, resetting to password authentication. If you are a developer coding a plugin that adds an authentication method, you can make the method a requisite by properly implementing method mayBe2faActivationRequisite part of interface AuthnMethod .", "title": "Forcing users to enroll a specific credential before 2FA is available"}, {"location": "casa/administration/2fa-basics/#enrolling-credentials-upon-registration-or-first-login", "text": "If the previous scenario is not enough for your needs, you can force users to enroll credentials and turn 2FA on before the first usage of the application. This can be done in two ways: Creating a new Agama project that takes charge of credentials enrollment and then reuses the flows bundled with the standard Agama project which performs the actual authentication. Learn more about this in the developer pages Making enrollments occur at registration time (through the application you use for this purpose)", "title": "Enrolling credentials upon registration or first login"}, {"location": "casa/administration/admin-console/", "tags": ["Casa", "administration", "admin console"], "text": "Admin Console # This document reviews the available options for configuring Casa. All configuration changes applied via the admin console take effect immediately with no restart or other actions required. Authentication methods # Here you can choose the type of 2FA credentials you want to support in Casa. Every authentication method is represented by a widget you can enable or disable. Administrators can arrange widgets according to perceived \"strength\" order, that is, methods considered safer than others can be placed on top of the list. This ordering has two practical consequences: When a user has 2FA turned on, he will be prompted safer methods first when authenticating. However, if the user has already chosen a preferred method in his dashboard, the prompt favors his choice In the user's dashboard enrolling options are presented following the defined order Widgets shown vary according to plugins installed. In a fresh installation, the following are supported out-of-the-box: OTP via SMS TOTP/HOTP: mobile OTP apps and hard tokens (cards, key fobs, dongles, etc.) FIDO devices Super Gluu for push notifications To add more authentication methods, please check the developer guide . Pass reset config # An admin can give users the ability to reset their password from inside Casa. To enable the password reset functionality, navigate to Pass reset config and click the toggle to ON . Reset to password authentication # If a user is locked out for any reason (e.g. lost device, etc.), an admin can navigate to Reset to password authentication in the admin console to turn 2FA off for them. Type the username (or part of) in the text field and then press search. Once the user has been located, click the checkbox and click the Reset to password button. The row will become disabled, and a success message will be displayed. Branding # Most organizations will want to custom brand Jans Casa. Follow our guide to learn more about custom branding Casa . Plugins # Through an easy-to-use screen, administrators can easily manage installed plugins and add new ones. Logging # Application logs are useful sources of information to diagnose anomalies and understand possible causes of errors if presented. Casa uses the Log4J2 logging framework for this. The severity level for logs can be modified at runtime and requires no restart. For more information about logging, check the FAQ entry . CORS domains # If a given plugin exposes one or more web services that are to be consumed from within a web browser, you can whitelist the origin domains from which consumption can takes place. 2FA settings # Warning This feature is only if the 2FA settings plugin is installed In the 2FA settings screen, an admin can: Specify the minimum number of credentials a user must enroll before 2FA can be turned on Determine whether 2FA should be automatically enabled upon credential enrollment Whether users can turn 2FA on and off their own Whether users can choose a preferred authentication method Choose from a few predefined policies for when 2FA should be prompted. To reduce the chance of lockouts, we recommend setting a minimum of two (2) strong credentials. Predefined 2FA policy options include: Enforce strong authentication for every login attempt Prompt for 2FA when users' location is unrecognized Prompt for 2FA when users' device is unrecognized Allow the user to set their own strong authentication policy The default policy is to enforce 2FA for every login attempt. If the admin opts to allow users to manager their own policy, a new widget will appear in the user-facing dashboard as described in the user guide . In addition, the plugin exposes an API to programmatically manipulate these settings.", "title": "Admin console"}, {"location": "casa/administration/admin-console/#admin-console", "text": "This document reviews the available options for configuring Casa. All configuration changes applied via the admin console take effect immediately with no restart or other actions required.", "title": "Admin Console"}, {"location": "casa/administration/admin-console/#authentication-methods", "text": "Here you can choose the type of 2FA credentials you want to support in Casa. Every authentication method is represented by a widget you can enable or disable. Administrators can arrange widgets according to perceived \"strength\" order, that is, methods considered safer than others can be placed on top of the list. This ordering has two practical consequences: When a user has 2FA turned on, he will be prompted safer methods first when authenticating. However, if the user has already chosen a preferred method in his dashboard, the prompt favors his choice In the user's dashboard enrolling options are presented following the defined order Widgets shown vary according to plugins installed. In a fresh installation, the following are supported out-of-the-box: OTP via SMS TOTP/HOTP: mobile OTP apps and hard tokens (cards, key fobs, dongles, etc.) FIDO devices Super Gluu for push notifications To add more authentication methods, please check the developer guide .", "title": "Authentication methods"}, {"location": "casa/administration/admin-console/#pass-reset-config", "text": "An admin can give users the ability to reset their password from inside Casa. To enable the password reset functionality, navigate to Pass reset config and click the toggle to ON .", "title": "Pass reset config"}, {"location": "casa/administration/admin-console/#reset-to-password-authentication", "text": "If a user is locked out for any reason (e.g. lost device, etc.), an admin can navigate to Reset to password authentication in the admin console to turn 2FA off for them. Type the username (or part of) in the text field and then press search. Once the user has been located, click the checkbox and click the Reset to password button. The row will become disabled, and a success message will be displayed.", "title": "Reset to password authentication"}, {"location": "casa/administration/admin-console/#branding", "text": "Most organizations will want to custom brand Jans Casa. Follow our guide to learn more about custom branding Casa .", "title": "Branding"}, {"location": "casa/administration/admin-console/#plugins", "text": "Through an easy-to-use screen, administrators can easily manage installed plugins and add new ones.", "title": "Plugins"}, {"location": "casa/administration/admin-console/#logging", "text": "Application logs are useful sources of information to diagnose anomalies and understand possible causes of errors if presented. Casa uses the Log4J2 logging framework for this. The severity level for logs can be modified at runtime and requires no restart. For more information about logging, check the FAQ entry .", "title": "Logging"}, {"location": "casa/administration/admin-console/#cors-domains", "text": "If a given plugin exposes one or more web services that are to be consumed from within a web browser, you can whitelist the origin domains from which consumption can takes place.", "title": "CORS domains"}, {"location": "casa/administration/admin-console/#2fa-settings", "text": "Warning This feature is only if the 2FA settings plugin is installed In the 2FA settings screen, an admin can: Specify the minimum number of credentials a user must enroll before 2FA can be turned on Determine whether 2FA should be automatically enabled upon credential enrollment Whether users can turn 2FA on and off their own Whether users can choose a preferred authentication method Choose from a few predefined policies for when 2FA should be prompted. To reduce the chance of lockouts, we recommend setting a minimum of two (2) strong credentials. Predefined 2FA policy options include: Enforce strong authentication for every login attempt Prompt for 2FA when users' location is unrecognized Prompt for 2FA when users' device is unrecognized Allow the user to set their own strong authentication policy The default policy is to enforce 2FA for every login attempt. If the admin opts to allow users to manager their own policy, a new widget will appear in the user-facing dashboard as described in the user guide . In addition, the plugin exposes an API to programmatically manipulate these settings.", "title": "2FA settings"}, {"location": "casa/administration/change-context-path/", "tags": ["Casa", "administration", "context path"], "text": "Change Application Context Path # To publish the application at a location other than /casa , do the following: Log into Janssen Server using SSH Edit tag <Set name=\"contextPath\"> in file /opt/jans/jetty/jans-casa/webapps/jans-casa.xml with the new path you want to use. For example, if you chose /creds , you would do the following: <Set name=\"contextPath\">/creds</Set> Edit tag <Set name=\"contextPath\"> in file /opt/jans/jetty/jans-casa/webapps/jans-casa_web_resources.xml appropriately with the new path you want to use. Adjust Apache's .conf file: Locate the https_jans.conf file. The exact location will vary depending on your distribution. In Ubuntu, for example, you can find it at /etc/apache2/sites-available Find the section starting with <Location /casa> and replace the 2 occurrences of casa with the path of your choice. Do not use trailing slashes Add the following directive: Redirect /casa /<new-context-path> before all <Location> and <Proxy> sections Adjust custom script settings: adjust the \"supergluu_app_id\" property of the casa custom script accordingly Wait for around 1 minute (so the server picks the script changes), then restart Casa and Apache services. Use this page as a guide The application should be accessible now at the new URL.", "title": "URL path customization"}, {"location": "casa/administration/change-context-path/#change-application-context-path", "text": "To publish the application at a location other than /casa , do the following: Log into Janssen Server using SSH Edit tag <Set name=\"contextPath\"> in file /opt/jans/jetty/jans-casa/webapps/jans-casa.xml with the new path you want to use. For example, if you chose /creds , you would do the following: <Set name=\"contextPath\">/creds</Set> Edit tag <Set name=\"contextPath\"> in file /opt/jans/jetty/jans-casa/webapps/jans-casa_web_resources.xml appropriately with the new path you want to use. Adjust Apache's .conf file: Locate the https_jans.conf file. The exact location will vary depending on your distribution. In Ubuntu, for example, you can find it at /etc/apache2/sites-available Find the section starting with <Location /casa> and replace the 2 occurrences of casa with the path of your choice. Do not use trailing slashes Add the following directive: Redirect /casa /<new-context-path> before all <Location> and <Proxy> sections Adjust custom script settings: adjust the \"supergluu_app_id\" property of the casa custom script accordingly Wait for around 1 minute (so the server picks the script changes), then restart Casa and Apache services. Use this page as a guide The application should be accessible now at the new URL.", "title": "Change Application Context Path"}, {"location": "casa/administration/custom-branding/", "tags": ["Casa", "administration", "custom branding", "brand"], "text": "Custom branding # In Casa, administrators can supply their own logo and favicon to better match the organization's look and feel. If you want to apply more advanced customizations, adding the custom branding plugin is the way to go. Note This page covers customizations available through the custom branding plugin . It is assumed you have already added it to your Casa installation. The plugin allows administrators to easily alter the appearance of Casa. There are two ways to tweak the design: a quick point-and-click set of changes that you can preview immediately, or a lower-level approach that allows you to supply your own CSS file and images (this is known as external assets directory usage). Quick design customization # Click on Custom branding in the admin console, and choose Upload images and pick colors . With this branding alternative, you can apply some visual changes effortlessly with zero CSS coding. You can: Supply your company logo and favicon Choose the background color for the page header Choose button colors Edit the footer text Once you supply your files, color values, and footer text, click on Save and see the changes take immediately by navigating to a different page or opening a new browser tab. Repeat the process till you get the combination that best matches your organization's look and feel. With \"Primary buttons\" we refer to the vast majority of buttons that trigger some action such as saving, updating or accepting - whether in the user pages or the admin UI itself. \"Cancel\" covers undo, close or cancel, while \"Misc\" is for anything not fitting any of the previous usages. You can choose \"Use defaults\" if you feel comfortable with the Bootstrap-like colors offered in Jans Casa. Using the external assets directory # Note Intermediate-level knowledge of CSS is required for this task. Background # Casa's UI design is driven by one CSS stylesheet and a few images. Specifically, Casa leverages the following UI frameworks: ZK Tachyons 4.11 Font Awesome 5.12 Particularly, ZK's default theme CSS file was disabled to offer a higher degree of flexibility in design. This enables Tachyons to claim control over style rules applied to HTML markup. External assets directory # In the /opt/jans/jetty/casa/static folder, you can place your own version of the main stylesheet and images Casa uses. No other stylesheet should be overriden. To start, log in to the Janssen Server and do the following: cd /opt/jans/jetty/jans-casa/static jar -xf ../webapps/jans-casa.war images styles/gluu/style.css This will copy the files you can edit later (these are the original versions provided out of the box in Casa). If you place additional files in this directory, ensure ownership is set to recursive. For instance, you can: $ chown -R jetty:jetty /opt/jans/jetty/jans-casa/static/ Enable and apply your customizations # In the admin console, navigate to Custom branding > Use Casa external assets directory . From that point on, your installation is reading relevant files from the static directory. Note In CSS, the rules' order of appearance is important. For all Casa pages, style.css is loaded first, then tachyons.css. This means rules for Tachyons have higher priority unless !important is used. The main stylesheet ( style.css ) is located at /opt/jans/jetty/jans-casa/static/styles/gluu if you have followed the instructions above. Here are some tips for applying your customizations: Get acquainted with functional CSS. This is the approach followed in Casa. Here , here , and here you can find useful introductory material. Inspect the DOM tree generated for application pages and determine the CSS selectors you need to edit or things you have to add in order to alter the appearance. Use your web browser's facilities to inspect web page composition: this is usually part of any browser's developer toolbar. Moreover, they allow you to change styles on the fly so you can play a lot before applying the real changes. Don't override rules that are already defined in Tachyons. Conversely, ZK rules (which are prefixed with z- ) are safe to be re-defined since ZK CSS isn't included. In most circumstances, your work will come down to editing existing rules in style.css . HTML markup will show rules (in the class attribute) prefixed with cust- that are apparently not defined anywhere. These rules are intended to give admins the opportunity to add their design tastes. The following is a list of custom selectors you can add to style.css . Names are in general self-explanatory, the images below help clarify more. cust-menu-item cust-content-heading cust-sections-wrapper cust-section cust-panel cust-modal-window cust-edit-button cust-link-button cust-delete-button cust-primary-button cust-cancel-button cust-misc-button cust-text-input cust-progress-bar Viewing your changes # There is no need to restart the application for the changes to take effect. However, most static files are cached by browsers, so you will need to open a fresh private browsing (incognito) session. If you tried the above and still don't see changes, try hitting the resource URL directly in a new browser tab. For example, to load the style.css file in your browser, visit https://<host-name>/casa/custom/styles/gluu/style.css . That way, you can determine if your changes are there. Reverting to Default Theme # If for any reason you wish to restore the default theme, select \"Use default (Gluu Inc.) theme\" in the admin dashboard. Examples # Here are solutions for common use cases: Use a different logo # Just replace images/logo.png (relative to the static directory) with your own image. Use a Different Favicon # Replace images/favicon.ico with your own image. Change the Font Used in Text # The vast majority of text that appears in the application uses the same font. To set the default font, locate at the bottom of style.css a declaration like @import url('https://fonts.googleapis.com... and point to one of your choosing. Check out this page to learn more about Google fonts. Then, scroll down and modify the html and body selectors appropriately with the font you picked. If you want to use your own fonts instead of Google's, you can use @font-face for this purpose. Copy your ttf , woff , svg or eot files somewhere in the static directory and link them appropriately. To use the more classical fonts like \"Helvetica\", \"Arial\", etc., simply update html and body selectors passing the font-family name.", "title": "Custom branding"}, {"location": "casa/administration/custom-branding/#custom-branding", "text": "In Casa, administrators can supply their own logo and favicon to better match the organization's look and feel. If you want to apply more advanced customizations, adding the custom branding plugin is the way to go. Note This page covers customizations available through the custom branding plugin . It is assumed you have already added it to your Casa installation. The plugin allows administrators to easily alter the appearance of Casa. There are two ways to tweak the design: a quick point-and-click set of changes that you can preview immediately, or a lower-level approach that allows you to supply your own CSS file and images (this is known as external assets directory usage).", "title": "Custom branding"}, {"location": "casa/administration/custom-branding/#quick-design-customization", "text": "Click on Custom branding in the admin console, and choose Upload images and pick colors . With this branding alternative, you can apply some visual changes effortlessly with zero CSS coding. You can: Supply your company logo and favicon Choose the background color for the page header Choose button colors Edit the footer text Once you supply your files, color values, and footer text, click on Save and see the changes take immediately by navigating to a different page or opening a new browser tab. Repeat the process till you get the combination that best matches your organization's look and feel. With \"Primary buttons\" we refer to the vast majority of buttons that trigger some action such as saving, updating or accepting - whether in the user pages or the admin UI itself. \"Cancel\" covers undo, close or cancel, while \"Misc\" is for anything not fitting any of the previous usages. You can choose \"Use defaults\" if you feel comfortable with the Bootstrap-like colors offered in Jans Casa.", "title": "Quick design customization"}, {"location": "casa/administration/custom-branding/#using-the-external-assets-directory", "text": "Note Intermediate-level knowledge of CSS is required for this task.", "title": "Using the external assets directory"}, {"location": "casa/administration/custom-branding/#background", "text": "Casa's UI design is driven by one CSS stylesheet and a few images. Specifically, Casa leverages the following UI frameworks: ZK Tachyons 4.11 Font Awesome 5.12 Particularly, ZK's default theme CSS file was disabled to offer a higher degree of flexibility in design. This enables Tachyons to claim control over style rules applied to HTML markup.", "title": "Background"}, {"location": "casa/administration/custom-branding/#external-assets-directory", "text": "In the /opt/jans/jetty/casa/static folder, you can place your own version of the main stylesheet and images Casa uses. No other stylesheet should be overriden. To start, log in to the Janssen Server and do the following: cd /opt/jans/jetty/jans-casa/static jar -xf ../webapps/jans-casa.war images styles/gluu/style.css This will copy the files you can edit later (these are the original versions provided out of the box in Casa). If you place additional files in this directory, ensure ownership is set to recursive. For instance, you can: $ chown -R jetty:jetty /opt/jans/jetty/jans-casa/static/", "title": "External assets directory"}, {"location": "casa/administration/custom-branding/#enable-and-apply-your-customizations", "text": "In the admin console, navigate to Custom branding > Use Casa external assets directory . From that point on, your installation is reading relevant files from the static directory. Note In CSS, the rules' order of appearance is important. For all Casa pages, style.css is loaded first, then tachyons.css. This means rules for Tachyons have higher priority unless !important is used. The main stylesheet ( style.css ) is located at /opt/jans/jetty/jans-casa/static/styles/gluu if you have followed the instructions above. Here are some tips for applying your customizations: Get acquainted with functional CSS. This is the approach followed in Casa. Here , here , and here you can find useful introductory material. Inspect the DOM tree generated for application pages and determine the CSS selectors you need to edit or things you have to add in order to alter the appearance. Use your web browser's facilities to inspect web page composition: this is usually part of any browser's developer toolbar. Moreover, they allow you to change styles on the fly so you can play a lot before applying the real changes. Don't override rules that are already defined in Tachyons. Conversely, ZK rules (which are prefixed with z- ) are safe to be re-defined since ZK CSS isn't included. In most circumstances, your work will come down to editing existing rules in style.css . HTML markup will show rules (in the class attribute) prefixed with cust- that are apparently not defined anywhere. These rules are intended to give admins the opportunity to add their design tastes. The following is a list of custom selectors you can add to style.css . Names are in general self-explanatory, the images below help clarify more. cust-menu-item cust-content-heading cust-sections-wrapper cust-section cust-panel cust-modal-window cust-edit-button cust-link-button cust-delete-button cust-primary-button cust-cancel-button cust-misc-button cust-text-input cust-progress-bar", "title": "Enable and apply your customizations"}, {"location": "casa/administration/custom-branding/#viewing-your-changes", "text": "There is no need to restart the application for the changes to take effect. However, most static files are cached by browsers, so you will need to open a fresh private browsing (incognito) session. If you tried the above and still don't see changes, try hitting the resource URL directly in a new browser tab. For example, to load the style.css file in your browser, visit https://<host-name>/casa/custom/styles/gluu/style.css . That way, you can determine if your changes are there.", "title": "Viewing your changes"}, {"location": "casa/administration/custom-branding/#reverting-to-default-theme", "text": "If for any reason you wish to restore the default theme, select \"Use default (Gluu Inc.) theme\" in the admin dashboard.", "title": "Reverting to Default Theme"}, {"location": "casa/administration/custom-branding/#examples", "text": "Here are solutions for common use cases:", "title": "Examples"}, {"location": "casa/administration/custom-branding/#use-a-different-logo", "text": "Just replace images/logo.png (relative to the static directory) with your own image.", "title": "Use a different logo"}, {"location": "casa/administration/custom-branding/#use-a-different-favicon", "text": "Replace images/favicon.ico with your own image.", "title": "Use a Different Favicon"}, {"location": "casa/administration/custom-branding/#change-the-font-used-in-text", "text": "The vast majority of text that appears in the application uses the same font. To set the default font, locate at the bottom of style.css a declaration like @import url('https://fonts.googleapis.com... and point to one of your choosing. Check out this page to learn more about Google fonts. Then, scroll down and modify the html and body selectors appropriately with the font you picked. If you want to use your own fonts instead of Google's, you can use @font-face for this purpose. Copy your ttf , woff , svg or eot files somewhere in the static directory and link them appropriately. To use the more classical fonts like \"Helvetica\", \"Arial\", etc., simply update html and body selectors passing the font-family name.", "title": "Change the Font Used in Text"}, {"location": "casa/administration/faq/", "tags": ["Casa", "administration", "faq"], "text": "Frequently Asked Questions # Common administrative tasks # Where are the logs? # The application logs are located at /opt/jans/jetty/jans-casa/logs . By default, Casa uses the INFO level for messages. You can change the log level at will using the app's admin UI. How do I custom brand Casa? # We have a dedicated page covering the topic of custom branding here . What ports are used by the application? # Casa uses port 8080 . One way to see if the app is up and running is by checking whether this port is open by issuing a command like netstat -nltp . How to turn 2FA off for a user? # If a user has been locked out for any reason (e.g. lost devices), you can reset his \"authentication method\" to password by accessing the admin console and choosing the menu item labelled \"Reset users preference\". Type the username (or part of) in the text field and then press search. Once you locate the user in the result grid, click the corresponding row and then hit \"Change to password\". The row will become disabled, and you'll see a success message. If you've followed the steps as described above, next time he attempts to log in, he won't be asked to present any credentials other than password to enter. How to adjust the issuer for OTP tokens # When people add OTP mobile apps, the enrollment appears in the device associated with an \"issuer\", so it is easy to recognize where the OTPs generated can be used. To keep track of which OTPs are valid for which IDPs, the issuer property can be adjusted in flow io.jans.casa.authn.otp part of Casa Agama project - you can use TUI for this purpose. For example, you might want to set the issuer property to ACME Dev on your dev server, and ACME, Inc. on your production server. Errors shown in the UI # A page with a \"Service Temporarily Unavailable\" message appears when accessing the application # This is the 503 HTTP error. There is an Apache server in front of the application and this means the reverse proxy couldn't establish a communication internally with the app. This usually happens when Casa hasn't started completely, so it's usually a matter of waiting a few seconds. An \"Unauthorized access\" error is shown when accessing the application # This is caused by an unauthorized access attempt (e.g. users requesting URLs without ever logging in or after session has expired). \"An error occurred: Casa did not start properly\" is shown when accessing the application # This occurs whenever the application failed to start successfully. Check the log to diagnose the problem. Try to find a message like \"WEBAPP INITIALIZATION FAILED\" and see the traces above it. Often, error messages are self-explanatory. Once fixed, please restart the application. You will have to see a \"WEBAPP INITIALIZED SUCCESSFULLY\" message to know that it's working. Miscellanenous # Admin console is not shown # If you have logged in using an administrative account and cannot find any admin features in the UI ensure you have gone through these steps . A previously enabled method is not available anymore # Check if the plugin that contributed the given authentication method was removed. The out-of-the-box methods will always appear listed. What kind of TOTP/HOTP devices are supported? # Both soft (mobile apps) or hard tokens (keyfobs, cards, etc.) are supported. Supported algorithms are HmacSHA1 , HmacSHA256 , and HmacSHA512 . Authentication fails when using TOTP or HOTP with no apparent reason # For Time-based OTP, ensure the time of your server is correctly synchronized (use NTP for instance). The time lag of the authentication device used (for instance, a mobile phone) with respect to server time should not be representative. Big time differences can cause unsuccessful attempts to enroll TOTP credentials in Casa. For Event-based OTP (HOTP), ensure you are using a suitable value for look ahead window (we suggest at least 10). Check the configuration of flow io.jans.casa.authn.otp part of Casa Agama project - you can use TUI for this purpose. The user interface is not showing any means to enroll credentials # In the administration console, ensure one or more authentication methods have been enabled. A user cannot turn 2FA on # To turn 2FA on, the user has to have enrolled at least a certain number of credentials through the app. Only after this is met, he will be able to perform this action. In the administration console you can specify the minimum number of enrolled credentials needed to enable second factor authentication for users. Please check the 2FA Settings plugin for more details. My problem is not listed here # Feel free to ask Janssen Server community .", "title": "FAQ"}, {"location": "casa/administration/faq/#frequently-asked-questions", "text": "", "title": "Frequently Asked Questions"}, {"location": "casa/administration/faq/#common-administrative-tasks", "text": "", "title": "Common administrative tasks"}, {"location": "casa/administration/faq/#where-are-the-logs", "text": "The application logs are located at /opt/jans/jetty/jans-casa/logs . By default, Casa uses the INFO level for messages. You can change the log level at will using the app's admin UI.", "title": "Where are the logs?"}, {"location": "casa/administration/faq/#how-do-i-custom-brand-casa", "text": "We have a dedicated page covering the topic of custom branding here .", "title": "How do I custom brand Casa?"}, {"location": "casa/administration/faq/#what-ports-are-used-by-the-application", "text": "Casa uses port 8080 . One way to see if the app is up and running is by checking whether this port is open by issuing a command like netstat -nltp .", "title": "What ports are used by the application?"}, {"location": "casa/administration/faq/#how-to-turn-2fa-off-for-a-user", "text": "If a user has been locked out for any reason (e.g. lost devices), you can reset his \"authentication method\" to password by accessing the admin console and choosing the menu item labelled \"Reset users preference\". Type the username (or part of) in the text field and then press search. Once you locate the user in the result grid, click the corresponding row and then hit \"Change to password\". The row will become disabled, and you'll see a success message. If you've followed the steps as described above, next time he attempts to log in, he won't be asked to present any credentials other than password to enter.", "title": "How to turn 2FA off for a user?"}, {"location": "casa/administration/faq/#how-to-adjust-the-issuer-for-otp-tokens", "text": "When people add OTP mobile apps, the enrollment appears in the device associated with an \"issuer\", so it is easy to recognize where the OTPs generated can be used. To keep track of which OTPs are valid for which IDPs, the issuer property can be adjusted in flow io.jans.casa.authn.otp part of Casa Agama project - you can use TUI for this purpose. For example, you might want to set the issuer property to ACME Dev on your dev server, and ACME, Inc. on your production server.", "title": "How to adjust the issuer for OTP tokens"}, {"location": "casa/administration/faq/#errors-shown-in-the-ui", "text": "", "title": "Errors shown in the UI"}, {"location": "casa/administration/faq/#a-page-with-a-service-temporarily-unavailable-message-appears-when-accessing-the-application", "text": "This is the 503 HTTP error. There is an Apache server in front of the application and this means the reverse proxy couldn't establish a communication internally with the app. This usually happens when Casa hasn't started completely, so it's usually a matter of waiting a few seconds.", "title": "A page with a \"Service Temporarily Unavailable\" message appears when accessing the application"}, {"location": "casa/administration/faq/#an-unauthorized-access-error-is-shown-when-accessing-the-application", "text": "This is caused by an unauthorized access attempt (e.g. users requesting URLs without ever logging in or after session has expired).", "title": "An \"Unauthorized access\" error is shown when accessing the application"}, {"location": "casa/administration/faq/#an-error-occurred-casa-did-not-start-properly-is-shown-when-accessing-the-application", "text": "This occurs whenever the application failed to start successfully. Check the log to diagnose the problem. Try to find a message like \"WEBAPP INITIALIZATION FAILED\" and see the traces above it. Often, error messages are self-explanatory. Once fixed, please restart the application. You will have to see a \"WEBAPP INITIALIZED SUCCESSFULLY\" message to know that it's working.", "title": "\"An error occurred: Casa did not start properly\" is shown when accessing the application"}, {"location": "casa/administration/faq/#miscellanenous", "text": "", "title": "Miscellanenous"}, {"location": "casa/administration/faq/#admin-console-is-not-shown", "text": "If you have logged in using an administrative account and cannot find any admin features in the UI ensure you have gone through these steps .", "title": "Admin console is not shown"}, {"location": "casa/administration/faq/#a-previously-enabled-method-is-not-available-anymore", "text": "Check if the plugin that contributed the given authentication method was removed. The out-of-the-box methods will always appear listed.", "title": "A previously enabled method is not available anymore"}, {"location": "casa/administration/faq/#what-kind-of-totphotp-devices-are-supported", "text": "Both soft (mobile apps) or hard tokens (keyfobs, cards, etc.) are supported. Supported algorithms are HmacSHA1 , HmacSHA256 , and HmacSHA512 .", "title": "What kind of TOTP/HOTP devices are supported?"}, {"location": "casa/administration/faq/#authentication-fails-when-using-totp-or-hotp-with-no-apparent-reason", "text": "For Time-based OTP, ensure the time of your server is correctly synchronized (use NTP for instance). The time lag of the authentication device used (for instance, a mobile phone) with respect to server time should not be representative. Big time differences can cause unsuccessful attempts to enroll TOTP credentials in Casa. For Event-based OTP (HOTP), ensure you are using a suitable value for look ahead window (we suggest at least 10). Check the configuration of flow io.jans.casa.authn.otp part of Casa Agama project - you can use TUI for this purpose.", "title": "Authentication fails when using TOTP or HOTP with no apparent reason"}, {"location": "casa/administration/faq/#the-user-interface-is-not-showing-any-means-to-enroll-credentials", "text": "In the administration console, ensure one or more authentication methods have been enabled.", "title": "The user interface is not showing any means to enroll credentials"}, {"location": "casa/administration/faq/#a-user-cannot-turn-2fa-on", "text": "To turn 2FA on, the user has to have enrolled at least a certain number of credentials through the app. Only after this is met, he will be able to perform this action. In the administration console you can specify the minimum number of enrolled credentials needed to enable second factor authentication for users. Please check the 2FA Settings plugin for more details.", "title": "A user cannot turn 2FA on"}, {"location": "casa/administration/faq/#my-problem-is-not-listed-here", "text": "Feel free to ask Janssen Server community .", "title": "My problem is not listed here"}, {"location": "casa/administration/localization/", "tags": ["Casa", "administration", "localization"], "text": "Casa localization # Casa supports multilingual support through resource bundles. Administrators supply bundles as plaintext files ending with the .properties file extension. By default, Casa contains three bundles, each in a separate file. These bundles contain the internationalization labels in the English language, as displayed in a default Casa installation. For example, to add support for French, you would have to create the following files: File Description user_fr.properties Contains labels mostly found in user-facing pages admin_fr.properties Contains labels mostly found in administrator-facing pages general_fr.properties Contains labels found widely across the app and plugins Adding internationalization labels # To supply labels in a particular language (or even if you want to override the English translation provided), do the following: Log in to the Janssen Server using SSH Extract the Casa default labels: /opt/jre/bin/jar -xf /opt/jans/jetty/jans-casa/webapps/casa.war WEB-INF/classes/labels Run cp WEB-INF/classes/labels/*.properties . and delete WEB-INF dir: rm -R WEB-INF/ Add the appropriate suffix to the properties files found in the current directory, ie. _de for German, _es for Spanish, _ja for Japanese, etc. Edit the contents of files accordingly. Use UTF-8 encoding for opening and saving cd to /opt/jans/jetty/jans-casa/static Create directory i18n if it does not exist: mkdir i18n Transfer the properties files to the i18n folder Ensure jetty user has permission for reading the files Restart casa Log in to the application and review your work. Make necessary edits and repeat the process. How are labels picked? # In Casa, the rule for displaying contents is leveraged from the underlying framework . In short, the locale to use per session is picked based on the end-user browser settings. As an example, if the browser was configured to use U.S. English, the locale will be en_US . This means that files ending in _en_US.properties will be considered first. Then, the country suffix is removed and thus _en.properties is looked up. Finally the non-suffixed ones are considered, that is, the default label files bundled with Casa. Additionally, end users can pick the language of their preference by selecting a language item from the dropdown list appearing at the bottom of any Casa page. The list is only shown if there are two or more languages available to display. Localization in plugins # Plugins also support localization through the \"zk-label\" bundle. If you have installed plugins developed by Gluu, they will only contain a single default English file. To add your own translation for plugin texts, proceed as follows: cd to the folder where you stored the jar file of the plugin of interest. Extract the plugin's default labels (requires Java bin on your path): jar -xf JAR_FILE labels/zk-label.properties cd to labels folder Add the appropriate suffix to the properties file, ie. _de for German, _es for Spanish, _ja for Japanese, etc. Edit the contents accordingly. Use UTF-8 encoding for opening and saving Connect to your Janssen Server using SSH cd to /opt/jans/jetty/jans-casa/static Create directory i18n if it does not exist: mkdir i18n Transfer the properties file to the i18n folder Ensure jetty user has permission for reading Restart casa Note If your plugins have a zk-label.properties , you can accumulate all plugin texts into a single file, or you can use a different filename for each plugin. Properties file syntax # Administrators acquainted with the format used for properties files in Java will find Casa resource bundle files familiar. The format used in Casa differs slightly, but it is more powerful. To learn more about this topic, visit this page . Tips # Not all entries present in default label files have to be translated in your own localized versions. If you are comfortable with the current text for a particular entry, you can simply remove it to use the one in the default files. There is no need to supply specific translations for countries. While supported, most of time it suffices to create files suffixed with the language code, for instance _es , and not with country code (e.g _es_CO , _es_AR , _es_EC , _es_ES , etc.) Actual filenames for properties files are not relevant. Upon start, Casa will parse all properties files present in i18n folder.", "title": "Localization"}, {"location": "casa/administration/localization/#casa-localization", "text": "Casa supports multilingual support through resource bundles. Administrators supply bundles as plaintext files ending with the .properties file extension. By default, Casa contains three bundles, each in a separate file. These bundles contain the internationalization labels in the English language, as displayed in a default Casa installation. For example, to add support for French, you would have to create the following files: File Description user_fr.properties Contains labels mostly found in user-facing pages admin_fr.properties Contains labels mostly found in administrator-facing pages general_fr.properties Contains labels found widely across the app and plugins", "title": "Casa localization"}, {"location": "casa/administration/localization/#adding-internationalization-labels", "text": "To supply labels in a particular language (or even if you want to override the English translation provided), do the following: Log in to the Janssen Server using SSH Extract the Casa default labels: /opt/jre/bin/jar -xf /opt/jans/jetty/jans-casa/webapps/casa.war WEB-INF/classes/labels Run cp WEB-INF/classes/labels/*.properties . and delete WEB-INF dir: rm -R WEB-INF/ Add the appropriate suffix to the properties files found in the current directory, ie. _de for German, _es for Spanish, _ja for Japanese, etc. Edit the contents of files accordingly. Use UTF-8 encoding for opening and saving cd to /opt/jans/jetty/jans-casa/static Create directory i18n if it does not exist: mkdir i18n Transfer the properties files to the i18n folder Ensure jetty user has permission for reading the files Restart casa Log in to the application and review your work. Make necessary edits and repeat the process.", "title": "Adding internationalization labels"}, {"location": "casa/administration/localization/#how-are-labels-picked", "text": "In Casa, the rule for displaying contents is leveraged from the underlying framework . In short, the locale to use per session is picked based on the end-user browser settings. As an example, if the browser was configured to use U.S. English, the locale will be en_US . This means that files ending in _en_US.properties will be considered first. Then, the country suffix is removed and thus _en.properties is looked up. Finally the non-suffixed ones are considered, that is, the default label files bundled with Casa. Additionally, end users can pick the language of their preference by selecting a language item from the dropdown list appearing at the bottom of any Casa page. The list is only shown if there are two or more languages available to display.", "title": "How are labels picked?"}, {"location": "casa/administration/localization/#localization-in-plugins", "text": "Plugins also support localization through the \"zk-label\" bundle. If you have installed plugins developed by Gluu, they will only contain a single default English file. To add your own translation for plugin texts, proceed as follows: cd to the folder where you stored the jar file of the plugin of interest. Extract the plugin's default labels (requires Java bin on your path): jar -xf JAR_FILE labels/zk-label.properties cd to labels folder Add the appropriate suffix to the properties file, ie. _de for German, _es for Spanish, _ja for Japanese, etc. Edit the contents accordingly. Use UTF-8 encoding for opening and saving Connect to your Janssen Server using SSH cd to /opt/jans/jetty/jans-casa/static Create directory i18n if it does not exist: mkdir i18n Transfer the properties file to the i18n folder Ensure jetty user has permission for reading Restart casa Note If your plugins have a zk-label.properties , you can accumulate all plugin texts into a single file, or you can use a different filename for each plugin.", "title": "Localization in plugins"}, {"location": "casa/administration/localization/#properties-file-syntax", "text": "Administrators acquainted with the format used for properties files in Java will find Casa resource bundle files familiar. The format used in Casa differs slightly, but it is more powerful. To learn more about this topic, visit this page .", "title": "Properties file syntax"}, {"location": "casa/administration/localization/#tips", "text": "Not all entries present in default label files have to be translated in your own localized versions. If you are comfortable with the current text for a particular entry, you can simply remove it to use the one in the default files. There is no need to supply specific translations for countries. While supported, most of time it suffices to create files suffixed with the language code, for instance _es , and not with country code (e.g _es_CO , _es_AR , _es_EC , _es_ES , etc.) Actual filenames for properties files are not relevant. Upon start, Casa will parse all properties files present in i18n folder.", "title": "Tips"}, {"location": "casa/administration/quick-start/", "tags": ["Casa", "quick start"], "text": "Jans Casa Quick Start Guide # Note This document is intended for administrators only. Learn here how to \"grant\" administrative privileges for Casa. Use this guide to install and configure your Casa deployment. Installation # Jans Casa can be used with Janssen Server or Gluu Flex Server . At installation time (applies to any of these two products), you will be prompted if you desire to include Casa. If you want to add Casa post-installation, you will simply have to re-run the installer and ensure to select Casa. Configuration # Enable authentication methods # The \"out-of-the-box\" login experience in Casa consists of the usual username and password prompt. To start leveraging a stronger authentication login to Casa with an administrative account (visit https://<your-server-name>/jans-casa ) and activate the methods you want to offer Casa users. Important notes : Usage of OTP via SMS requires the setup of a Twilio account and populating configuration properties of flow io.jans.casa.authn.twilio_sms found in Casa Agama project. You can do the latter via TUI . We encourage you to use the online Twilio testing tools beforehand to ensure you can send SMS to the countries you are targetting Usage of Super Gluu has some preliminar requisites described here Add the strong authentication settings plugin # This step is optional. Check this page for more information. Use this plugin if you need to exercise an advanced control on how 2FA behaves in your Casa deployment. Test enrollment and 2FA # Do the following steps using a testing account with no administrative privileges: Login to Casa. Only username and password should be prompted Use the menu on the left to access the screens from which enrollment of credentials can be performed Ensure at least two credentials have been added. In the home page, turn on 2FA Log off and log back in. From now on, besides username and password, one credential has to be presented to get access Click here to learn more about 2FA in Casa. Finish configuration # Once you are done with testing, you may use casa as the default authentication method of Janssen Server using TUI to log in users via Casa for all applications the server protects. Finally, as a security measure you can thoroughly disable access to the administrative console of Casa by following the steps below: Connect to your server Navigate to /opt/jans/jetty/jans-casa remove file .administrable (ie. rm .administrable ) If you want to make the admin console available again you need to recreate the marker file: Create an empty file (eg. touch .administrable ) Run chown casa:casa .administrable (do this only if you are on FIPS environment) Logout in case you have an open browser session, and login again Check out available plugins # Browse our catalog of plugins to add features and expand Casa!.", "title": "Quick Start"}, {"location": "casa/administration/quick-start/#jans-casa-quick-start-guide", "text": "Note This document is intended for administrators only. Learn here how to \"grant\" administrative privileges for Casa. Use this guide to install and configure your Casa deployment.", "title": "Jans Casa Quick Start Guide"}, {"location": "casa/administration/quick-start/#installation", "text": "Jans Casa can be used with Janssen Server or Gluu Flex Server . At installation time (applies to any of these two products), you will be prompted if you desire to include Casa. If you want to add Casa post-installation, you will simply have to re-run the installer and ensure to select Casa.", "title": "Installation"}, {"location": "casa/administration/quick-start/#configuration", "text": "", "title": "Configuration"}, {"location": "casa/administration/quick-start/#enable-authentication-methods", "text": "The \"out-of-the-box\" login experience in Casa consists of the usual username and password prompt. To start leveraging a stronger authentication login to Casa with an administrative account (visit https://<your-server-name>/jans-casa ) and activate the methods you want to offer Casa users. Important notes : Usage of OTP via SMS requires the setup of a Twilio account and populating configuration properties of flow io.jans.casa.authn.twilio_sms found in Casa Agama project. You can do the latter via TUI . We encourage you to use the online Twilio testing tools beforehand to ensure you can send SMS to the countries you are targetting Usage of Super Gluu has some preliminar requisites described here", "title": "Enable authentication methods"}, {"location": "casa/administration/quick-start/#add-the-strong-authentication-settings-plugin", "text": "This step is optional. Check this page for more information. Use this plugin if you need to exercise an advanced control on how 2FA behaves in your Casa deployment.", "title": "Add the strong authentication settings plugin"}, {"location": "casa/administration/quick-start/#test-enrollment-and-2fa", "text": "Do the following steps using a testing account with no administrative privileges: Login to Casa. Only username and password should be prompted Use the menu on the left to access the screens from which enrollment of credentials can be performed Ensure at least two credentials have been added. In the home page, turn on 2FA Log off and log back in. From now on, besides username and password, one credential has to be presented to get access Click here to learn more about 2FA in Casa.", "title": "Test enrollment and 2FA"}, {"location": "casa/administration/quick-start/#finish-configuration", "text": "Once you are done with testing, you may use casa as the default authentication method of Janssen Server using TUI to log in users via Casa for all applications the server protects. Finally, as a security measure you can thoroughly disable access to the administrative console of Casa by following the steps below: Connect to your server Navigate to /opt/jans/jetty/jans-casa remove file .administrable (ie. rm .administrable ) If you want to make the admin console available again you need to recreate the marker file: Create an empty file (eg. touch .administrable ) Run chown casa:casa .administrable (do this only if you are on FIPS environment) Logout in case you have an open browser session, and login again", "title": "Finish configuration"}, {"location": "casa/administration/quick-start/#check-out-available-plugins", "text": "Browse our catalog of plugins to add features and expand Casa!.", "title": "Check out available plugins"}, {"location": "casa/developer/add-authn-methods/", "tags": ["Casa", "developer guide"], "text": "Onboarding custom authentication methods # Out-of-the-box Casa supports some useful authentication methods for a secure, pleasant authentication experience. Adding more authentication mechanisms is possible and requires certain development effort. In this guide we summarize the steps required to do so and give you some useful pointers to start your coding journey. Supporting a new authentication mechanisms consists of two tasks: coding an Agama flow and creating a plugin that contributes an authentication method. The former has to do with the authentication flow the user experiences (to access Casa or other apps), while the latter with the credential enrollment process. Agama flow # Note Acquaintance with Agama framework and Agama project management is required About Casa authentication flow # Authentication in Casa is implemented through an Agama project called casa - in TUI you can see it listed in the Agama management screen. As a first step, the user is requested to enter the username and password combination, then depending on how the application is configured, personal user settings, and access policies defined, a second factor may be requested. The casa project allows to onboard new types of second factors (authentication mechanisms) and also provides a user experience that supports backtracking: if a user is asked to present a specific credential and that credential is not currently available or is not working, he can choose an alternative method for authentication where a different type of credential will be prompted. Users can backtrack several times. Flow requisites # To code the flow corresponding to the authentication method to add, you can use the Agama project found here as a canvas. Ensure the following conditions are met so that it properly integrates in the main Casa flow: The flow will be passed an Agama map containing information of the person attempting the authentication. This input parameter will contain at least three keys: uid , inum , and name . uid and inum map directly to attributes stored in the user's profile and are never empty, name is a displayable name which may come from attribute givenName or displayName . All values are strings . The flow should terminate with a true outcome if the user successfully passes the challenge, presents the expected credential, etc. In any other case, false must be returned and an optional error message can be included for the caller flow ( io.jans.casa.authn.main ) to show it in the screen. Any additional data attached in the Finish instruction will not be processed. If for some reason your flow crashes, the corresponding exception will be printed to the logs, the caller will continue running, and the browser taken to the selector page where an error message will be displayed. Note your project may contain more flows to serve as utilitarians or simply to break down the authentication flow into smaller, more manageable pieces. About templates # Regarding UI templates, it is recommended to re-use a couple of Freemarker macros available in the casa project. This will allow your flow's UI to have the same look-and-feel of flows bundled out-of-the box, like OTP and fido. Additionally this will allow to properly incorporate backtracking. Import the commons template in your UI page: <#import \"../kz1vc3/commons.ftlh\" as com> Copy the above line of code in the first line of your templates, preferably. Note you may need to add extra ../ fragments in the path to commons.ftlh depending on the directory level where your template resides inside the web subdirectory of your Agama project. Then call the main macro and supply your markup, like this: <@com.main> <!-- your markup here --> <@com.main> The above will generate a page incorporating the required CSS files and will render the header and footer appropriately while leaving your content in the center of the page. The casa project makes heavy use the Tachyons CSS. You may like to use those for building templates instead of incorporating yet another styling framework. It is highly recommended to include the following near the bottom of your markup (still inside the main call block): <@com.alternative /> This will render a form with a text and a link that will allow users to \"escape\" from your flow and take another route, i.e. to backtrack: Then, in your flow's code, you handle the escape this way: data = RRF \"mytemplate.ftlh\" ... When data.skipped is \"\" Finish false The above means your flow can finish with false not only if the authentication did not succeed but also when users wants to backtrack. The selector page # When backtracking, a selector page is shown where all available methods for the given user are displayed - sorted by strength. From here, the user can take another route to be challenged for an alternative credential. Every element in the list has an icon and descriptive text associated. These elements are configurable and for the case of adding an authentication method, both icon and text should be supplied. To do so, locate in TUI the casa Agama project. See how the flow io.jans.casa.authn.main has a selector section in its configurations. This is a dictionary (JSON object) where keys are qualified names of flows and values are dictionaries at the same time - this where you can provide the required info. For example, if your authentication method is backed by a flow com.acme.authn.food , the casa project configuration may look like { \"io.jans.casa.authn.main\": { \"selector\": { \"com.acme.authn.food\": { \"icon\": \"<i class='fas fa-pizza-slice'></i>\", \"text\": \"A sentence describing what the user is supposed to present in the next screen\" }, ... } }, ... } Alternatively, a pointer to a localized message can be used instead of text . This is the recommended practice if localization/internationalization is relevant. In this case, something like the below will work: ... \"com.acme.authn.food\": { \"icon\": \"<i class='fas fa-pizza-slice'></i>\", \"textKey\": \"foodAuth.methodTitle\" } ... as long as the message key foodAuth.methodTitle is defined in the project's labels.txt file, or elsewhere in another project. Note textKey takes precedence over text when rendering the page. Both icon and textKey (or text ) may contain HTML markup. In this example we are using the font awesome library available in the selector page for rendering a nice icon but we could have used any other thing here like an img tag, for instance. Ensure to properly escape double quotes if necessary. Also make the markup a one-liner: JSON strings cannot span several lines. Recommended practices # Note Ensure to go through this page before proceeding Config settings # Use a single place to store configuration settings for your authentication method. The most convenient place is in the Agama project itself. You may have configs associated to each flow in your project and they can be accessed directly in your flows code. Additionally, they can be easily read from your plugin's Java code this way: ips = io.jans.casa.misc.Utils.managedBean(IPersistenceService.class); JSONObject p = ips.getAgamaFlowConfigProperties(\"flow qname\"); Out-of-the-box methods in Casa employ this strategy. Also when you do this, every time a change in project configuration is detected, your Java code gets notified: a call to method reloadConfiguration of your extension is issued, see class SampleCredentialAuthnMethod in the sample credential plugin. Retries # Giving the user only one chance to pass an authentication challenge is unfair. Code your flow so users have a couple of opportunities to fail before finishing with false as outcome. Agama's Repeat directive helps you cover this case. Key questions # As you try to assemble your project, you will come up with some design decisions, for instance: How to model and store credentials associated to the authentication method? What kind of parameters are relevant for the authentication method? What's the algorithm for authenticating users once they have supplied a valid username/password combination? Depending on the answers, you may like to start instead with plugin development first. This is not always the case though, however, getting your hands on the plugin might help unclutter the path. Enrollment plugin # Coding a Casa plugin is mainly a Java development task. You can use the \"Sample credential\" plugin as a template to start the work. Ensure you have: A Jans Server installation that includes Jans Casa - prefer a VM environment over the CN edition for development purposes. Also, you'll need a way to connect to your server via SSH A copy of the Jans repository (a shallow clone of main branch is OK): https://github.com/JanssenProject/jans Plugin deployment # Start with deploying the plugin to get acquainted with the process: In the local development machine, cd to ./jans/jans-casa/plugins/samples/sample-cred Run mvn -Dmaven.test.skip package . This may take several minutes (lots of network requests). Once you get it done, the next time you can add the -o switch (offline mode) for faster results A target folder with a couple of jar files in it will be generated Access Casa admin console and in the plugins page, upload the file suffixed with jar-with-dependencies.jar . After one minute approximately, visit the \"Authentication methods\" page, check the \"Favorite color\" widget, and click on \"Save\". Then logout. Login again, this time with a non administrative account. In the landing page (user's dashboard), an item labeled \"Your favorite color\" will be shown on the left (under the \"2FA credentials\" heading). Also, a panel in the central area of the page will be added in accordance. Click on \"Your favorite color\" and you'll land a page to let Casa know what your favorite color is!. This color will be used as a second factor for authentication. Ensure you have enabled another method such as OTP so you can enroll an additional credential in order to be able to active 2FA for this account. Study the sample project # Now it's time for you to go through the project folder checking one file at a time. Most of files contain comments that explain the purpose of things. Ensure you make a deep inspection of file ./src/main/resources/assets/user/cred_details.zul . It contains the markup of the page you visited earlier. Make an excursion to interface AuthnMethod found in shared maven module. Note it brings a couple of default methods. Class SampleCredentialAuthnMethod implements this interface. Editing the project # Modifying the project may require you to edit files mainly with .java , .zul , or .properties extensions. Most Java classes used in this plugin can be found in: The repository you cloned earlier The ZK framework documentation Standard Java SE API docs You can remove the plugin and add it as many times as you like - no restarts are needed unless things go really weird. You can do so either via the admin console or by dropping/removing the file directly in the filesystem (the path is /opt/jans/jetty/jans-casa/plugins ). Page tweaks # If you alter a .zul file and then package and redeploy the plugin, you will most probably not see any change taking effect in the UI page. This is because the ZK framework caches the .zul pages by default for a very long period. To change this behavior do the following: Connect to your VM and cd to /opt/gluu/jetty/jans-casa/webapps Extract ZK descriptor: # jar -xf jans-casa.war WEB-INF/zk.xml Locate XML tag file-check-period and remove it including its surrounding parent desktop-config Save the file and patch the application war: # jar -uf jans-casa.war WEB-INF/zk.xml Restart casa (e.g. systemctl casa restart ) From now on, any template change will take effect after 5 seconds.", "title": "Adding authentication methods"}, {"location": "casa/developer/add-authn-methods/#onboarding-custom-authentication-methods", "text": "Out-of-the-box Casa supports some useful authentication methods for a secure, pleasant authentication experience. Adding more authentication mechanisms is possible and requires certain development effort. In this guide we summarize the steps required to do so and give you some useful pointers to start your coding journey. Supporting a new authentication mechanisms consists of two tasks: coding an Agama flow and creating a plugin that contributes an authentication method. The former has to do with the authentication flow the user experiences (to access Casa or other apps), while the latter with the credential enrollment process.", "title": "Onboarding custom authentication methods"}, {"location": "casa/developer/add-authn-methods/#agama-flow", "text": "Note Acquaintance with Agama framework and Agama project management is required", "title": "Agama flow"}, {"location": "casa/developer/add-authn-methods/#about-casa-authentication-flow", "text": "Authentication in Casa is implemented through an Agama project called casa - in TUI you can see it listed in the Agama management screen. As a first step, the user is requested to enter the username and password combination, then depending on how the application is configured, personal user settings, and access policies defined, a second factor may be requested. The casa project allows to onboard new types of second factors (authentication mechanisms) and also provides a user experience that supports backtracking: if a user is asked to present a specific credential and that credential is not currently available or is not working, he can choose an alternative method for authentication where a different type of credential will be prompted. Users can backtrack several times.", "title": "About Casa authentication flow"}, {"location": "casa/developer/add-authn-methods/#flow-requisites", "text": "To code the flow corresponding to the authentication method to add, you can use the Agama project found here as a canvas. Ensure the following conditions are met so that it properly integrates in the main Casa flow: The flow will be passed an Agama map containing information of the person attempting the authentication. This input parameter will contain at least three keys: uid , inum , and name . uid and inum map directly to attributes stored in the user's profile and are never empty, name is a displayable name which may come from attribute givenName or displayName . All values are strings . The flow should terminate with a true outcome if the user successfully passes the challenge, presents the expected credential, etc. In any other case, false must be returned and an optional error message can be included for the caller flow ( io.jans.casa.authn.main ) to show it in the screen. Any additional data attached in the Finish instruction will not be processed. If for some reason your flow crashes, the corresponding exception will be printed to the logs, the caller will continue running, and the browser taken to the selector page where an error message will be displayed. Note your project may contain more flows to serve as utilitarians or simply to break down the authentication flow into smaller, more manageable pieces.", "title": "Flow requisites"}, {"location": "casa/developer/add-authn-methods/#about-templates", "text": "Regarding UI templates, it is recommended to re-use a couple of Freemarker macros available in the casa project. This will allow your flow's UI to have the same look-and-feel of flows bundled out-of-the box, like OTP and fido. Additionally this will allow to properly incorporate backtracking. Import the commons template in your UI page: <#import \"../kz1vc3/commons.ftlh\" as com> Copy the above line of code in the first line of your templates, preferably. Note you may need to add extra ../ fragments in the path to commons.ftlh depending on the directory level where your template resides inside the web subdirectory of your Agama project. Then call the main macro and supply your markup, like this: <@com.main> <!-- your markup here --> <@com.main> The above will generate a page incorporating the required CSS files and will render the header and footer appropriately while leaving your content in the center of the page. The casa project makes heavy use the Tachyons CSS. You may like to use those for building templates instead of incorporating yet another styling framework. It is highly recommended to include the following near the bottom of your markup (still inside the main call block): <@com.alternative /> This will render a form with a text and a link that will allow users to \"escape\" from your flow and take another route, i.e. to backtrack: Then, in your flow's code, you handle the escape this way: data = RRF \"mytemplate.ftlh\" ... When data.skipped is \"\" Finish false The above means your flow can finish with false not only if the authentication did not succeed but also when users wants to backtrack.", "title": "About templates"}, {"location": "casa/developer/add-authn-methods/#the-selector-page", "text": "When backtracking, a selector page is shown where all available methods for the given user are displayed - sorted by strength. From here, the user can take another route to be challenged for an alternative credential. Every element in the list has an icon and descriptive text associated. These elements are configurable and for the case of adding an authentication method, both icon and text should be supplied. To do so, locate in TUI the casa Agama project. See how the flow io.jans.casa.authn.main has a selector section in its configurations. This is a dictionary (JSON object) where keys are qualified names of flows and values are dictionaries at the same time - this where you can provide the required info. For example, if your authentication method is backed by a flow com.acme.authn.food , the casa project configuration may look like { \"io.jans.casa.authn.main\": { \"selector\": { \"com.acme.authn.food\": { \"icon\": \"<i class='fas fa-pizza-slice'></i>\", \"text\": \"A sentence describing what the user is supposed to present in the next screen\" }, ... } }, ... } Alternatively, a pointer to a localized message can be used instead of text . This is the recommended practice if localization/internationalization is relevant. In this case, something like the below will work: ... \"com.acme.authn.food\": { \"icon\": \"<i class='fas fa-pizza-slice'></i>\", \"textKey\": \"foodAuth.methodTitle\" } ... as long as the message key foodAuth.methodTitle is defined in the project's labels.txt file, or elsewhere in another project. Note textKey takes precedence over text when rendering the page. Both icon and textKey (or text ) may contain HTML markup. In this example we are using the font awesome library available in the selector page for rendering a nice icon but we could have used any other thing here like an img tag, for instance. Ensure to properly escape double quotes if necessary. Also make the markup a one-liner: JSON strings cannot span several lines.", "title": "The selector page"}, {"location": "casa/developer/add-authn-methods/#recommended-practices", "text": "Note Ensure to go through this page before proceeding", "title": "Recommended practices"}, {"location": "casa/developer/add-authn-methods/#config-settings", "text": "Use a single place to store configuration settings for your authentication method. The most convenient place is in the Agama project itself. You may have configs associated to each flow in your project and they can be accessed directly in your flows code. Additionally, they can be easily read from your plugin's Java code this way: ips = io.jans.casa.misc.Utils.managedBean(IPersistenceService.class); JSONObject p = ips.getAgamaFlowConfigProperties(\"flow qname\"); Out-of-the-box methods in Casa employ this strategy. Also when you do this, every time a change in project configuration is detected, your Java code gets notified: a call to method reloadConfiguration of your extension is issued, see class SampleCredentialAuthnMethod in the sample credential plugin.", "title": "Config settings"}, {"location": "casa/developer/add-authn-methods/#retries", "text": "Giving the user only one chance to pass an authentication challenge is unfair. Code your flow so users have a couple of opportunities to fail before finishing with false as outcome. Agama's Repeat directive helps you cover this case.", "title": "Retries"}, {"location": "casa/developer/add-authn-methods/#key-questions", "text": "As you try to assemble your project, you will come up with some design decisions, for instance: How to model and store credentials associated to the authentication method? What kind of parameters are relevant for the authentication method? What's the algorithm for authenticating users once they have supplied a valid username/password combination? Depending on the answers, you may like to start instead with plugin development first. This is not always the case though, however, getting your hands on the plugin might help unclutter the path.", "title": "Key questions"}, {"location": "casa/developer/add-authn-methods/#enrollment-plugin", "text": "Coding a Casa plugin is mainly a Java development task. You can use the \"Sample credential\" plugin as a template to start the work. Ensure you have: A Jans Server installation that includes Jans Casa - prefer a VM environment over the CN edition for development purposes. Also, you'll need a way to connect to your server via SSH A copy of the Jans repository (a shallow clone of main branch is OK): https://github.com/JanssenProject/jans", "title": "Enrollment plugin"}, {"location": "casa/developer/add-authn-methods/#plugin-deployment", "text": "Start with deploying the plugin to get acquainted with the process: In the local development machine, cd to ./jans/jans-casa/plugins/samples/sample-cred Run mvn -Dmaven.test.skip package . This may take several minutes (lots of network requests). Once you get it done, the next time you can add the -o switch (offline mode) for faster results A target folder with a couple of jar files in it will be generated Access Casa admin console and in the plugins page, upload the file suffixed with jar-with-dependencies.jar . After one minute approximately, visit the \"Authentication methods\" page, check the \"Favorite color\" widget, and click on \"Save\". Then logout. Login again, this time with a non administrative account. In the landing page (user's dashboard), an item labeled \"Your favorite color\" will be shown on the left (under the \"2FA credentials\" heading). Also, a panel in the central area of the page will be added in accordance. Click on \"Your favorite color\" and you'll land a page to let Casa know what your favorite color is!. This color will be used as a second factor for authentication. Ensure you have enabled another method such as OTP so you can enroll an additional credential in order to be able to active 2FA for this account.", "title": "Plugin deployment"}, {"location": "casa/developer/add-authn-methods/#study-the-sample-project", "text": "Now it's time for you to go through the project folder checking one file at a time. Most of files contain comments that explain the purpose of things. Ensure you make a deep inspection of file ./src/main/resources/assets/user/cred_details.zul . It contains the markup of the page you visited earlier. Make an excursion to interface AuthnMethod found in shared maven module. Note it brings a couple of default methods. Class SampleCredentialAuthnMethod implements this interface.", "title": "Study the sample project"}, {"location": "casa/developer/add-authn-methods/#editing-the-project", "text": "Modifying the project may require you to edit files mainly with .java , .zul , or .properties extensions. Most Java classes used in this plugin can be found in: The repository you cloned earlier The ZK framework documentation Standard Java SE API docs You can remove the plugin and add it as many times as you like - no restarts are needed unless things go really weird. You can do so either via the admin console or by dropping/removing the file directly in the filesystem (the path is /opt/jans/jetty/jans-casa/plugins ).", "title": "Editing the project"}, {"location": "casa/developer/add-authn-methods/#page-tweaks", "text": "If you alter a .zul file and then package and redeploy the plugin, you will most probably not see any change taking effect in the UI page. This is because the ZK framework caches the .zul pages by default for a very long period. To change this behavior do the following: Connect to your VM and cd to /opt/gluu/jetty/jans-casa/webapps Extract ZK descriptor: # jar -xf jans-casa.war WEB-INF/zk.xml Locate XML tag file-check-period and remove it including its surrounding parent desktop-config Save the file and patch the application war: # jar -uf jans-casa.war WEB-INF/zk.xml Restart casa (e.g. systemctl casa restart ) From now on, any template change will take effect after 5 seconds.", "title": "Page tweaks"}, {"location": "casa/developer/overview/", "tags": ["Casa", "developer guide"], "text": "Developer guide # This page gives developers relevant pointers for several tasks including: Plugins development Configuration management Credentials enrollment Customization of Casa's authentication flow Plugins # A plugin is an artifact packaged in a Java ARchive ( jar file) that augments the functionalities available in your default Casa installation. The following is by no means an extensive list of things you can add via plugins: Menu items in user's menu, top-right dropdown menu, or admin's dashboard menu UI pages with arbitrary content (and backend-functionality!), this also applies for the admin dashboard Static files (e.g. Javascript, images, stylesheets, etc.) REST services Authentication mechanisms to be supported by the application In addition to the above: Any plugin can have easy access to the underlying Jans Server database Plugins can onboard their own libraries (jar files) and classes Tools # Acquaintance with the following technologies is recommended: Java 11 or higher, maven ZK 9 framework PF4J framework HTML/CSS/Javascript The underlying database engine used by your Jans Server installation, e.g. PostgreSQL, MySQL, etc. Sample plugins # The best way to start learning Casa plugin development is by playing with the sample plugins you can find here . Clone the repository (a shallow clone of main branch is fine), cd to one of the directories in the folder and run mvn package , then upload the resulting jar-with-dependencies through the administration console. Configuration management # Most aspects of Casa that are configurable through the admin console UI can be programmatically operated using the configuration API. A formal description can be found here . Note all endpoints are protected by OAuth tokens which must have the https://jans.io/casa.config scope. Credentials enrollment # Casa has enrollment capabilities built-in but there are use cases where credential enrollment needs to happen elsewhere in your app ecosystem. A typical scenario is in a user registration application, where users are asked to enroll strong authentication credentials during account creation. To facilitate these tasks, Casa exposes APIs for enrolling the following types of authenticators: Phone numbers for SMS OTP OTP apps or tokens FIDO2 security keys Note Per spec FIDO 2 credentials can only be enrolled from a page belonging to the same domain or subdomain of your Gluu Server. In addition to the above, the API also provides endpoints to query the number/type of credentials currently enrolled by a user as well as means to turn 2FA on and off. Customizing the authentication flow # The authentication experience the user faces when trying to access Casa is implemented in an Agama project which is attached to the authentication server when Casa is installed. As with all authentication flows in Janssen, they belong to (run in the context of) the jans-auth application. This distinction is important because jans-auth and casa are separate Java webapps executed on different Jetty instances. In Casa flow, the user is requested to enter the username and password combination, then depending on how the application is configured, personal user settings, and access policies defined, a second factor may be requested. While this may cater most companies requirements, sometimes there is the need to customize the authentication experience. In fact, Agama facilitates this by design. Here are some things companies would like to do: Alter the UI pages - e.g. look-and-feel, structure, etc. Support more authentication methods Add links to the initial screen to take users to different authentication paths, for instance, to leverage social sites login Include an account registration process Include an extra final screen in case of password expiration Add a \"forgot password\" link Important You might be tempted to take the Agama project archive, apply some editions, add files to it, repack, and redeploy it. While this might seem the easiest thing to do, it is also the worst thing to do. Authentication journeys can be extended/tailored by means of creating additional projects. Try not to hack/patch the original project. Casa ACR update # Given the warning above, there has to be a way to launch a different Agama flow than the one used by default to log into Casa. This can be achieved by supplying a value for Casa's acr startup variable: in VM-based installations, locate the file /etc/default/casa in and modify the variable as needed. The format is agama_<qualified-name-of-your-flow> . Then restart Casa. Requisites # Regardless of the customization required, it is desirable to get acquaintance with Agama framework . This is a good time to go through the Agama developer guide pages found in the Administration section of Jans Server docs. Specifically, several of the Agama advanced usages will help you materialize your requirements. Extract the Agama project to your development machine. It is useful to get an idea of how and what the out-of-the-box project does. Also, keep the Freemarker manual at hand. Page customizations # The UI pages of the default Casa flow resemble the design of the Casa app itself. Also, modifications applied through the \"custom branding\" functionalities are automatically reflected in flow pages without any sort of intervention. This is neat, but if you need to go further, you will have to code the UI pages your own based on the existing ones. For this purpose, create a new Agama project with one flow in it. Pick one of the pages you want to change from the original project and build your own - initially keep it really simple: a dummy page is OK. From your new flow, use the Trigger directive to launch flow io.jans.casa.authn.main . Add an Override templates directive to your Trigger so the page in Casa project is superseded by the page you are creating. This is explained here . Pack your new project and deploy it. Wait for around 30 seconds and try to log into Casa to see the changes. Note you have to configure casa so your flow is launched, not the default one, ie. io.jans.casa.authn.main . This was explained earlier . Do as many changes as needed to your page. Then pick another page to alter and feed your Override templates accordingly. Repeat until your are done. Recall there is no need to restart jans-auth or casa . In some cases, the original look-and-feel may be satisfying but it's the text content what you would like to change. Agama engine supports localization and internationalization as explained here so you can supply translated messages in your own project and make templates use those. Note Casa is only bundled with a set of \"default\" labels out-of-the box and thus pages don't change content regardless of browser's language or location. By overriding templates and providing labels in several languages, you can achieve full localization/internationalization in the authentication UI. Support more authentication methods # This is probably the most common requirement. Visit this page to learn more. Other forms of customization # Most forms of customization can be tackled using flow cancellation. Through cancellation, a flow can be aborted while running and the control returned to one of its callers. Learn more about this topic here . As an example, let's assume you want to add a \"don't have an account? register here\" button in the initial screen of Casa flow. Here's what you can do: Create a new Agama project with one flow in it. Copy the page that prompts username and password into your project. Below the login button, add a form containing markup like <button type=\"submit\" name=\"_abort\">don't have an account? register here</button> In your flow, let's call it A , use the Trigger directive to launch flow io.jans.casa.authn.main . Add an Override templates directive to your Trigger so the original login page in Casa project is superseded by the page you created Create another flow, let's call it B . This will be the \"registration\" flow which will present one or more screens to grab data in order to create an account for the user. Make B finish with true outcome if the account was successfully created, otherwise finish with false Back in flow A , add code to check if io.jans.casa.authn.main was aborted, if so, launch flow B . For simplicity, if B didn't go well, terminate A If B went well, show the original login form, that is, no registration button this time Add code for termination So flow A will end up looking more or less like this: ... result = Trigger io.jans.casa.authn.main Override templates \"kz1vc3/main.ftlh\" \"newPage.ftlh\" When result.aborted is true //registration button was clicked result = Trigger B When result.success is false Finish false result = Trigger io.jans.casa.authn.main Finish result Here we have taken a simplistic approach to make the example concise. In practice you may like to be more elaborated and include an \"already have an account?\" button in the registration page, which could create a sort of navigational loop. Here the Repeat directive will emerge in your code for sure. Note When trying to customize an existing flow, familiarize with all possible paths the flow can take you to. Consider all possible screens and determine which require adjustments and the points at which cancellation is of use. Sometimes you will have to glance its .flow file (Agama code) to get a better idea.", "title": "Overview"}, {"location": "casa/developer/overview/#developer-guide", "text": "This page gives developers relevant pointers for several tasks including: Plugins development Configuration management Credentials enrollment Customization of Casa's authentication flow", "title": "Developer guide"}, {"location": "casa/developer/overview/#plugins", "text": "A plugin is an artifact packaged in a Java ARchive ( jar file) that augments the functionalities available in your default Casa installation. The following is by no means an extensive list of things you can add via plugins: Menu items in user's menu, top-right dropdown menu, or admin's dashboard menu UI pages with arbitrary content (and backend-functionality!), this also applies for the admin dashboard Static files (e.g. Javascript, images, stylesheets, etc.) REST services Authentication mechanisms to be supported by the application In addition to the above: Any plugin can have easy access to the underlying Jans Server database Plugins can onboard their own libraries (jar files) and classes", "title": "Plugins"}, {"location": "casa/developer/overview/#tools", "text": "Acquaintance with the following technologies is recommended: Java 11 or higher, maven ZK 9 framework PF4J framework HTML/CSS/Javascript The underlying database engine used by your Jans Server installation, e.g. PostgreSQL, MySQL, etc.", "title": "Tools"}, {"location": "casa/developer/overview/#sample-plugins", "text": "The best way to start learning Casa plugin development is by playing with the sample plugins you can find here . Clone the repository (a shallow clone of main branch is fine), cd to one of the directories in the folder and run mvn package , then upload the resulting jar-with-dependencies through the administration console.", "title": "Sample plugins"}, {"location": "casa/developer/overview/#configuration-management", "text": "Most aspects of Casa that are configurable through the admin console UI can be programmatically operated using the configuration API. A formal description can be found here . Note all endpoints are protected by OAuth tokens which must have the https://jans.io/casa.config scope.", "title": "Configuration management"}, {"location": "casa/developer/overview/#credentials-enrollment", "text": "Casa has enrollment capabilities built-in but there are use cases where credential enrollment needs to happen elsewhere in your app ecosystem. A typical scenario is in a user registration application, where users are asked to enroll strong authentication credentials during account creation. To facilitate these tasks, Casa exposes APIs for enrolling the following types of authenticators: Phone numbers for SMS OTP OTP apps or tokens FIDO2 security keys Note Per spec FIDO 2 credentials can only be enrolled from a page belonging to the same domain or subdomain of your Gluu Server. In addition to the above, the API also provides endpoints to query the number/type of credentials currently enrolled by a user as well as means to turn 2FA on and off.", "title": "Credentials enrollment"}, {"location": "casa/developer/overview/#customizing-the-authentication-flow", "text": "The authentication experience the user faces when trying to access Casa is implemented in an Agama project which is attached to the authentication server when Casa is installed. As with all authentication flows in Janssen, they belong to (run in the context of) the jans-auth application. This distinction is important because jans-auth and casa are separate Java webapps executed on different Jetty instances. In Casa flow, the user is requested to enter the username and password combination, then depending on how the application is configured, personal user settings, and access policies defined, a second factor may be requested. While this may cater most companies requirements, sometimes there is the need to customize the authentication experience. In fact, Agama facilitates this by design. Here are some things companies would like to do: Alter the UI pages - e.g. look-and-feel, structure, etc. Support more authentication methods Add links to the initial screen to take users to different authentication paths, for instance, to leverage social sites login Include an account registration process Include an extra final screen in case of password expiration Add a \"forgot password\" link Important You might be tempted to take the Agama project archive, apply some editions, add files to it, repack, and redeploy it. While this might seem the easiest thing to do, it is also the worst thing to do. Authentication journeys can be extended/tailored by means of creating additional projects. Try not to hack/patch the original project.", "title": "Customizing the authentication flow"}, {"location": "casa/developer/overview/#casa-acr-update", "text": "Given the warning above, there has to be a way to launch a different Agama flow than the one used by default to log into Casa. This can be achieved by supplying a value for Casa's acr startup variable: in VM-based installations, locate the file /etc/default/casa in and modify the variable as needed. The format is agama_<qualified-name-of-your-flow> . Then restart Casa.", "title": "Casa ACR update"}, {"location": "casa/developer/overview/#requisites", "text": "Regardless of the customization required, it is desirable to get acquaintance with Agama framework . This is a good time to go through the Agama developer guide pages found in the Administration section of Jans Server docs. Specifically, several of the Agama advanced usages will help you materialize your requirements. Extract the Agama project to your development machine. It is useful to get an idea of how and what the out-of-the-box project does. Also, keep the Freemarker manual at hand.", "title": "Requisites"}, {"location": "casa/developer/overview/#page-customizations", "text": "The UI pages of the default Casa flow resemble the design of the Casa app itself. Also, modifications applied through the \"custom branding\" functionalities are automatically reflected in flow pages without any sort of intervention. This is neat, but if you need to go further, you will have to code the UI pages your own based on the existing ones. For this purpose, create a new Agama project with one flow in it. Pick one of the pages you want to change from the original project and build your own - initially keep it really simple: a dummy page is OK. From your new flow, use the Trigger directive to launch flow io.jans.casa.authn.main . Add an Override templates directive to your Trigger so the page in Casa project is superseded by the page you are creating. This is explained here . Pack your new project and deploy it. Wait for around 30 seconds and try to log into Casa to see the changes. Note you have to configure casa so your flow is launched, not the default one, ie. io.jans.casa.authn.main . This was explained earlier . Do as many changes as needed to your page. Then pick another page to alter and feed your Override templates accordingly. Repeat until your are done. Recall there is no need to restart jans-auth or casa . In some cases, the original look-and-feel may be satisfying but it's the text content what you would like to change. Agama engine supports localization and internationalization as explained here so you can supply translated messages in your own project and make templates use those. Note Casa is only bundled with a set of \"default\" labels out-of-the box and thus pages don't change content regardless of browser's language or location. By overriding templates and providing labels in several languages, you can achieve full localization/internationalization in the authentication UI.", "title": "Page customizations"}, {"location": "casa/developer/overview/#support-more-authentication-methods", "text": "This is probably the most common requirement. Visit this page to learn more.", "title": "Support more authentication methods"}, {"location": "casa/developer/overview/#other-forms-of-customization", "text": "Most forms of customization can be tackled using flow cancellation. Through cancellation, a flow can be aborted while running and the control returned to one of its callers. Learn more about this topic here . As an example, let's assume you want to add a \"don't have an account? register here\" button in the initial screen of Casa flow. Here's what you can do: Create a new Agama project with one flow in it. Copy the page that prompts username and password into your project. Below the login button, add a form containing markup like <button type=\"submit\" name=\"_abort\">don't have an account? register here</button> In your flow, let's call it A , use the Trigger directive to launch flow io.jans.casa.authn.main . Add an Override templates directive to your Trigger so the original login page in Casa project is superseded by the page you created Create another flow, let's call it B . This will be the \"registration\" flow which will present one or more screens to grab data in order to create an account for the user. Make B finish with true outcome if the account was successfully created, otherwise finish with false Back in flow A , add code to check if io.jans.casa.authn.main was aborted, if so, launch flow B . For simplicity, if B didn't go well, terminate A If B went well, show the original login form, that is, no registration button this time Add code for termination So flow A will end up looking more or less like this: ... result = Trigger io.jans.casa.authn.main Override templates \"kz1vc3/main.ftlh\" \"newPage.ftlh\" When result.aborted is true //registration button was clicked result = Trigger B When result.success is false Finish false result = Trigger io.jans.casa.authn.main Finish result Here we have taken a simplistic approach to make the example concise. In practice you may like to be more elaborated and include an \"already have an account?\" button in the registration page, which could create a sort of navigational loop. Here the Repeat directive will emerge in your code for sure. Note When trying to customize an existing flow, familiarize with all possible paths the flow can take you to. Consider all possible screens and determine which require adjustments and the points at which cancellation is of use. Sometimes you will have to glance its .flow file (Agama code) to get a better idea.", "title": "Other forms of customization"}, {"location": "casa/plugins/2fa-settings/", "tags": ["Casa", "2FA"], "text": "2FA Settings Plugin # Overview # This plugin allows administrators to configure how and when 2FA is applied. Admins may: Specify the minimum number of credentials users must enroll before 2FA can be used Allow 2FA to be automatically enabled upon credential enrollment Prevent users to turn 2FA on and off their own Allow users to choose a preferred method of authentication When (2) is not used, option (3) is disabled. This is the default behavior exhibited in Casa where users explicitly enable or disable 2FA usage. When (2) is active, 2FA is turned on as soon as the user enrolls a credential and the minimum required is fulfilled. Bear in mind: Automatic enablement happens only via GUI: enrollments made using the API will have to turn 2FA on by means of the API itself Plugins attaching authentication methods to Casa have to explicitly call method notifyEnrollment of SndFactorAuthenticationUtils upon successful enrollments (see the javadocs). Also, 2FA is automatically turned on upon login for users with enough credentials registered and not having 2FA turned on yet. With (4) users may choose a preferred type of credential. This means that when requested for a second factor, a credential of such \"preferred\" type will be prompted first instead of the credential considered the \"strongest\". The strength associated to a method is equal to the numeric level assigned to the custom script that represents the method. For more restrictive scenarios, administrators have the option to remove the 2FA switch (3) from the user's dashboard. Additionally this plugin allows to: Choose from a set of predefined policies for when 2FA should be prompted: Always (at every login attempt) When user's location is unrecognized When user's device is unrecognized Users can define their own policy (based on the above) Set how long a location or device can be deemed as recognized Moreover, when administrators allow users to set their own strong authentication policy, users can: View the list of physical devices they have used to login (e.g. PC, tablet, phone) View the time and location (city) associated to the last login event Remove a device from the list (eg. when it should not be considered trustworthy anymore) A device/location is considered trustworthy when the user has presented a strong credential in order to login to Casa in such device/location. Subsequent login attempts from trustworthy (recognized) device/locations will not require them to present a second factor. Requirements # The plugin jar file must match the version of your Janssen Server installation. Installation # Download the plugin Log in to Casa using an administrator account Navigate to Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add How to use # For administrators, a new link labeled \"2FA settings\" appears in the dashboard menu to access the function. For regular users, proper details appear in the widget where 2FA is turned on. API # Configurations provided by this plugin can also be applied by means of the API exposed for this purpose. A formal description of the API can be found in this swagger file. Note all endpoints are protected by tokens which must have the https://jans.io/casa.config OAuth scope.", "title": "2FA Settings"}, {"location": "casa/plugins/2fa-settings/#2fa-settings-plugin", "text": "", "title": "2FA Settings Plugin"}, {"location": "casa/plugins/2fa-settings/#overview", "text": "This plugin allows administrators to configure how and when 2FA is applied. Admins may: Specify the minimum number of credentials users must enroll before 2FA can be used Allow 2FA to be automatically enabled upon credential enrollment Prevent users to turn 2FA on and off their own Allow users to choose a preferred method of authentication When (2) is not used, option (3) is disabled. This is the default behavior exhibited in Casa where users explicitly enable or disable 2FA usage. When (2) is active, 2FA is turned on as soon as the user enrolls a credential and the minimum required is fulfilled. Bear in mind: Automatic enablement happens only via GUI: enrollments made using the API will have to turn 2FA on by means of the API itself Plugins attaching authentication methods to Casa have to explicitly call method notifyEnrollment of SndFactorAuthenticationUtils upon successful enrollments (see the javadocs). Also, 2FA is automatically turned on upon login for users with enough credentials registered and not having 2FA turned on yet. With (4) users may choose a preferred type of credential. This means that when requested for a second factor, a credential of such \"preferred\" type will be prompted first instead of the credential considered the \"strongest\". The strength associated to a method is equal to the numeric level assigned to the custom script that represents the method. For more restrictive scenarios, administrators have the option to remove the 2FA switch (3) from the user's dashboard. Additionally this plugin allows to: Choose from a set of predefined policies for when 2FA should be prompted: Always (at every login attempt) When user's location is unrecognized When user's device is unrecognized Users can define their own policy (based on the above) Set how long a location or device can be deemed as recognized Moreover, when administrators allow users to set their own strong authentication policy, users can: View the list of physical devices they have used to login (e.g. PC, tablet, phone) View the time and location (city) associated to the last login event Remove a device from the list (eg. when it should not be considered trustworthy anymore) A device/location is considered trustworthy when the user has presented a strong credential in order to login to Casa in such device/location. Subsequent login attempts from trustworthy (recognized) device/locations will not require them to present a second factor.", "title": "Overview"}, {"location": "casa/plugins/2fa-settings/#requirements", "text": "The plugin jar file must match the version of your Janssen Server installation.", "title": "Requirements"}, {"location": "casa/plugins/2fa-settings/#installation", "text": "Download the plugin Log in to Casa using an administrator account Navigate to Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add", "title": "Installation"}, {"location": "casa/plugins/2fa-settings/#how-to-use", "text": "For administrators, a new link labeled \"2FA settings\" appears in the dashboard menu to access the function. For regular users, proper details appear in the widget where 2FA is turned on.", "title": "How to use"}, {"location": "casa/plugins/2fa-settings/#api", "text": "Configurations provided by this plugin can also be applied by means of the API exposed for this purpose. A formal description of the API can be found in this swagger file. Note all endpoints are protected by tokens which must have the https://jans.io/casa.config OAuth scope.", "title": "API"}, {"location": "casa/plugins/bioid/", "tags": ["Casa", "Biometrical"], "text": "BioID plugin # Overview # This plugin allows users to enroll their BioID facial biometrics. Requirements # A Janssen server installation with Casa installed A BioID account. Register on the BioID site Application credentials from the BWS Portal. Please register an application against your account. You will need the app identifier, app secret, storage and partition. Installation # Download the plugin jar. Log into Casa as an administrator, navigate to Administration Console > Casa plugins and add the plugin jar Restart the casa service: sudo systemctl restart jans-casa Using the TUI, navigate to Auth Server > Clients , open the details for Client for Casa , and add the following redirect URI: https://<hostname>/jans-casa/pl/bioid-plugin/user/interlude.zul . Replace <hostname> with the hostname of your server, and save the client. Run the following commands to generate the Agama flow file: git clone --depth 1 --branch main --no-checkout https://github.com/JanssenProject/jans.git cd jans/jans-casa/plugins/bioid/extras/agama zip -r casa-bioid.gama ./* 1. Transfer the casa-bioid.gama file to the server, and deploy it using the TUI 1. Using the TUI, export the sample configuration, edit it according to the specification below and import it back in Agama Configuration # { \"io.jans.agama.bioid.enroll\": { \"host\": \"https://<HOSTNAME>/jans-auth/fl/callback\", \"endpoint\": \"https://bws.bioid.com/extension/\", \"appIdentifier\": \"\", \"appSecret\": \"\", \"storage\": \"\", \"partition\": \"\" } } host : Replace <HOSTNAME> with the hostname of your server endpoint : BioID API endpoint. Leave as default appIdentifier : The app identifier string from BWS Portal - Configuration appSecret : The app secret from BWS Portal - Configuration storage : Storage value from BWS Portal - Configuration partition : Partition value from BWS Portal - Configuration How to use # The plugin provides a user menu. When clicking the Click to Enroll button, Casa launches the io.jans.agama.bioid.enroll flow on the authorization server. This flow queries the BioID database for existing enrollments for the user. If the user has not enrolled, the flow presents the BWS GUI for enrollment. Upon success, the flow redirects back to a Casa landing page. Deletion of credentials is not supported as of now because Casa is unaware of enrollment status of a user.", "title": "BioID"}, {"location": "casa/plugins/bioid/#bioid-plugin", "text": "", "title": "BioID plugin"}, {"location": "casa/plugins/bioid/#overview", "text": "This plugin allows users to enroll their BioID facial biometrics.", "title": "Overview"}, {"location": "casa/plugins/bioid/#requirements", "text": "A Janssen server installation with Casa installed A BioID account. Register on the BioID site Application credentials from the BWS Portal. Please register an application against your account. You will need the app identifier, app secret, storage and partition.", "title": "Requirements"}, {"location": "casa/plugins/bioid/#installation", "text": "Download the plugin jar. Log into Casa as an administrator, navigate to Administration Console > Casa plugins and add the plugin jar Restart the casa service: sudo systemctl restart jans-casa Using the TUI, navigate to Auth Server > Clients , open the details for Client for Casa , and add the following redirect URI: https://<hostname>/jans-casa/pl/bioid-plugin/user/interlude.zul . Replace <hostname> with the hostname of your server, and save the client. Run the following commands to generate the Agama flow file: git clone --depth 1 --branch main --no-checkout https://github.com/JanssenProject/jans.git cd jans/jans-casa/plugins/bioid/extras/agama zip -r casa-bioid.gama ./* 1. Transfer the casa-bioid.gama file to the server, and deploy it using the TUI 1. Using the TUI, export the sample configuration, edit it according to the specification below and import it back in", "title": "Installation"}, {"location": "casa/plugins/bioid/#agama-configuration", "text": "{ \"io.jans.agama.bioid.enroll\": { \"host\": \"https://<HOSTNAME>/jans-auth/fl/callback\", \"endpoint\": \"https://bws.bioid.com/extension/\", \"appIdentifier\": \"\", \"appSecret\": \"\", \"storage\": \"\", \"partition\": \"\" } } host : Replace <HOSTNAME> with the hostname of your server endpoint : BioID API endpoint. Leave as default appIdentifier : The app identifier string from BWS Portal - Configuration appSecret : The app secret from BWS Portal - Configuration storage : Storage value from BWS Portal - Configuration partition : Partition value from BWS Portal - Configuration", "title": "Agama Configuration"}, {"location": "casa/plugins/bioid/#how-to-use", "text": "The plugin provides a user menu. When clicking the Click to Enroll button, Casa launches the io.jans.agama.bioid.enroll flow on the authorization server. This flow queries the BioID database for existing enrollments for the user. If the user has not enrolled, the flow presents the BWS GUI for enrollment. Upon success, the flow redirects back to a Casa landing page. Deletion of credentials is not supported as of now because Casa is unaware of enrollment status of a user.", "title": "How to use"}, {"location": "casa/plugins/consent-management/", "tags": ["Casa", "Consent"], "text": "Consent Management Plugin # Overview # The Consent Management plugin gives end-users the ability to view and revoke previously granted authorizations provided to applications accessed with their account in a Janssen Server. Requirements # The plugin jar file must match the version of your Casa (and Janssen Server) installation. Installation # Download the plugin Login to Casa using an administrator account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add User guide # For information on how to use the plugin, see the User Guide", "title": "Consent Management"}, {"location": "casa/plugins/consent-management/#consent-management-plugin", "text": "", "title": "Consent Management Plugin"}, {"location": "casa/plugins/consent-management/#overview", "text": "The Consent Management plugin gives end-users the ability to view and revoke previously granted authorizations provided to applications accessed with their account in a Janssen Server.", "title": "Overview"}, {"location": "casa/plugins/consent-management/#requirements", "text": "The plugin jar file must match the version of your Casa (and Janssen Server) installation.", "title": "Requirements"}, {"location": "casa/plugins/consent-management/#installation", "text": "Download the plugin Login to Casa using an administrator account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add", "title": "Installation"}, {"location": "casa/plugins/consent-management/#user-guide", "text": "For information on how to use the plugin, see the User Guide", "title": "User guide"}, {"location": "casa/plugins/custom-branding/", "tags": ["Casa", "Branding"], "text": "Custom Branding Plugin # Overview # This plugin allows admins to apply a design customization by choosing colors, favicon, logo, and footer text to match their company's look and feel. Alternatively, they can supply all assets (images and CSS files) externally to cover more demanding needs. Requirements # The plugin jar file must match the version of your Casa (and Janssen Server) installation. Installation # Download the plugin Login to Casa using an administrator account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add How to use # See the custom branding page for full instructions.", "title": "Custom Branding"}, {"location": "casa/plugins/custom-branding/#custom-branding-plugin", "text": "", "title": "Custom Branding Plugin"}, {"location": "casa/plugins/custom-branding/#overview", "text": "This plugin allows admins to apply a design customization by choosing colors, favicon, logo, and footer text to match their company's look and feel. Alternatively, they can supply all assets (images and CSS files) externally to cover more demanding needs.", "title": "Overview"}, {"location": "casa/plugins/custom-branding/#requirements", "text": "The plugin jar file must match the version of your Casa (and Janssen Server) installation.", "title": "Requirements"}, {"location": "casa/plugins/custom-branding/#installation", "text": "Download the plugin Login to Casa using an administrator account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin jar file Click on Add", "title": "Installation"}, {"location": "casa/plugins/custom-branding/#how-to-use", "text": "See the custom branding page for full instructions.", "title": "How to use"}, {"location": "casa/plugins/email-otp/", "tags": ["Casa", "OTP"], "text": "E-mail OTP Plugin # Overview # With this plugin, administrators can onboard a new type of authentication factor consisting of one-time passcodes (OTP) delivered to the user's inbox. This plugin simply shows a list of the already registered e-mail addresses of the user in the UI of Casa, however the accompanying Agama project contributes a new option in the authentication experience where the user is prompted to enter an OTP delivered to one of his e-mail addresses, if any. By adding the plugin and the corresponding Agama project to your server, all users having at least one e-mail address in his profile (database attribute mail ) will be given the option to get a passcode delivered and then prompted for such as a form of 2FA. Requirements # The SMTP configuration must be previously populated in the Jans Server. For this purpose you can use an administrative tool like TUI. Visit the SMTP section and fill the values requested. Ensure to run and pass the test presented before proceeding. Then, restart the authentication server. Installation # Plugin # Download the plugin jar file Login to Casa using an administrative account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin file Click on Add and wait for one minute Visit the Authentication methods section of the admin console. Tick the Registered e-mails widget, drag it to the desired position, and finally hit Save Agama project # Download the project archive Deploy the project onto the server - you can use TUI for this task Parameterize the project - you can use the project's sample configuration as a guide. The below summarizes the properties used: otp_length : Number of digits the OTPs will have (passcode length) otp_lifetime : Passcode expiration in minutes subject : Subject to use in e-mail messages. You can use %s as a placeholder to insert the value of the generated OTP message : Body of e-mail messages. You can use %s as a placeholder to insert the value of the generated OTP. Basic HTML markup is supported; ensure to properly escape characters like double quotes - keep in mind this is JSON content Parameterize the casa project: in the casa project configuration, locate the selector section under io.jans.casa.authn.main flow and add an entry with key io.jans.casa.authn.emailotp . Assign an icon and a pointer to a short descriptive text. Example: ... \"io.jans.casa.authn.emailotp\": { \"icon\": \"<i class='fas fa-envelope' data-fa-transform='shrink-1'></i>\", \"textKey\": \"email2fa.selector_text\" } ... Test # Create one or more testing users with real e-mail addresses associated to their accounts Log into casa with such users and enroll some credential, like a passkey, SuperGluu, etc. Then turn 2fA for them. Logout and login again. A new option for receiving OTPs via e-mail will be presented User guide # Using the plugin is straightforward and does not require further explanation.", "title": "Email OTP"}, {"location": "casa/plugins/email-otp/#e-mail-otp-plugin", "text": "", "title": "E-mail OTP Plugin"}, {"location": "casa/plugins/email-otp/#overview", "text": "With this plugin, administrators can onboard a new type of authentication factor consisting of one-time passcodes (OTP) delivered to the user's inbox. This plugin simply shows a list of the already registered e-mail addresses of the user in the UI of Casa, however the accompanying Agama project contributes a new option in the authentication experience where the user is prompted to enter an OTP delivered to one of his e-mail addresses, if any. By adding the plugin and the corresponding Agama project to your server, all users having at least one e-mail address in his profile (database attribute mail ) will be given the option to get a passcode delivered and then prompted for such as a form of 2FA.", "title": "Overview"}, {"location": "casa/plugins/email-otp/#requirements", "text": "The SMTP configuration must be previously populated in the Jans Server. For this purpose you can use an administrative tool like TUI. Visit the SMTP section and fill the values requested. Ensure to run and pass the test presented before proceeding. Then, restart the authentication server.", "title": "Requirements"}, {"location": "casa/plugins/email-otp/#installation", "text": "", "title": "Installation"}, {"location": "casa/plugins/email-otp/#plugin", "text": "Download the plugin jar file Login to Casa using an administrative account Visit Administration console > Casa plugins Click on Add a plugin... and select the plugin file Click on Add and wait for one minute Visit the Authentication methods section of the admin console. Tick the Registered e-mails widget, drag it to the desired position, and finally hit Save", "title": "Plugin"}, {"location": "casa/plugins/email-otp/#agama-project", "text": "Download the project archive Deploy the project onto the server - you can use TUI for this task Parameterize the project - you can use the project's sample configuration as a guide. The below summarizes the properties used: otp_length : Number of digits the OTPs will have (passcode length) otp_lifetime : Passcode expiration in minutes subject : Subject to use in e-mail messages. You can use %s as a placeholder to insert the value of the generated OTP message : Body of e-mail messages. You can use %s as a placeholder to insert the value of the generated OTP. Basic HTML markup is supported; ensure to properly escape characters like double quotes - keep in mind this is JSON content Parameterize the casa project: in the casa project configuration, locate the selector section under io.jans.casa.authn.main flow and add an entry with key io.jans.casa.authn.emailotp . Assign an icon and a pointer to a short descriptive text. Example: ... \"io.jans.casa.authn.emailotp\": { \"icon\": \"<i class='fas fa-envelope' data-fa-transform='shrink-1'></i>\", \"textKey\": \"email2fa.selector_text\" } ...", "title": "Agama project"}, {"location": "casa/plugins/email-otp/#test", "text": "Create one or more testing users with real e-mail addresses associated to their accounts Log into casa with such users and enroll some credential, like a passkey, SuperGluu, etc. Then turn 2fA for them. Logout and login again. A new option for receiving OTPs via e-mail will be presented", "title": "Test"}, {"location": "casa/plugins/email-otp/#user-guide", "text": "Using the plugin is straightforward and does not require further explanation.", "title": "User guide"}, {"location": "casa/plugins/accts-linking/account-linking-index/", "tags": ["Casa", "Accounts Linking"], "text": "Accounts Linking Plugin # Overview # This plugin allows users to \"link\" their local Jans account with existing accounts at third-party identity providers like OIDC OPs and social sites, e.g. Apple, Facebook, Google, etc. Besides the usual onboarding of a plugin jar file in Casa, administrators must deploy a number of additional components. This will be regarded later. However let's summary the key points of the accounts linking experience: When a user tries to login to Casa, the usual username/password form is presented but also a list of links that can take him to external sites (third-party identity providers) where authentication takes place Once authenticated, user profile data is grabbed from the external site - this is all backchannel A process called attribute mapping is performed on profile data. This is a transformation process that turns incoming profile data into a shape compatible with a regular Jans database user entry If the mapped profile data matches an existing user in the Jans database, the existing entry is updated with the incoming data, otherwise, a new entry is inserted - this is called user provisioning . When provisioning occurs, the account has no password associated Finally the user is given access to Casa From the perspective of a user already logged into Casa, the experience is as follows: In casa, a menu item is provided which takes the user to a (Casa) page that shows a list of third-party identity providers. For every provider there are options to trigger linking in case there is no account linked yet (external site authentication is launched), or to remove the linked account from the user profile If an account has no password assigned, removal of linked accounts is not allowed. However, a functionality for the user to assign himself a password is provided Components deployment # The pieces that allow materialization of the experience summarized above are the following: a) The Casa plugin jar file b) The Agama inbound identity project c) The Casa accounts linking Agama project Most of work is demanded on setting up project c , where configuration of identity providers and attribute mapping tuning takes place. In the following, it is assumed you have a VM-based installation of Jans Server (or Gluu Flex) available with Casa installed. In a separate machine, ensure you have SSH/SCP/SFTP access to such server and git installed. Download the plugin jar file https://maven.jans.io/maven/io/jans/casa/plugins/acct-linking/replace-janssen-version/acct-linking-replace-janssen-version-jar-with-dependencies.jar and copy to your server's /opt/jans/jetty/jans-casa/plugins Download the utility jar file https://maven.jans.io/maven/io/jans/agama-inbound/replace-janssen-version/agama-inbound-replace-janssen-version.jar and copy to your server's /opt/jans/jetty/jans-auth/custom/libs In TUI, visit the Clients screen, locate the client labeled \"Client for Casa\". Add the following redirect URI to the list: https://<your-jans-host>/jans-casa/pl/acct-linking/user/interlude.zul . Replace the name of your Jans server accordingly Run the following commands to generate the archive of the Agama inbound identity project git clone --depth 1 --branch main --no-checkout https://github.com/JanssenProject/jans.git cd jans git sparse-checkout init --cone git sparse-checkout set docs/agama-catalog/jans/inboundID/project git checkout main cd docs/agama-catalog/jans/inboundID/project zip -r inbound.zip * Download the Casa accounts linking Agama project https://maven.jans.io/maven/io/jans/casa/plugins/acct-linking-agama/replace-janssen-version/acct-linking-agama-replace-janssen-version-project.zip Transfer the two zip files to a location in the server, deploy both archives using TUI (Agama menu) Finally restart the authentication server Configuration # The first step is figuring out the external sites to support. Keep in mind only OpenID or OAuth 2.0 based providers can be onboarded. There is not support for SAML IDPs. The procedures for getting configuration settings in order to integrate third party providers vary widely. Here, only basic guidelines are given: If the provider is OpenId-compliant and supports dynamic client registration, obtain the OP URL and the scopes list to use when requesting user profile information. Most of times the scopes openid , profile and email will fit the bill If the provider is OpenId-compliant and does not support dynamic client registration, obtain the OP URL and scopes as in the previous case, and also a client ID and secret If the provider does not support OpenId. Obtain the following: The authorization endpoint URL The token endpoint URL The endpoint URL where profile data can be retrieved Client credentials (ID and secret) Scopes to use when requesting user profile information The steps required to grab the above data vary among providers. Normally this is obtained through a sort of administrative developer GUI tool. If you are prompted for a \"redirect URI\" in such tool, provide https://<your-jans-host>/jans-auth/fl/callback . Now it's time to supply the settings grabbed. The component these configurations are injected to is the Casa accounts linking Agama project. To make the effort easier, this project is bundled with some dummy configuration properties you can use as a template. Proceed as follows: In TUI, open the Agama tab and scroll through the list of projects until the casa-account-linking is highlighted Open the configuration management dialog (press c ) and choose to export the sample configuration to a file on disk Apply changes as needed - this is covered in a separate doc page here . Note you can add or remove sections in the file at will, and that providers can also be disabled so they are not listed in the login page or in Casa app Still in TUI, choose to import the file you have edited For VM-based installations, update the file /etc/default/jans-casa . Locate a segment that reads -Dacr= and assign agama_io.jans.casa.authn.acctlinking as new value. This will make Casa use the flow found in the accounts linking project - not the flow bundled out-of-the-box. Finally restart Casa and conduct your testing. You will now see the login page contains a list of links to the configured identity providers.", "title": "Accounts Linking Plugin"}, {"location": "casa/plugins/accts-linking/account-linking-index/#accounts-linking-plugin", "text": "", "title": "Accounts Linking Plugin"}, {"location": "casa/plugins/accts-linking/account-linking-index/#overview", "text": "This plugin allows users to \"link\" their local Jans account with existing accounts at third-party identity providers like OIDC OPs and social sites, e.g. Apple, Facebook, Google, etc. Besides the usual onboarding of a plugin jar file in Casa, administrators must deploy a number of additional components. This will be regarded later. However let's summary the key points of the accounts linking experience: When a user tries to login to Casa, the usual username/password form is presented but also a list of links that can take him to external sites (third-party identity providers) where authentication takes place Once authenticated, user profile data is grabbed from the external site - this is all backchannel A process called attribute mapping is performed on profile data. This is a transformation process that turns incoming profile data into a shape compatible with a regular Jans database user entry If the mapped profile data matches an existing user in the Jans database, the existing entry is updated with the incoming data, otherwise, a new entry is inserted - this is called user provisioning . When provisioning occurs, the account has no password associated Finally the user is given access to Casa From the perspective of a user already logged into Casa, the experience is as follows: In casa, a menu item is provided which takes the user to a (Casa) page that shows a list of third-party identity providers. For every provider there are options to trigger linking in case there is no account linked yet (external site authentication is launched), or to remove the linked account from the user profile If an account has no password assigned, removal of linked accounts is not allowed. However, a functionality for the user to assign himself a password is provided", "title": "Overview"}, {"location": "casa/plugins/accts-linking/account-linking-index/#components-deployment", "text": "The pieces that allow materialization of the experience summarized above are the following: a) The Casa plugin jar file b) The Agama inbound identity project c) The Casa accounts linking Agama project Most of work is demanded on setting up project c , where configuration of identity providers and attribute mapping tuning takes place. In the following, it is assumed you have a VM-based installation of Jans Server (or Gluu Flex) available with Casa installed. In a separate machine, ensure you have SSH/SCP/SFTP access to such server and git installed. Download the plugin jar file https://maven.jans.io/maven/io/jans/casa/plugins/acct-linking/replace-janssen-version/acct-linking-replace-janssen-version-jar-with-dependencies.jar and copy to your server's /opt/jans/jetty/jans-casa/plugins Download the utility jar file https://maven.jans.io/maven/io/jans/agama-inbound/replace-janssen-version/agama-inbound-replace-janssen-version.jar and copy to your server's /opt/jans/jetty/jans-auth/custom/libs In TUI, visit the Clients screen, locate the client labeled \"Client for Casa\". Add the following redirect URI to the list: https://<your-jans-host>/jans-casa/pl/acct-linking/user/interlude.zul . Replace the name of your Jans server accordingly Run the following commands to generate the archive of the Agama inbound identity project git clone --depth 1 --branch main --no-checkout https://github.com/JanssenProject/jans.git cd jans git sparse-checkout init --cone git sparse-checkout set docs/agama-catalog/jans/inboundID/project git checkout main cd docs/agama-catalog/jans/inboundID/project zip -r inbound.zip * Download the Casa accounts linking Agama project https://maven.jans.io/maven/io/jans/casa/plugins/acct-linking-agama/replace-janssen-version/acct-linking-agama-replace-janssen-version-project.zip Transfer the two zip files to a location in the server, deploy both archives using TUI (Agama menu) Finally restart the authentication server", "title": "Components deployment"}, {"location": "casa/plugins/accts-linking/account-linking-index/#configuration", "text": "The first step is figuring out the external sites to support. Keep in mind only OpenID or OAuth 2.0 based providers can be onboarded. There is not support for SAML IDPs. The procedures for getting configuration settings in order to integrate third party providers vary widely. Here, only basic guidelines are given: If the provider is OpenId-compliant and supports dynamic client registration, obtain the OP URL and the scopes list to use when requesting user profile information. Most of times the scopes openid , profile and email will fit the bill If the provider is OpenId-compliant and does not support dynamic client registration, obtain the OP URL and scopes as in the previous case, and also a client ID and secret If the provider does not support OpenId. Obtain the following: The authorization endpoint URL The token endpoint URL The endpoint URL where profile data can be retrieved Client credentials (ID and secret) Scopes to use when requesting user profile information The steps required to grab the above data vary among providers. Normally this is obtained through a sort of administrative developer GUI tool. If you are prompted for a \"redirect URI\" in such tool, provide https://<your-jans-host>/jans-auth/fl/callback . Now it's time to supply the settings grabbed. The component these configurations are injected to is the Casa accounts linking Agama project. To make the effort easier, this project is bundled with some dummy configuration properties you can use as a template. Proceed as follows: In TUI, open the Agama tab and scroll through the list of projects until the casa-account-linking is highlighted Open the configuration management dialog (press c ) and choose to export the sample configuration to a file on disk Apply changes as needed - this is covered in a separate doc page here . Note you can add or remove sections in the file at will, and that providers can also be disabled so they are not listed in the login page or in Casa app Still in TUI, choose to import the file you have edited For VM-based installations, update the file /etc/default/jans-casa . Locate a segment that reads -Dacr= and assign agama_io.jans.casa.authn.acctlinking as new value. This will make Casa use the flow found in the accounts linking project - not the flow bundled out-of-the-box. Finally restart Casa and conduct your testing. You will now see the login page contains a list of links to the configured identity providers.", "title": "Configuration"}, {"location": "casa/plugins/accts-linking/accts-linking-agama/", "tags": ["Casa", "Accounts Linking", "Agama"], "text": "Accounts linking project configuration # Overview # The accounts linking Agama project must be configured in order to integrate third-party identity providers. The configuration of this project is supplied in a JSON file whose structure is like: { \"io.jans.casa.authn.acctlinking\": { \"providerID_1\": { ... }, \"providerID_2\": { ... }, ... } } Each property part of the JSON object io.jans.casa.auth.acctlinking holds the configuration of a different identity provider. Here's a how a typical configuration of a provider looks like: { \"displayName\": \"Goooogle\", \"flowQname\": \"io.jans.inbound.GenericProvider\", \"mappingClassField\": \"io.jans.casa.acctlinking.Mappings.GOOGLE\", \"oauthParams\": { \"authzEndpoint\": \"https://accounts.google.com/o/oauth2/v2/auth\", \"tokenEndpoint\": \"https://oauth2.googleapis.com/token\", \"userInfoEndpoint\": \"https://www.googleapis.com/oauth2/v3/userinfo\", \"clientId\": \"202403151302\", \"clientSecret\": \"m|a1l2d3i4t5a6S7h8a9k0i'r\u00bfa\", \"scopes\": [\"email\", \"profile\"] } } In this case, we are populating the configuration of an OAuth-based provider called \"Goooogle\". The tables shown in this page list all possible properties to configure a provider. Particularly, two properties deserve the most detail: flowQname . Agama projects are made up of flows - think of small \"web journeys\". This property must contain the name of an existing flow capable of interfacing with the identity provider of interest. Often, there is no need to write such \"interfacing\" flow. The below are ready-to-use and cover most of real-world cases, specifically OpenId/OAuth providers that support the authorization code grant (see section 1.3 of rfc6749 ): io.jans.inbound.GenericProvider . It implements the authorization code flow where the user's browser is taken to the external site. When authentication completes, a code is received at a designated redirect (callback) URL. With such code an access token is obtained as well as user's profile data. This flow supports dynamic client registration io.jans.inbound.Apple . It implements the authorization code flow with some nuances required in order to integrate \"Apple Sign In\" mappingClassField . This is key for performing the attribute mapping process and the user provisioning. The remainder of this document is dedicated to these two aspects Note Recall enabled is a handy property that can be used to temporarily \"deactive\" a given identity provider. Configuring attribute mappings # An introduction to attribute mapping can be found here . Unless an elaborated processing of attributes is required, a basic knowledge of Java language suffices to write a useful mapping. To write a mapping, you can use the samples provided as a guideline (see folder lib/io/jans/casa/acctlinking in the Agama accounts linking project). You can add your mapping in the same file or create a new Java class for this purpose. Then save your changes, re-package (zip) the project, re-deploy, and update (re-import) the configuration if necessary. Specifically, for Casa accounts linking, the mapping must include an attribute named ID . While ID is not part of the Jans database, here it is used to supply what could be understood as the identifier of the user at the external site. For instance, in a social site this may be the username or email. The example below shows how to set ID assuming the username was returned by the external site in an attribute named userId : profile -> { Map<String, Object> map = new HashMap<>(); map.put(\"ID\", profile.get(\"userId\")); ... return map; } In the above example, profile is a Map<String, Object> that holds the attribute-value pairs the third-party identity provider released for this user. For the interested, profile contents are dumped to the server logs (check jans-auth_script.log ) so it is easy to peak into the values. Check for a message in debug level starting with \"Profile data\". Both the ID of identity provider and the ID of the user will end up stored in an auxiliary database attribute. This helps to identify if the incoming user is already known (has been onboarded previously). When the attribute mapping is applied, the uid attribute is set as well. This is the username the incoming user will be assigned in the local Jans database. The uid is automatically generated based on ID unless the mapping already populates the uid directly. The return value of the mapping is a Map<String, Object> . This caters for cases where resulting attributes hold booleans, dates, numbers, strings, etc. When the attribute has to hold multiple values, you can use an array or a Java Collection object, like a List . User provisioning # After attribute mapping occurs, the local database is checked to determine if the incoming user is known (based on the ID in the mapping and the ID of the provider in question). If no match is found, the user is onboarded: a new entry is created in the database using the information found in the resulting mapping. Otherwise, the exact behavior varies depending on the provider configuration as follows: If skipProfileUpdate is set to false , the existing database entry is left untouched, otherwise: If cumulativeUpdate is set to false , the existing attributes in the entry which are part of the mapping are overwritten If cumulativeUpdate is set to true , the existing attribute values in the entry are preserved and new values are added if present in the mapping The updates just referenced apply to the matching entry based on mapping and provider ID, however, when emailLinkingSafe is set to true and the mapping comes with a mail value equal to an existing e-mail in the database, the update is carried over the e-mail matching entry.", "title": "Configuring Agama Project"}, {"location": "casa/plugins/accts-linking/accts-linking-agama/#accounts-linking-project-configuration", "text": "", "title": "Accounts linking project configuration"}, {"location": "casa/plugins/accts-linking/accts-linking-agama/#overview", "text": "The accounts linking Agama project must be configured in order to integrate third-party identity providers. The configuration of this project is supplied in a JSON file whose structure is like: { \"io.jans.casa.authn.acctlinking\": { \"providerID_1\": { ... }, \"providerID_2\": { ... }, ... } } Each property part of the JSON object io.jans.casa.auth.acctlinking holds the configuration of a different identity provider. Here's a how a typical configuration of a provider looks like: { \"displayName\": \"Goooogle\", \"flowQname\": \"io.jans.inbound.GenericProvider\", \"mappingClassField\": \"io.jans.casa.acctlinking.Mappings.GOOGLE\", \"oauthParams\": { \"authzEndpoint\": \"https://accounts.google.com/o/oauth2/v2/auth\", \"tokenEndpoint\": \"https://oauth2.googleapis.com/token\", \"userInfoEndpoint\": \"https://www.googleapis.com/oauth2/v3/userinfo\", \"clientId\": \"202403151302\", \"clientSecret\": \"m|a1l2d3i4t5a6S7h8a9k0i'r\u00bfa\", \"scopes\": [\"email\", \"profile\"] } } In this case, we are populating the configuration of an OAuth-based provider called \"Goooogle\". The tables shown in this page list all possible properties to configure a provider. Particularly, two properties deserve the most detail: flowQname . Agama projects are made up of flows - think of small \"web journeys\". This property must contain the name of an existing flow capable of interfacing with the identity provider of interest. Often, there is no need to write such \"interfacing\" flow. The below are ready-to-use and cover most of real-world cases, specifically OpenId/OAuth providers that support the authorization code grant (see section 1.3 of rfc6749 ): io.jans.inbound.GenericProvider . It implements the authorization code flow where the user's browser is taken to the external site. When authentication completes, a code is received at a designated redirect (callback) URL. With such code an access token is obtained as well as user's profile data. This flow supports dynamic client registration io.jans.inbound.Apple . It implements the authorization code flow with some nuances required in order to integrate \"Apple Sign In\" mappingClassField . This is key for performing the attribute mapping process and the user provisioning. The remainder of this document is dedicated to these two aspects Note Recall enabled is a handy property that can be used to temporarily \"deactive\" a given identity provider.", "title": "Overview"}, {"location": "casa/plugins/accts-linking/accts-linking-agama/#configuring-attribute-mappings", "text": "An introduction to attribute mapping can be found here . Unless an elaborated processing of attributes is required, a basic knowledge of Java language suffices to write a useful mapping. To write a mapping, you can use the samples provided as a guideline (see folder lib/io/jans/casa/acctlinking in the Agama accounts linking project). You can add your mapping in the same file or create a new Java class for this purpose. Then save your changes, re-package (zip) the project, re-deploy, and update (re-import) the configuration if necessary. Specifically, for Casa accounts linking, the mapping must include an attribute named ID . While ID is not part of the Jans database, here it is used to supply what could be understood as the identifier of the user at the external site. For instance, in a social site this may be the username or email. The example below shows how to set ID assuming the username was returned by the external site in an attribute named userId : profile -> { Map<String, Object> map = new HashMap<>(); map.put(\"ID\", profile.get(\"userId\")); ... return map; } In the above example, profile is a Map<String, Object> that holds the attribute-value pairs the third-party identity provider released for this user. For the interested, profile contents are dumped to the server logs (check jans-auth_script.log ) so it is easy to peak into the values. Check for a message in debug level starting with \"Profile data\". Both the ID of identity provider and the ID of the user will end up stored in an auxiliary database attribute. This helps to identify if the incoming user is already known (has been onboarded previously). When the attribute mapping is applied, the uid attribute is set as well. This is the username the incoming user will be assigned in the local Jans database. The uid is automatically generated based on ID unless the mapping already populates the uid directly. The return value of the mapping is a Map<String, Object> . This caters for cases where resulting attributes hold booleans, dates, numbers, strings, etc. When the attribute has to hold multiple values, you can use an array or a Java Collection object, like a List .", "title": "Configuring attribute mappings"}, {"location": "casa/plugins/accts-linking/accts-linking-agama/#user-provisioning", "text": "After attribute mapping occurs, the local database is checked to determine if the incoming user is known (based on the ID in the mapping and the ID of the provider in question). If no match is found, the user is onboarded: a new entry is created in the database using the information found in the resulting mapping. Otherwise, the exact behavior varies depending on the provider configuration as follows: If skipProfileUpdate is set to false , the existing database entry is left untouched, otherwise: If cumulativeUpdate is set to false , the existing attributes in the entry which are part of the mapping are overwritten If cumulativeUpdate is set to true , the existing attribute values in the entry are preserved and new values are added if present in the mapping The updates just referenced apply to the matching entry based on mapping and provider ID, however, when emailLinkingSafe is set to true and the mapping comes with a mail value equal to an existing e-mail in the database, the update is carried over the e-mail matching entry.", "title": "User provisioning"}, {"location": "cedarling/cedarling-authz/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling"], "text": "Authorization Using Cedarling # The Policy Store contains the Cedar Policies, Cedar Schema, and optionally, a list of the Trusted IDPs. The Cedarling loads its Policy Store during initialization as a static JSON file or fetched via HTTPS. In enterprise deployments, the Cedarling can retrieve its Policy Store from a Jans Lock Server OAuth protected endpoint. Developers need to define Cedar Schema that makes sense for their application. For example, a developer writing a customer support application might define an \"Issue\" Resource and Actions like \"Reply\" or \"Close\". Once the schema is defined, developers can author policies to model the fine grain access controls needed to implement the business rules of their application. The easiest way to define schema and policies is to use the AgamaLab Policy Designer. This is a free developer tool hosted by Gluu . The JWTs, Resource, Action, and Context are sent in the authz request. Cedar Pricipals entities are derived from JWT tokens. The OpenID Connect (\"OIDC\") JWTs are joined by the Cedarling to create User and Role entities; the OAuth access token is used to create a Workload entity, which is the software that is acting on behalf of the Person (or autonomously). The Cedarling validates that given its policies, Role, Person and Workload are authorized. If one of Role or Person and Workload is authorized then the request is allowed to proceed. The Cedarling maps \"Roles\" out-of-the-box. In Cedar, Roles are a special kind of Principal. Instead of saying \"User can perform action\", we can say \"Role can perform action\"--a convenient way to implement RBAC. Developers can specify which JWT claim is used to map Cedar Roles. For example, one domain may use the role user claim of the OpenID Userinfo token; another domain may use the memberOf claim in the OIDC id_token. Developers can also express a variety of policies beyond the limitations of RBAC by expressing ABAC conditions, or combining ABAC and RBAC conditions. For example, a policy like Admins can access a \"private\" Resource from the private network, during business hours. In this case \"Admins\" is the role, but the other conditions are ABAC. Policy evaluation is fast because Cedar uses the RBAC role to \"slice\" the data, minimizing the number of entries on which to evaluate the ABAC conditions. The OIDC id_token JWT represents a Person authentication event. The access token JWT represents a Workload authentication event. These tokens contain other interesting contextual data. The id_token tells you who authenticated, when they authenticated, how they authenticatated, and optionally other claims like the User's roles. An OAuth access token can tell you information about the Workload that obtained the JWT, its extent of access as defined by the OAuth Authorization Server ( i.e. the values of the scope claim), or other claims--domains frequently enhance the access token to contain business specific data needed for policy evaluation. The Cedarling authorizes a Person using a certain piece of software, which is called a \"Workload\". From a logical perspective, ( person_allowed AND workload_allowed ) must be True . The JWT's, Action, Resource and Context is sent by the application in the authorization request. For example, this is a sample request from a hypothetical application: const bootstrap_config = {...}; const cedarling = await init ( bootstrap_config ); let input = { \"tokens\" : { \"access_token\" : \"eyJhbGc....\" , \"id_token\" : \"eyJjbGc...\" , \"userinfo_token\" : \"eyJjbGc...\" , }, \"action\" : \"View\" , \"resource\" : { \"id\" : \"ticket-10101\" , \"type\" : \"Ticket\" , \"owner\" : \"bob@acme.com\" , \"org_id\" : \"Acme\" }, \"context\" : { \"ip_address\" : \"54.9.21.201\" , \"network_type\" : \"VPN\" , \"user_agent\" : \"Chrome 125.0.6422.77 (Official Build) (arm64)\" , \"time\" : \"1719266610.98636\" , } } decision_result = await cedarling ( input ) Automatically Adding Entity References to the Context # Cedarling simplifies context creation by automatically including certain entities. This means you don't need to manually pass their references when using them in your policies. The following entities are automatically added to the context. Workload Entity User Entity Resource Entity Access Token Entity ID Token Entity Userinfo Token Entity Example Policy # Below is an example policy schema that illustrates how entities are used: type Context = { \"access_token\": Access_token, \"time\": Long, \"user\": User, \"workload\": Workload }; type Url = { \"host\": String, \"path\": String, \"protocol\": String }; entity Access_token = { \"exp\": Long, \"iss\": TrustedIssuer }; entity Issue = { \"country\": String, \"org_id\": String }; entity Role; entity TrustedIssuer = { \"issuer_entity_id\": Url }; entity User in [Role] = { \"country\": String, \"email\": String, \"sub\": String, \"username\": String }; entity Workload = { \"client_id\": String, \"iss\": TrustedIssuer, \"name\": String, \"org_id\": String }; action \"Update\" appliesTo { principal: [Role, Workload, User], resource: [Issue], context: { \"access_token\": Access_token, \"time\": Long, \"user\": User, \"workload\": Workload } }; action \"View\" appliesTo { principal: [Role, Workload, User], resource: [Issue], context: Context }; With this schema, you only need to provide the fields that are not automatically included. For instance, to define the time in the context: let context = { \"time\" : 1719266610.98636 , }", "title": "Authz"}, {"location": "cedarling/cedarling-authz/#authorization-using-cedarling", "text": "The Policy Store contains the Cedar Policies, Cedar Schema, and optionally, a list of the Trusted IDPs. The Cedarling loads its Policy Store during initialization as a static JSON file or fetched via HTTPS. In enterprise deployments, the Cedarling can retrieve its Policy Store from a Jans Lock Server OAuth protected endpoint. Developers need to define Cedar Schema that makes sense for their application. For example, a developer writing a customer support application might define an \"Issue\" Resource and Actions like \"Reply\" or \"Close\". Once the schema is defined, developers can author policies to model the fine grain access controls needed to implement the business rules of their application. The easiest way to define schema and policies is to use the AgamaLab Policy Designer. This is a free developer tool hosted by Gluu . The JWTs, Resource, Action, and Context are sent in the authz request. Cedar Pricipals entities are derived from JWT tokens. The OpenID Connect (\"OIDC\") JWTs are joined by the Cedarling to create User and Role entities; the OAuth access token is used to create a Workload entity, which is the software that is acting on behalf of the Person (or autonomously). The Cedarling validates that given its policies, Role, Person and Workload are authorized. If one of Role or Person and Workload is authorized then the request is allowed to proceed. The Cedarling maps \"Roles\" out-of-the-box. In Cedar, Roles are a special kind of Principal. Instead of saying \"User can perform action\", we can say \"Role can perform action\"--a convenient way to implement RBAC. Developers can specify which JWT claim is used to map Cedar Roles. For example, one domain may use the role user claim of the OpenID Userinfo token; another domain may use the memberOf claim in the OIDC id_token. Developers can also express a variety of policies beyond the limitations of RBAC by expressing ABAC conditions, or combining ABAC and RBAC conditions. For example, a policy like Admins can access a \"private\" Resource from the private network, during business hours. In this case \"Admins\" is the role, but the other conditions are ABAC. Policy evaluation is fast because Cedar uses the RBAC role to \"slice\" the data, minimizing the number of entries on which to evaluate the ABAC conditions. The OIDC id_token JWT represents a Person authentication event. The access token JWT represents a Workload authentication event. These tokens contain other interesting contextual data. The id_token tells you who authenticated, when they authenticated, how they authenticatated, and optionally other claims like the User's roles. An OAuth access token can tell you information about the Workload that obtained the JWT, its extent of access as defined by the OAuth Authorization Server ( i.e. the values of the scope claim), or other claims--domains frequently enhance the access token to contain business specific data needed for policy evaluation. The Cedarling authorizes a Person using a certain piece of software, which is called a \"Workload\". From a logical perspective, ( person_allowed AND workload_allowed ) must be True . The JWT's, Action, Resource and Context is sent by the application in the authorization request. For example, this is a sample request from a hypothetical application: const bootstrap_config = {...}; const cedarling = await init ( bootstrap_config ); let input = { \"tokens\" : { \"access_token\" : \"eyJhbGc....\" , \"id_token\" : \"eyJjbGc...\" , \"userinfo_token\" : \"eyJjbGc...\" , }, \"action\" : \"View\" , \"resource\" : { \"id\" : \"ticket-10101\" , \"type\" : \"Ticket\" , \"owner\" : \"bob@acme.com\" , \"org_id\" : \"Acme\" }, \"context\" : { \"ip_address\" : \"54.9.21.201\" , \"network_type\" : \"VPN\" , \"user_agent\" : \"Chrome 125.0.6422.77 (Official Build) (arm64)\" , \"time\" : \"1719266610.98636\" , } } decision_result = await cedarling ( input )", "title": "Authorization Using Cedarling"}, {"location": "cedarling/cedarling-authz/#automatically-adding-entity-references-to-the-context", "text": "Cedarling simplifies context creation by automatically including certain entities. This means you don't need to manually pass their references when using them in your policies. The following entities are automatically added to the context. Workload Entity User Entity Resource Entity Access Token Entity ID Token Entity Userinfo Token Entity", "title": "Automatically Adding Entity References to the Context"}, {"location": "cedarling/cedarling-authz/#example-policy", "text": "Below is an example policy schema that illustrates how entities are used: type Context = { \"access_token\": Access_token, \"time\": Long, \"user\": User, \"workload\": Workload }; type Url = { \"host\": String, \"path\": String, \"protocol\": String }; entity Access_token = { \"exp\": Long, \"iss\": TrustedIssuer }; entity Issue = { \"country\": String, \"org_id\": String }; entity Role; entity TrustedIssuer = { \"issuer_entity_id\": Url }; entity User in [Role] = { \"country\": String, \"email\": String, \"sub\": String, \"username\": String }; entity Workload = { \"client_id\": String, \"iss\": TrustedIssuer, \"name\": String, \"org_id\": String }; action \"Update\" appliesTo { principal: [Role, Workload, User], resource: [Issue], context: { \"access_token\": Access_token, \"time\": Long, \"user\": User, \"workload\": Workload } }; action \"View\" appliesTo { principal: [Role, Workload, User], resource: [Issue], context: Context }; With this schema, you only need to provide the fields that are not automatically included. For instance, to define the time in the context: let context = { \"time\" : 1719266610.98636 , }", "title": "Example Policy"}, {"location": "cedarling/cedarling-jwt/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling", "JWT"], "text": "Cedarling JWT Flow # Json Web Token Validation # Note: To enable Json Web Token (JWT) Validation in Cedarling, it is required to populate the trusted_issuers field in the Policy Store . Enabling JWT Signature Validation # Cedarling can validate JWT signatures for enhanced security. To enable this feature, set the CEDARLING_JWT_VALIDATION bootstrap property to True . For development and testing purposes, you can set this property to False and submit an unsigned JWT, such as one generated from JWT.io . Public Key Management # When token validation is enabled, Cedarling downloads the public keys of the Trusted IDPs specified in the policy store during initialization. Cedarling uses the JWT iss claim to select the appropriate keys for validation. JWT Revocation # In enterprise deployments, Cedarling can also check for JWT revocation. This is achieved by following the mechanism described in the OAuth Status Lists draft. Token status enforcement helps mitigate risks associated with account takeover by enabling immediate revocation of all tokens issued to an attacker. Additionally, domains may choose to use Token Status to implement single-use transaction tokens. Summary of JWT Validation Mechanisms # Depending on your bootstrap properties, Cedarling may validate JWTs through the following methods: Validate signatures from Trusted Issuers Check JWT status for revocation Discard id_token if the aud claim does not match the client_id of the access token Discard Userinfo tokens that are not associated with a sub claim from the id_token Verify exp (expiration) and nbf (not before) claims of access tokens and id_tokens, if timestamps are provided in the context", "title": "JWT"}, {"location": "cedarling/cedarling-jwt/#cedarling-jwt-flow", "text": "", "title": "Cedarling JWT Flow"}, {"location": "cedarling/cedarling-jwt/#json-web-token-validation", "text": "Note: To enable Json Web Token (JWT) Validation in Cedarling, it is required to populate the trusted_issuers field in the Policy Store .", "title": "Json Web Token Validation"}, {"location": "cedarling/cedarling-jwt/#enabling-jwt-signature-validation", "text": "Cedarling can validate JWT signatures for enhanced security. To enable this feature, set the CEDARLING_JWT_VALIDATION bootstrap property to True . For development and testing purposes, you can set this property to False and submit an unsigned JWT, such as one generated from JWT.io .", "title": "Enabling JWT Signature Validation"}, {"location": "cedarling/cedarling-jwt/#public-key-management", "text": "When token validation is enabled, Cedarling downloads the public keys of the Trusted IDPs specified in the policy store during initialization. Cedarling uses the JWT iss claim to select the appropriate keys for validation.", "title": "Public Key Management"}, {"location": "cedarling/cedarling-jwt/#jwt-revocation", "text": "In enterprise deployments, Cedarling can also check for JWT revocation. This is achieved by following the mechanism described in the OAuth Status Lists draft. Token status enforcement helps mitigate risks associated with account takeover by enabling immediate revocation of all tokens issued to an attacker. Additionally, domains may choose to use Token Status to implement single-use transaction tokens.", "title": "JWT Revocation"}, {"location": "cedarling/cedarling-jwt/#summary-of-jwt-validation-mechanisms", "text": "Depending on your bootstrap properties, Cedarling may validate JWTs through the following methods: Validate signatures from Trusted Issuers Check JWT status for revocation Discard id_token if the aud claim does not match the client_id of the access token Discard Userinfo tokens that are not associated with a sub claim from the id_token Verify exp (expiration) and nbf (not before) claims of access tokens and id_tokens, if timestamps are provided in the context", "title": "Summary of JWT Validation Mechanisms"}, {"location": "cedarling/cedarling-logs/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling", "logging", "audit"], "text": "Cedarling Logs # Cedarling Audit Logs # The Cedarling logs contains a record of all a Cedarling's decisions and token validations. Cedarling has four logging options, which are configurable via the CEDARLING_LOG_TYPE bootstrap property: off - no logging memory - logs stored in Cedarling in-memory KV store, fetched by client via logging interface. This is ideal for batching logs without impeding authz performance std_out - write logs synchronously to std_out lock - periodically POST logs to Jans Lock Server /audit endpoint for central archiving. There are three different log records produced by the Cedarling: Decision - The result and diagnostics of an authz decision System - Startup, debug and other Cedarling messages not related to authz Metric - Performance and usage data System Log Levels # This is set by CEDARLING_LOG_LEVEL FATAL : Indicates very severe error events that will likely lead the application to abort. These are the most critical issues. ERROR : Designates error events that might still allow the application to continue running but indicate a significant problem. WARN : Designates potentially harmful situations that should be addressed to prevent future issues. INFO : Provides informational messages that highlight the progress of the application at a coarse-grained level. DEBUG : Designates fine-grained informational events useful for debugging the application. TRACE : Provides finer-grained informational events than DEBUG. It is often used for detailed tracing of program execution. Jans Lock Server # In enterprise deployments, Janssen Lock Server collects Cedarling logs and can stream to a database or S3 bucket. The Cedarling decision logs provide compliance evidence of usage of the domain's externalized policies. The logs are also useful for forensic analysis to show everything the attacker attempted, both allowed and denied. Sample logs # The JSON in this document is formatted for readability but is not prettified in the actual implementation. Startup Message # { \"request_id\" : \"0193b8a8-efc0-77ce-bd90-4a62a2998462\" , \"timestamp\" : \"2024-12-12T04:18:19.456Z\" , \"log_kind\" : \"System\" , \"pdp_id\" : \"d47e245e-beaa-4ea4-b899-b8184cd3eb7e\" , \"level\" : \"DEBUG\" , \"msg\" : \"configuration parsed successfully\" } { \"request_id\" : \"0193b8a8-efc1-7e42-9678-b2480268b91f\" , \"timestamp\" : \"2024-12-12T04:18:19.457Z\" , \"log_kind\" : \"System\" , \"pdp_id\" : \"d47e245e-beaa-4ea4-b899-b8184cd3eb7e\" , \"level\" : \"INFO\" , \"msg\" : \"Cedarling Authz initialized successfully\" , \"application_id\" : \"My App\" , \"cedar_lang_version\" : \"4.1.0\" , \"cedar_sdk_version\" : \"4.2.2\" } Decision Log # Example of decision log. { \"request_id\" : \"019394db-f52b-7b06-88b8-a288670a32c2\" , \"timestamp\" : \"2024-12-05T05:27:43.403Z\" , \"log_type\" : \"Decision\" , \"pdp_id\" : \"9e189c4b-96ae-4818-8e7f-75a42186af15\" , \"policystore_id\" : \"a1bf93115de86de760ee0bea1d529b521489e5a11747\" , \"policystore_version\" : \"undefined\" , \"principal\" : \"User & Workload\" , \"User\" : { \"username\" : \"admin@gluu.org\" }, \"Workload\" : { \"org_id\" : \"some_long_id\" }, \"diagnostics\" : { \"reason\" : [ { \"id\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"policy for user\" } ], \"errors\" : [] }, \"lock_client_id\" : null , \"action\" : \"Jans::Action::\\\"Update\\\"\" , \"resource\" : \"Jans::Issue::\\\"random_id\\\"\" , \"decision\" : \"ALLOW\" , \"tokens\" : { \"id_token\" : { \"jti\" : \"id_tkn_jti\" }, \"Userinfo\" : { \"jti\" : \"usrinfo_tkn_jti\" }, \"access\" : { \"jti\" : \"access_tkn_jti\" } }, \"decision_time_ms\" : 3 } Field Definitions # request_id : unique identifier for the decision request timestamp : Derived if possible from the system or context--may be empty in cases where WASM can't access the system clock, and the time wasn't sent in the context. pdp_id : unique identifier for the Cedarling policystore_id : What policystore this Cedarling instance is using policystore_version : What version of the policystore the Cedarling is using principal : User | Workload User : A list of claims, specified by the CEDARLING_DECISION_LOG_USER_CLAIMS property, that must be present in the Cedar User entity Workload : A list of claims, specified by the CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS property, that must be present in the Cedar Workload entity lock_client_id : If this Cedarling has registered with a Lock Server, what is the client_id it received action : From the request resource : From the Request decision : ALLOW or DENY tokens : Dictionary with the token type and claims which should be included in the log decision_time_ms : how long the decision took Debug Log Sample # The result of the authorization is quite extensive because we log all cedar-policy entity information for forensic analysis. We cannot truncate the data, as it may contain critical information. { \"id\" : \"01937015-4649-7aad-8df8-4976e4bd8565\" , \"time\" : 1732752262 , \"log_type\" : \"Decision\" , \"level\" : \"DEBUG\" , \"pdp_id\" : \"75f0dc93-0a90-4076-95fa-dc16d3f00375\" , \"msg\" : \"Result of authorize.\" , \"application_id\" : \"TestApp\" , \"action\" : \"Jans::Action::\\\"Read\\\"\" , \"resource\" : \"Jans::Application::\\\"some_id\\\"\" , \"context\" : { \"user_agent\" : \"Linux\" , \"operating_system\" : \"Linux\" , \"network_type\" : \"Local\" , \"network\" : \"127.0.0.1\" , \"geolocation\" : [ \"America\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"device_health\" : [ \"Healthy\" ], \"current_time\" : 1732752262 }, \"entities\" : [ { \"uid\" : { \"type\" : \"Jans::User\" , \"id\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" }, \"attrs\" : { \"sub\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" , \"role\" : [ \"CasaAdmin\" ], \"email\" : { \"domain\" : \"jans.test\" , \"uid\" : \"admin\" } }, \"parents\" : [ { \"type\" : \"Jans::Role\" , \"id\" : \"CasaAdmin\" } ] }, { \"uid\" : { \"type\" : \"Jans::id_token\" , \"id\" : \"ijLZO1ooRyWrgIn7cIdNyA\" }, \"attrs\" : { \"sub\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" , \"acr\" : \"simple_password_auth\" , \"exp\" : 1731956630 , \"jti\" : \"ijLZO1ooRyWrgIn7cIdNyA\" , \"amr\" : [], \"aud\" : \"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\" , \"iss\" : { \"__entity\" : { \"type\" : \"Jans::TrustedIssuer\" , \"id\" : \"https://account.gluu.org\" } }, \"iat\" : 1731953030 }, \"parents\" : [] }, ... { \"uid\" : { \"type\" : \"Jans::Action\" , \"id\" : \"Tag\" }, \"attrs\" : {}, \"parents\" : [] } ], \"person_principal\" : \"Jans::User::\\\"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\\\"\" , \"person_diagnostics\" : { \"reason\" : [ { \"id\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"simple policy example for principal user\" } ], \"errors\" : [] }, \"person_decision\" : \"ALLOW\" , \"workload_principal\" : \"Jans::Workload::\\\"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\\\"\" , \"workload_diagnostics\" : { \"reason\" : [ { \"id\" : \"444da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"simple policy example for principal workload\" } ], \"errors\" : [] }, \"workload_decision\" : \"ALLOW\" , \"authorized\" : true }", "title": "Logs"}, {"location": "cedarling/cedarling-logs/#cedarling-logs", "text": "", "title": "Cedarling Logs"}, {"location": "cedarling/cedarling-logs/#cedarling-audit-logs", "text": "The Cedarling logs contains a record of all a Cedarling's decisions and token validations. Cedarling has four logging options, which are configurable via the CEDARLING_LOG_TYPE bootstrap property: off - no logging memory - logs stored in Cedarling in-memory KV store, fetched by client via logging interface. This is ideal for batching logs without impeding authz performance std_out - write logs synchronously to std_out lock - periodically POST logs to Jans Lock Server /audit endpoint for central archiving. There are three different log records produced by the Cedarling: Decision - The result and diagnostics of an authz decision System - Startup, debug and other Cedarling messages not related to authz Metric - Performance and usage data", "title": "Cedarling Audit Logs"}, {"location": "cedarling/cedarling-logs/#system-log-levels", "text": "This is set by CEDARLING_LOG_LEVEL FATAL : Indicates very severe error events that will likely lead the application to abort. These are the most critical issues. ERROR : Designates error events that might still allow the application to continue running but indicate a significant problem. WARN : Designates potentially harmful situations that should be addressed to prevent future issues. INFO : Provides informational messages that highlight the progress of the application at a coarse-grained level. DEBUG : Designates fine-grained informational events useful for debugging the application. TRACE : Provides finer-grained informational events than DEBUG. It is often used for detailed tracing of program execution.", "title": "System Log Levels"}, {"location": "cedarling/cedarling-logs/#jans-lock-server", "text": "In enterprise deployments, Janssen Lock Server collects Cedarling logs and can stream to a database or S3 bucket. The Cedarling decision logs provide compliance evidence of usage of the domain's externalized policies. The logs are also useful for forensic analysis to show everything the attacker attempted, both allowed and denied.", "title": "Jans Lock Server"}, {"location": "cedarling/cedarling-logs/#sample-logs", "text": "The JSON in this document is formatted for readability but is not prettified in the actual implementation.", "title": "Sample logs"}, {"location": "cedarling/cedarling-logs/#startup-message", "text": "{ \"request_id\" : \"0193b8a8-efc0-77ce-bd90-4a62a2998462\" , \"timestamp\" : \"2024-12-12T04:18:19.456Z\" , \"log_kind\" : \"System\" , \"pdp_id\" : \"d47e245e-beaa-4ea4-b899-b8184cd3eb7e\" , \"level\" : \"DEBUG\" , \"msg\" : \"configuration parsed successfully\" } { \"request_id\" : \"0193b8a8-efc1-7e42-9678-b2480268b91f\" , \"timestamp\" : \"2024-12-12T04:18:19.457Z\" , \"log_kind\" : \"System\" , \"pdp_id\" : \"d47e245e-beaa-4ea4-b899-b8184cd3eb7e\" , \"level\" : \"INFO\" , \"msg\" : \"Cedarling Authz initialized successfully\" , \"application_id\" : \"My App\" , \"cedar_lang_version\" : \"4.1.0\" , \"cedar_sdk_version\" : \"4.2.2\" }", "title": "Startup Message"}, {"location": "cedarling/cedarling-logs/#decision-log", "text": "Example of decision log. { \"request_id\" : \"019394db-f52b-7b06-88b8-a288670a32c2\" , \"timestamp\" : \"2024-12-05T05:27:43.403Z\" , \"log_type\" : \"Decision\" , \"pdp_id\" : \"9e189c4b-96ae-4818-8e7f-75a42186af15\" , \"policystore_id\" : \"a1bf93115de86de760ee0bea1d529b521489e5a11747\" , \"policystore_version\" : \"undefined\" , \"principal\" : \"User & Workload\" , \"User\" : { \"username\" : \"admin@gluu.org\" }, \"Workload\" : { \"org_id\" : \"some_long_id\" }, \"diagnostics\" : { \"reason\" : [ { \"id\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"policy for user\" } ], \"errors\" : [] }, \"lock_client_id\" : null , \"action\" : \"Jans::Action::\\\"Update\\\"\" , \"resource\" : \"Jans::Issue::\\\"random_id\\\"\" , \"decision\" : \"ALLOW\" , \"tokens\" : { \"id_token\" : { \"jti\" : \"id_tkn_jti\" }, \"Userinfo\" : { \"jti\" : \"usrinfo_tkn_jti\" }, \"access\" : { \"jti\" : \"access_tkn_jti\" } }, \"decision_time_ms\" : 3 }", "title": "Decision Log"}, {"location": "cedarling/cedarling-logs/#field-definitions", "text": "request_id : unique identifier for the decision request timestamp : Derived if possible from the system or context--may be empty in cases where WASM can't access the system clock, and the time wasn't sent in the context. pdp_id : unique identifier for the Cedarling policystore_id : What policystore this Cedarling instance is using policystore_version : What version of the policystore the Cedarling is using principal : User | Workload User : A list of claims, specified by the CEDARLING_DECISION_LOG_USER_CLAIMS property, that must be present in the Cedar User entity Workload : A list of claims, specified by the CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS property, that must be present in the Cedar Workload entity lock_client_id : If this Cedarling has registered with a Lock Server, what is the client_id it received action : From the request resource : From the Request decision : ALLOW or DENY tokens : Dictionary with the token type and claims which should be included in the log decision_time_ms : how long the decision took", "title": "Field Definitions"}, {"location": "cedarling/cedarling-logs/#debug-log-sample", "text": "The result of the authorization is quite extensive because we log all cedar-policy entity information for forensic analysis. We cannot truncate the data, as it may contain critical information. { \"id\" : \"01937015-4649-7aad-8df8-4976e4bd8565\" , \"time\" : 1732752262 , \"log_type\" : \"Decision\" , \"level\" : \"DEBUG\" , \"pdp_id\" : \"75f0dc93-0a90-4076-95fa-dc16d3f00375\" , \"msg\" : \"Result of authorize.\" , \"application_id\" : \"TestApp\" , \"action\" : \"Jans::Action::\\\"Read\\\"\" , \"resource\" : \"Jans::Application::\\\"some_id\\\"\" , \"context\" : { \"user_agent\" : \"Linux\" , \"operating_system\" : \"Linux\" , \"network_type\" : \"Local\" , \"network\" : \"127.0.0.1\" , \"geolocation\" : [ \"America\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"device_health\" : [ \"Healthy\" ], \"current_time\" : 1732752262 }, \"entities\" : [ { \"uid\" : { \"type\" : \"Jans::User\" , \"id\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" }, \"attrs\" : { \"sub\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" , \"role\" : [ \"CasaAdmin\" ], \"email\" : { \"domain\" : \"jans.test\" , \"uid\" : \"admin\" } }, \"parents\" : [ { \"type\" : \"Jans::Role\" , \"id\" : \"CasaAdmin\" } ] }, { \"uid\" : { \"type\" : \"Jans::id_token\" , \"id\" : \"ijLZO1ooRyWrgIn7cIdNyA\" }, \"attrs\" : { \"sub\" : \"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\" , \"acr\" : \"simple_password_auth\" , \"exp\" : 1731956630 , \"jti\" : \"ijLZO1ooRyWrgIn7cIdNyA\" , \"amr\" : [], \"aud\" : \"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\" , \"iss\" : { \"__entity\" : { \"type\" : \"Jans::TrustedIssuer\" , \"id\" : \"https://account.gluu.org\" } }, \"iat\" : 1731953030 }, \"parents\" : [] }, ... { \"uid\" : { \"type\" : \"Jans::Action\" , \"id\" : \"Tag\" }, \"attrs\" : {}, \"parents\" : [] } ], \"person_principal\" : \"Jans::User::\\\"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\\\"\" , \"person_diagnostics\" : { \"reason\" : [ { \"id\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"simple policy example for principal user\" } ], \"errors\" : [] }, \"person_decision\" : \"ALLOW\" , \"workload_principal\" : \"Jans::Workload::\\\"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\\\"\" , \"workload_diagnostics\" : { \"reason\" : [ { \"id\" : \"444da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"description\" : \"simple policy example for principal workload\" } ], \"errors\" : [] }, \"workload_decision\" : \"ALLOW\" , \"authorized\" : true }", "title": "Debug Log Sample"}, {"location": "cedarling/cedarling-overview/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling"], "text": "Cedarling Overview # What is Cedar # Cedar is a policy syntax invented by Amazon and used by their Verified Permission service. Cedar policies enable developers to implement fine-grain access control and externalize policies. To learn more about why the design of Cedar is intuitive , fast and safe , read this article or watch this video Cedar uses the PARC syntax: P rincipal A ction R esource C ontext For example, you may have a policy that says Admins can write to the /config folder. The Admin role is the Principal, write is the Action, and the /config folder is the Resource. The Context is used to specify information about the enivironment, like the time of day or network address. Fine grain access control makes sense in both the frontend and backend. In the frontend, mastery of authz can help developers build better UX. For example, why display form fields a user is not authorized to see? In the backend, fine grain policies are necessary for a zero trust architecture. What is the Cedarling # Architecturally, the Cedarling is an embeddable stateful Policy Decision Point, or \"PDP\". It is stateful because it implements an in-memory cache which makes it possible to batch logs and implement other performance optimizations. The Cedarling is written in Rust with bindings to WASM, iOS, Android, and Python--this makes it possible for web, mobile, and cloud developers to incorporate the Cedarling into their applications. The Cedarling is used for both frontend and backend security. Because the frontend is more constrained with regard to memory and compute, this requirement was critical to the design. For example, in the backend, a PDP could run in a Linux container. But in the frontend, the Cedarling must run in a browser, using the browser WASM engine. How does the Cedarling get the data to calculate a decision? The Principal data is contained in the JWTs--a person, a workload, or both. The Action, Resource and Context are sent by the application as arguments in the authz request. The Cedarling is fast because it has all the data it needs to make a local decision. No cloud round-trips are needed to return an authz decision--a cloud roundtrip may kill the performance of a frontend application. The Cedarling can execute many requests in less then 1ms--this is critical for UX fine grain authorization. Below is a conceptual diagram showing how you can archiect the Cedarling for frontend and backend security. The Cedarling is used to determine if the Mobile Application should be allowed to register. For example, perhaps the IDP wants to execute a policy that restricts registration to mobile applications that present a Google Integrity API attestation to indicate the checksum of the binary has not changed, and that the phone is not rooted. The Cedarling is used to authenticate the person using the mobile application, i.e. the \"User\". For example, perhaps the IDP wants to execute a policy that says that 2FA is required from a non trusted network. The Cedarling is used to determine which scopes to add to the OAuth access token. For example, perhaps if the mobile application presents a software statement assertion JWT (i.e. and \"SSA\") issued by the IDP, the application may request the financial scope. Once JWT tokens are issued by the IDP, the frontend can use these tokens to evaluate local policies. For example, perhaps the mobile application only allows access to certain features if the Userinfo JWT contains a role claim for a \"Manager\". The mobile application may send an OAuth access token to call an API. This API Gateway may route this request to a backend service, but only after evaluating certain security policies. For example, perhaps the Action POST is only allowed on a Resource (e.g. \"URI\") when the access token JWT contains a certain scope. Finally, the Backend API can use the Cedarling to perform its own fine grain authorization. For example, perhaps the Backend only allows transaction greater than $10,000 if the access token contains scope value high-net-worth . This is just a hypothetical example, but hopefully you can see how the Cedarling is used to achieve multilayer security. Each Cedarling has it's own specific policy store. The API Gateway Cedarling instance does not need to know the policies or schema for the mobile application. By layering security, you can implement a zero trust architecture. Cedarling Interfaces # The developer using the Cedarling to build an application uses three easy interfaces: (\" init \"), authorization (\" authz \") and logging (\" log \"). Developers call the init interface on startup of their application, causing the Cedarling to read its bootstrap properties and load its policy store . If configured, the Cedarling will also retrieve the most recent IDP public keys and request JWT status updates. The authz interface provides the main functionality of the Cedarling: to authorize a PARC request from the application by mapping the data sent in the request, and evaluating it with the embedded Rust Cedar Engine . The authz interface answers the question: \"Is this action, on this resource, given this context, allowed with these JWTs?\". The Cedarling returns the decion-- allow or deny . If denied, the Cedarling returns \"diagnostics\"--additional context if the decision is denied. During authz , the Cedarling can perform two more important jobs: (1) validate JWT tokens; (2) log the resulting decision. The log interface enables developers to retrieve decision and system logs from the Cedarling's in-memory cache. See the Cedarling log documentation for more information. Cedarling Components # As a developer, you don't really need to understand how the Cedarling is constructed. But this section is meant to give you an idea to help you get a better understand of what it's actually doing. The following diagram is a very high level picture: Cedar Engine is the latest code released from the open source Rust Cedar project. Thanks Amazon for supporting this fabulous technology! SparKV is an in-memory key-value store that support automatic expiration of data. For example, we don't want to store logs for more then a few minutes. The Cedarling is a stateful PDP, but of course it doesn't write anything to disk. The state is stored entirely in Memory, and SparKV provides an easy way to do this. Init, Authz, and Log Engines perform actions similar to those described in the interfaces above. JWT Engine is used to validate JWT signatures and to check the status of a JWT token. Lock Engine is used for enterprise deployments, where the Cedarling is one of many instances, and it needs to pick up its Policy Store from a trusted source and send to store its logs centrally, for example in a SIEM. So you can see that the Cedar Engine is central to the functionality of the Cedarling. However, the other helper engines make it easier for developer to use Cedar for application security when they are using JWT tokens as the source of Person and Workload identity.", "title": "Overview"}, {"location": "cedarling/cedarling-overview/#cedarling-overview", "text": "", "title": "Cedarling Overview"}, {"location": "cedarling/cedarling-overview/#what-is-cedar", "text": "Cedar is a policy syntax invented by Amazon and used by their Verified Permission service. Cedar policies enable developers to implement fine-grain access control and externalize policies. To learn more about why the design of Cedar is intuitive , fast and safe , read this article or watch this video Cedar uses the PARC syntax: P rincipal A ction R esource C ontext For example, you may have a policy that says Admins can write to the /config folder. The Admin role is the Principal, write is the Action, and the /config folder is the Resource. The Context is used to specify information about the enivironment, like the time of day or network address. Fine grain access control makes sense in both the frontend and backend. In the frontend, mastery of authz can help developers build better UX. For example, why display form fields a user is not authorized to see? In the backend, fine grain policies are necessary for a zero trust architecture.", "title": "What is Cedar"}, {"location": "cedarling/cedarling-overview/#what-is-the-cedarling", "text": "Architecturally, the Cedarling is an embeddable stateful Policy Decision Point, or \"PDP\". It is stateful because it implements an in-memory cache which makes it possible to batch logs and implement other performance optimizations. The Cedarling is written in Rust with bindings to WASM, iOS, Android, and Python--this makes it possible for web, mobile, and cloud developers to incorporate the Cedarling into their applications. The Cedarling is used for both frontend and backend security. Because the frontend is more constrained with regard to memory and compute, this requirement was critical to the design. For example, in the backend, a PDP could run in a Linux container. But in the frontend, the Cedarling must run in a browser, using the browser WASM engine. How does the Cedarling get the data to calculate a decision? The Principal data is contained in the JWTs--a person, a workload, or both. The Action, Resource and Context are sent by the application as arguments in the authz request. The Cedarling is fast because it has all the data it needs to make a local decision. No cloud round-trips are needed to return an authz decision--a cloud roundtrip may kill the performance of a frontend application. The Cedarling can execute many requests in less then 1ms--this is critical for UX fine grain authorization. Below is a conceptual diagram showing how you can archiect the Cedarling for frontend and backend security. The Cedarling is used to determine if the Mobile Application should be allowed to register. For example, perhaps the IDP wants to execute a policy that restricts registration to mobile applications that present a Google Integrity API attestation to indicate the checksum of the binary has not changed, and that the phone is not rooted. The Cedarling is used to authenticate the person using the mobile application, i.e. the \"User\". For example, perhaps the IDP wants to execute a policy that says that 2FA is required from a non trusted network. The Cedarling is used to determine which scopes to add to the OAuth access token. For example, perhaps if the mobile application presents a software statement assertion JWT (i.e. and \"SSA\") issued by the IDP, the application may request the financial scope. Once JWT tokens are issued by the IDP, the frontend can use these tokens to evaluate local policies. For example, perhaps the mobile application only allows access to certain features if the Userinfo JWT contains a role claim for a \"Manager\". The mobile application may send an OAuth access token to call an API. This API Gateway may route this request to a backend service, but only after evaluating certain security policies. For example, perhaps the Action POST is only allowed on a Resource (e.g. \"URI\") when the access token JWT contains a certain scope. Finally, the Backend API can use the Cedarling to perform its own fine grain authorization. For example, perhaps the Backend only allows transaction greater than $10,000 if the access token contains scope value high-net-worth . This is just a hypothetical example, but hopefully you can see how the Cedarling is used to achieve multilayer security. Each Cedarling has it's own specific policy store. The API Gateway Cedarling instance does not need to know the policies or schema for the mobile application. By layering security, you can implement a zero trust architecture.", "title": "What is the Cedarling"}, {"location": "cedarling/cedarling-overview/#cedarling-interfaces", "text": "The developer using the Cedarling to build an application uses three easy interfaces: (\" init \"), authorization (\" authz \") and logging (\" log \"). Developers call the init interface on startup of their application, causing the Cedarling to read its bootstrap properties and load its policy store . If configured, the Cedarling will also retrieve the most recent IDP public keys and request JWT status updates. The authz interface provides the main functionality of the Cedarling: to authorize a PARC request from the application by mapping the data sent in the request, and evaluating it with the embedded Rust Cedar Engine . The authz interface answers the question: \"Is this action, on this resource, given this context, allowed with these JWTs?\". The Cedarling returns the decion-- allow or deny . If denied, the Cedarling returns \"diagnostics\"--additional context if the decision is denied. During authz , the Cedarling can perform two more important jobs: (1) validate JWT tokens; (2) log the resulting decision. The log interface enables developers to retrieve decision and system logs from the Cedarling's in-memory cache. See the Cedarling log documentation for more information.", "title": "Cedarling Interfaces"}, {"location": "cedarling/cedarling-overview/#cedarling-components", "text": "As a developer, you don't really need to understand how the Cedarling is constructed. But this section is meant to give you an idea to help you get a better understand of what it's actually doing. The following diagram is a very high level picture: Cedar Engine is the latest code released from the open source Rust Cedar project. Thanks Amazon for supporting this fabulous technology! SparKV is an in-memory key-value store that support automatic expiration of data. For example, we don't want to store logs for more then a few minutes. The Cedarling is a stateful PDP, but of course it doesn't write anything to disk. The state is stored entirely in Memory, and SparKV provides an easy way to do this. Init, Authz, and Log Engines perform actions similar to those described in the interfaces above. JWT Engine is used to validate JWT signatures and to check the status of a JWT token. Lock Engine is used for enterprise deployments, where the Cedarling is one of many instances, and it needs to pick up its Policy Store from a trusted source and send to store its logs centrally, for example in a SIEM. So you can see that the Cedar Engine is central to the functionality of the Cedarling. However, the other helper engines make it easier for developer to use Cedar for application security when they are using JWT tokens as the source of Person and Workload identity.", "title": "Cedarling Components"}, {"location": "cedarling/cedarling-policy-store/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling", "policy store"], "text": "Cedarling Policy Store # The Cedarling Policy Store uses a JSON file named cedarling_store.json to store all necessary data for evaluating policies and verifying JWT tokens. The structure includes the following key components: Cedar Schema : The Cedar schema encoded in Base64. Cedar Policies : The Cedar policies encoded in Base64. Trusted Issuers : Details about the trusted issuers (see below for syntax). Note: The cedarling_store.json file is only needed if the bootstrap properties: CEDARLING_LOCK ; CEDARLING_POLICY_STORE_URI ; and CEDARLING_POLICY_STORE_ID are not set to a local location. If you're fetching the policies remotely, you don't need a cedarling_store.json file. JSON Schema # The JSON Schema accepted by cedarling is defined as follows: { \"cedar_version\" : \"v4.0.0\" , \"policy_stores\" : { \"some_unique_string_id\" : { \"name\" : \"TestPolicy\" , \"description\" : \"Once upon a time there was a Policy, that lived in a Store.\" , \"policies\" : { ... }, \"schema\" : { ... }, \"trusted_issuers\" : { ... } } } } cedar_version : ( String ) The version of Cedar policy . The protocols of this version will be followed when processing Cedar schema and policies. policies : ( Object ) Object containing one or more policy IDs as keys, with their corresponding objects as values. See: policies schema . schema : ( String | Object ) The Cedar Schema. See schema below. trusted_issuers : ( Object of {unique_id => IdentitySource}(#trusted-issuer-schema) ) List of metadata for Identity Sources. schema # Either String or Object , where Object is preferred. Where Object - An object with encoding , content_type and body keys. For example: \"schema\" : { \"encoding\" : \"none\" , // can be one of \"none\" or \"base64\" \"content_type\" : \"cedar\" , // can be one of \"cedar\" or \"cedar-json\" \"body\" : \"namespace Jans {\\ntype Url = {\" hos t \": String, \" pa t h \": String, \" pro t ocol \": String};...\" } Where String - The schema in cedar-json format, encoded as Base64. For example: \"schema\" : \"cGVybWl0KAogICAgc...\" Cedar Policies Schema # The policies field describes the Cedar policies that will be used in Cedarling. Multiple policies can be defined, with each policy requiring a unique_policy_id . \"policies\" : { \"unique_policy_id\" : { \"cedar_version\" : \"v4.0.0\" , \"name\" : \"Policy for Unique Id\" , \"description\" : \"simple policy example\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : { ... }, }, ... } unique_policy_id : ( String ) A uniqe policy ID used to for tracking and auditing purposes. name : ( String ) A name for the policy description : ( String ) A brief description of cedar policy creation_date : ( String ) Policy creating date in YYYY-MM-DDTHH:MM:SS.ssssss policy_content : ( String | Object ) The Cedar Policy. See policy_content below. policy_content # Either String or Object , where Object is preferred. Where Object - An object with encoding , content_type and body keys. For example: \"policy_content\" : { \"encoding\" : \"none\" , // can be one of \"none\" or \"base64\" \"content_type\" : \"cedar\" , // ONLY \"cedar\" for now due to limitations in cedar-policy crate \"body\" : \"permit(\\n principal is Jans::User,\\n action in [Jans::Action::\\\"Update\\\"],\\n resource is Jans::Issue\\n)when{\\n principal.country == resource.country\\n};\" } Where String - The policy in cedar format, encoded as Base64. For example: \"policy_content\" : \"cGVybWl0KAogICAgc...\" Example of policies # Here is a non-normative example of the policies field: \"policies\" : { \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-first\" , \"description\" : \"simple policy example for principal workload\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : \"cGVybWl0KAogICAgc...\" }, \"0fo1kl928Afa0sc9123scma0123891asklajsh1233ab\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-second\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : \"kJW1bWl0KA0g3CAxa...\" }, \"1fo1kl928Afa0sc9123scma0123891asklajsh1233ac\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-third\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : { \"encoding\" : \"none\" , \"content_type\" : \"cedar\" , \"body\" : \"permit(...) where {...}\" } }, \"2fo1kl928Afa0sc9123scma0123891asklajsh1233ad\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-fourth\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : { \"encoding\" : \"base64\" , \"content_type\" : \"cedar\" , \"body\" : \"kJW1bWl0KA0g3CAxa...\" } }, ... } Trusted Issuers Schema # This record contains the information needed to validate tokens from this issuer: \"identity_source\" : { \"some_unique_id\" : { \"name\" : \"name_of_the_trusted_issuer\" , \"description\" : \"description for the trusted issuer\" , \"openid_configuration_endpoint\" : \"https://<trusted-issuer-hostname>/.well-known/openid-configuration\" , \"access_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"jti\" , ... }, \"id_tokens\" : { ... }, \"userinfo_tokens\" : { ... }, \"tx_tokens\" : { ... }, } ... } name : ( String ) The name of the trusted issuer. description : ( String ) A brief description of the trusted issuer, providing context for administrators. openid_configuration_endpoint : ( String ) The HTTPS URL for the OpenID Connect configuration endpoint (usually found at /.well-known/openid-configuration ). identity_source : ( Object , optional ) Metadata related to the tokens issued by this issuer. Notes : The access_tokens , id_tokens , userinfo_tokens , and tx_tokens fields will follow the Token Metadata Schema . The access_tokens will contain a trusted and principal_identifier field in addition to the fields from the Token Metadata Schema . Token Metadata Schema # The Token Entity Metadata Schema defines how tokens are mapped, parsed, and transformed within Cedarling. It allows you to specify how to extract user IDs, roles, and other claims from a token using customizable parsers. { \"user_id\" : \"<field name in token (e.g., 'email', 'sub', 'uid', etc.) or '' if not used>\" , \"role_mapping\" : \"<field for role assignment (e.g., 'role', 'memberOf', etc.) or '' if not used>\" , \"claim_mapping\" : { \"mapping_target\" : { \"parser\" : \"<type of parser ('regex' or 'json')>\" , \"type\" : \"<type identifier (e.g., 'Acme::Email')>\" , \"...\" : \"Additional configurations specific to the parser\" }, }, } Role mapping # role_mapping : (String OR Array of String, Optional ) Indicates which field in the token should be used for role-based access control. If not needed, set to an empty string ( \"\" ). You can include a role_mapping in each token, all of them will be executed by Cedarling. If none role_mapping defined the Cedarling will try to find role in userinfo token in field role . Claim mapping # claim_mapping: Defines how to extract and transform specific claims from the token. Each claim can have its own parser ( regex or json ) and type ( Acme::email_address , Acme::Url , etc.). In regex attribute mapping like \"UID\": {\"attr\": \"uid\", \"type\":\"String\"}, , type field can contain possible variants: String - to string without transformation, Number - parse string to float64 (JSON number) if error returns default value Boolean - if string NOT empty map to true else false Note, use of regex named capture groups which is more readable by referring to parts of a regex match by descriptive names rather than numbers. For example, (?P<name>...) defines a named capture group where name is the identifier, and ... is the regex pattern for what you want to capture. When you use (?x) modifier in regexp, ensure that you escaped character # => \\# . example of mapping email_address and Url : ... \"claim_mapping\" : { \"email\" : { \"parser\" : \"regex\" , \"type\" : \"Test::email_address\" , \"regex_expression\" : \"^(?P<UID>[^@]+)@(?P<DOMAIN>.+)$\" , \"UID\" : { \"attr\" : \"uid\" , \"type\" : \"String\" }, \"DOMAIN\" : { \"attr\" : \"domain\" , \"type\" : \"String\" } }, \"profile\" : { \"parser\" : \"regex\" , \"type\" : \"Test::Url\" , \"regex_expression\" : \"(?x) ^(?P<SCHEME>[a-zA-Z][a-zA-Z0-9+.-]*):\\\\/\\\\/(?P<HOST>[^\\\\/:\\\\#?]+)(?::(?<PORT>\\\\d+))?(?P<PATH>\\\\/[^?\\\\#]*)?(?:\\\\?(?P<QUERY>[^\\\\#]*))?(?:(?P<FRAGMENT>.*))?\" , \"SCHEME\" : { \"attr\" : \"scheme\" , \"type\" : \"String\" }, \"HOST\" : { \"attr\" : \"host\" , \"type\" : \"String\" }, \"PORT\" : { \"attr\" : \"port\" , \"type\" : \"String\" }, \"PATH\" : { \"attr\" : \"path\" , \"type\" : \"String\" }, \"QUERY\" : { \"attr\" : \"query\" , \"type\" : \"String\" }, \"FRAGMENT\" : { \"attr\" : \"fragment\" , \"type\" : \"String\" } } } ... Example Policy store # Here is a non-normative example of a cedarling_store.json file: { \"cedar_version\" : \"v4.0.0\" , \"policies\" : { \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" : { \"description\" : \"simple policy example\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : \"cedar_policy_encoded_in_base64\" } }, \"schema\" : \"schema_encoded_in_base64\" , \"identity_source\" : { \"08c6c18a654f492adcf3fe069d729b4d9e6bf82605cb\" : { \"name\" : \"Google\" , \"description\" : \"Consumer IDP\" , \"openid_configuration_endpoint\" : \"https://accounts.google.com/.well-known/openid-configuration\" , \"access_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"\" , }, \"id_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"sub\" , \"role_mapping\" : \"\" , }, \"userinfo_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"role\" , }, \"tx_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"\" , }, } } } Policy and Schema Authoring # You can hand create your Cedar policies and schema in Visual Studio . Make sure you run the cedar command line tool to validate both your schema and policies. The easiest way to author your policy store is to use the Policy Designer in Agama Lab . This tool helps you define the policies, schema and trusted IDPs and to publish a policy store to a Github repository. Minimum supported cedar-policy schema # Here is example of a minimum supported cedar-policy schema : namespace Jans { entity id_token = {\"aud\": String,\"iss\": String, \"sub\": String}; entity Role; entity User in [Role] = {}; entity Access_token = {\"aud\": String,\"iss\": String, \"jti\": String, \"client_id\": String}; entity Workload = {}; entity Issue = {}; action \"Update\" appliesTo { principal: [Workload, User, Role], resource: [Issue], context: {} }; } You can extend all of this entites and add your own. Mandatory entities is: id_token , Role , User , Access_token , Workload . Issue entity and Update action are optinal. Is created for example, you can create others for your needs. Context and Resource entities you can pass during authorization request and next entites creating based on the JWT tokens: id_token - entity based on the id JWT token fields. ID for entity based in jti field. Role - define role of user. Mapping defined in Token Metadata Schema . Claim in JWT usually is string or array of string. Each Role is parent for User . So to check role in policy use operator in to check hierarchy. User - entity based on the id and userinfo JWT token fields. If id and userinfo JWT token fields has different sub value, userinfo JWT token will be ignored. ID for entity based in sub field. (will be changed in future) Access_token - entity based on the access JWT token fields. ID for entity based in jti field. Workload - entity based on the access JWT token fields. ID for entity based in client_id field. Note on test fixtures # You will notice that test fixtures in the cedarling code base are quite often in yaml rather than in json. yaml is intended for cedarling internal use only . The rationale is that yaml has excellent support for embedded, indented, multiline string values. That is far easier to read than base64 encoded json strings, and is beneficial for debugging and validation that test cases are correct.", "title": "Policy Store"}, {"location": "cedarling/cedarling-policy-store/#cedarling-policy-store", "text": "The Cedarling Policy Store uses a JSON file named cedarling_store.json to store all necessary data for evaluating policies and verifying JWT tokens. The structure includes the following key components: Cedar Schema : The Cedar schema encoded in Base64. Cedar Policies : The Cedar policies encoded in Base64. Trusted Issuers : Details about the trusted issuers (see below for syntax). Note: The cedarling_store.json file is only needed if the bootstrap properties: CEDARLING_LOCK ; CEDARLING_POLICY_STORE_URI ; and CEDARLING_POLICY_STORE_ID are not set to a local location. If you're fetching the policies remotely, you don't need a cedarling_store.json file.", "title": "Cedarling Policy Store"}, {"location": "cedarling/cedarling-policy-store/#json-schema", "text": "The JSON Schema accepted by cedarling is defined as follows: { \"cedar_version\" : \"v4.0.0\" , \"policy_stores\" : { \"some_unique_string_id\" : { \"name\" : \"TestPolicy\" , \"description\" : \"Once upon a time there was a Policy, that lived in a Store.\" , \"policies\" : { ... }, \"schema\" : { ... }, \"trusted_issuers\" : { ... } } } } cedar_version : ( String ) The version of Cedar policy . The protocols of this version will be followed when processing Cedar schema and policies. policies : ( Object ) Object containing one or more policy IDs as keys, with their corresponding objects as values. See: policies schema . schema : ( String | Object ) The Cedar Schema. See schema below. trusted_issuers : ( Object of {unique_id => IdentitySource}(#trusted-issuer-schema) ) List of metadata for Identity Sources.", "title": "JSON Schema"}, {"location": "cedarling/cedarling-policy-store/#schema", "text": "Either String or Object , where Object is preferred. Where Object - An object with encoding , content_type and body keys. For example: \"schema\" : { \"encoding\" : \"none\" , // can be one of \"none\" or \"base64\" \"content_type\" : \"cedar\" , // can be one of \"cedar\" or \"cedar-json\" \"body\" : \"namespace Jans {\\ntype Url = {\" hos t \": String, \" pa t h \": String, \" pro t ocol \": String};...\" } Where String - The schema in cedar-json format, encoded as Base64. For example: \"schema\" : \"cGVybWl0KAogICAgc...\"", "title": "schema"}, {"location": "cedarling/cedarling-policy-store/#cedar-policies-schema", "text": "The policies field describes the Cedar policies that will be used in Cedarling. Multiple policies can be defined, with each policy requiring a unique_policy_id . \"policies\" : { \"unique_policy_id\" : { \"cedar_version\" : \"v4.0.0\" , \"name\" : \"Policy for Unique Id\" , \"description\" : \"simple policy example\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : { ... }, }, ... } unique_policy_id : ( String ) A uniqe policy ID used to for tracking and auditing purposes. name : ( String ) A name for the policy description : ( String ) A brief description of cedar policy creation_date : ( String ) Policy creating date in YYYY-MM-DDTHH:MM:SS.ssssss policy_content : ( String | Object ) The Cedar Policy. See policy_content below.", "title": "Cedar Policies Schema"}, {"location": "cedarling/cedarling-policy-store/#policy_content", "text": "Either String or Object , where Object is preferred. Where Object - An object with encoding , content_type and body keys. For example: \"policy_content\" : { \"encoding\" : \"none\" , // can be one of \"none\" or \"base64\" \"content_type\" : \"cedar\" , // ONLY \"cedar\" for now due to limitations in cedar-policy crate \"body\" : \"permit(\\n principal is Jans::User,\\n action in [Jans::Action::\\\"Update\\\"],\\n resource is Jans::Issue\\n)when{\\n principal.country == resource.country\\n};\" } Where String - The policy in cedar format, encoded as Base64. For example: \"policy_content\" : \"cGVybWl0KAogICAgc...\"", "title": "policy_content"}, {"location": "cedarling/cedarling-policy-store/#example-of-policies", "text": "Here is a non-normative example of the policies field: \"policies\" : { \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-first\" , \"description\" : \"simple policy example for principal workload\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : \"cGVybWl0KAogICAgc...\" }, \"0fo1kl928Afa0sc9123scma0123891asklajsh1233ab\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-second\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : \"kJW1bWl0KA0g3CAxa...\" }, \"1fo1kl928Afa0sc9123scma0123891asklajsh1233ac\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-third\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : { \"encoding\" : \"none\" , \"content_type\" : \"cedar\" , \"body\" : \"permit(...) where {...}\" } }, \"2fo1kl928Afa0sc9123scma0123891asklajsh1233ad\" : { \"cedar_version\" : \"v2.7.4\" , \"name\" : \"Policy-the-fourth\" , \"description\" : \"another policy example\" , \"creation_date\" : \"2024-09-20T18:22:39.192051\" , \"policy_content\" : { \"encoding\" : \"base64\" , \"content_type\" : \"cedar\" , \"body\" : \"kJW1bWl0KA0g3CAxa...\" } }, ... }", "title": "Example of policies"}, {"location": "cedarling/cedarling-policy-store/#trusted-issuers-schema", "text": "This record contains the information needed to validate tokens from this issuer: \"identity_source\" : { \"some_unique_id\" : { \"name\" : \"name_of_the_trusted_issuer\" , \"description\" : \"description for the trusted issuer\" , \"openid_configuration_endpoint\" : \"https://<trusted-issuer-hostname>/.well-known/openid-configuration\" , \"access_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"jti\" , ... }, \"id_tokens\" : { ... }, \"userinfo_tokens\" : { ... }, \"tx_tokens\" : { ... }, } ... } name : ( String ) The name of the trusted issuer. description : ( String ) A brief description of the trusted issuer, providing context for administrators. openid_configuration_endpoint : ( String ) The HTTPS URL for the OpenID Connect configuration endpoint (usually found at /.well-known/openid-configuration ). identity_source : ( Object , optional ) Metadata related to the tokens issued by this issuer. Notes : The access_tokens , id_tokens , userinfo_tokens , and tx_tokens fields will follow the Token Metadata Schema . The access_tokens will contain a trusted and principal_identifier field in addition to the fields from the Token Metadata Schema .", "title": "Trusted Issuers Schema"}, {"location": "cedarling/cedarling-policy-store/#token-metadata-schema", "text": "The Token Entity Metadata Schema defines how tokens are mapped, parsed, and transformed within Cedarling. It allows you to specify how to extract user IDs, roles, and other claims from a token using customizable parsers. { \"user_id\" : \"<field name in token (e.g., 'email', 'sub', 'uid', etc.) or '' if not used>\" , \"role_mapping\" : \"<field for role assignment (e.g., 'role', 'memberOf', etc.) or '' if not used>\" , \"claim_mapping\" : { \"mapping_target\" : { \"parser\" : \"<type of parser ('regex' or 'json')>\" , \"type\" : \"<type identifier (e.g., 'Acme::Email')>\" , \"...\" : \"Additional configurations specific to the parser\" }, }, }", "title": "Token Metadata Schema"}, {"location": "cedarling/cedarling-policy-store/#role-mapping", "text": "role_mapping : (String OR Array of String, Optional ) Indicates which field in the token should be used for role-based access control. If not needed, set to an empty string ( \"\" ). You can include a role_mapping in each token, all of them will be executed by Cedarling. If none role_mapping defined the Cedarling will try to find role in userinfo token in field role .", "title": "Role mapping"}, {"location": "cedarling/cedarling-policy-store/#claim-mapping", "text": "claim_mapping: Defines how to extract and transform specific claims from the token. Each claim can have its own parser ( regex or json ) and type ( Acme::email_address , Acme::Url , etc.). In regex attribute mapping like \"UID\": {\"attr\": \"uid\", \"type\":\"String\"}, , type field can contain possible variants: String - to string without transformation, Number - parse string to float64 (JSON number) if error returns default value Boolean - if string NOT empty map to true else false Note, use of regex named capture groups which is more readable by referring to parts of a regex match by descriptive names rather than numbers. For example, (?P<name>...) defines a named capture group where name is the identifier, and ... is the regex pattern for what you want to capture. When you use (?x) modifier in regexp, ensure that you escaped character # => \\# . example of mapping email_address and Url : ... \"claim_mapping\" : { \"email\" : { \"parser\" : \"regex\" , \"type\" : \"Test::email_address\" , \"regex_expression\" : \"^(?P<UID>[^@]+)@(?P<DOMAIN>.+)$\" , \"UID\" : { \"attr\" : \"uid\" , \"type\" : \"String\" }, \"DOMAIN\" : { \"attr\" : \"domain\" , \"type\" : \"String\" } }, \"profile\" : { \"parser\" : \"regex\" , \"type\" : \"Test::Url\" , \"regex_expression\" : \"(?x) ^(?P<SCHEME>[a-zA-Z][a-zA-Z0-9+.-]*):\\\\/\\\\/(?P<HOST>[^\\\\/:\\\\#?]+)(?::(?<PORT>\\\\d+))?(?P<PATH>\\\\/[^?\\\\#]*)?(?:\\\\?(?P<QUERY>[^\\\\#]*))?(?:(?P<FRAGMENT>.*))?\" , \"SCHEME\" : { \"attr\" : \"scheme\" , \"type\" : \"String\" }, \"HOST\" : { \"attr\" : \"host\" , \"type\" : \"String\" }, \"PORT\" : { \"attr\" : \"port\" , \"type\" : \"String\" }, \"PATH\" : { \"attr\" : \"path\" , \"type\" : \"String\" }, \"QUERY\" : { \"attr\" : \"query\" , \"type\" : \"String\" }, \"FRAGMENT\" : { \"attr\" : \"fragment\" , \"type\" : \"String\" } } } ...", "title": "Claim mapping"}, {"location": "cedarling/cedarling-policy-store/#example-policy-store", "text": "Here is a non-normative example of a cedarling_store.json file: { \"cedar_version\" : \"v4.0.0\" , \"policies\" : { \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" : { \"description\" : \"simple policy example\" , \"creation_date\" : \"2024-09-20T17:22:39.996050\" , \"policy_content\" : \"cedar_policy_encoded_in_base64\" } }, \"schema\" : \"schema_encoded_in_base64\" , \"identity_source\" : { \"08c6c18a654f492adcf3fe069d729b4d9e6bf82605cb\" : { \"name\" : \"Google\" , \"description\" : \"Consumer IDP\" , \"openid_configuration_endpoint\" : \"https://accounts.google.com/.well-known/openid-configuration\" , \"access_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"\" , }, \"id_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"sub\" , \"role_mapping\" : \"\" , }, \"userinfo_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"role\" , }, \"tx_tokens\" : { \"trusted\" : true , \"principal_identifier\" : \"\" , \"role_mapping\" : \"\" , }, } } }", "title": "Example Policy store"}, {"location": "cedarling/cedarling-policy-store/#policy-and-schema-authoring", "text": "You can hand create your Cedar policies and schema in Visual Studio . Make sure you run the cedar command line tool to validate both your schema and policies. The easiest way to author your policy store is to use the Policy Designer in Agama Lab . This tool helps you define the policies, schema and trusted IDPs and to publish a policy store to a Github repository.", "title": "Policy and Schema Authoring"}, {"location": "cedarling/cedarling-policy-store/#minimum-supported-cedar-policy-schema", "text": "Here is example of a minimum supported cedar-policy schema : namespace Jans { entity id_token = {\"aud\": String,\"iss\": String, \"sub\": String}; entity Role; entity User in [Role] = {}; entity Access_token = {\"aud\": String,\"iss\": String, \"jti\": String, \"client_id\": String}; entity Workload = {}; entity Issue = {}; action \"Update\" appliesTo { principal: [Workload, User, Role], resource: [Issue], context: {} }; } You can extend all of this entites and add your own. Mandatory entities is: id_token , Role , User , Access_token , Workload . Issue entity and Update action are optinal. Is created for example, you can create others for your needs. Context and Resource entities you can pass during authorization request and next entites creating based on the JWT tokens: id_token - entity based on the id JWT token fields. ID for entity based in jti field. Role - define role of user. Mapping defined in Token Metadata Schema . Claim in JWT usually is string or array of string. Each Role is parent for User . So to check role in policy use operator in to check hierarchy. User - entity based on the id and userinfo JWT token fields. If id and userinfo JWT token fields has different sub value, userinfo JWT token will be ignored. ID for entity based in sub field. (will be changed in future) Access_token - entity based on the access JWT token fields. ID for entity based in jti field. Workload - entity based on the access JWT token fields. ID for entity based in client_id field.", "title": "Minimum supported cedar-policy schema"}, {"location": "cedarling/cedarling-policy-store/#note-on-test-fixtures", "text": "You will notice that test fixtures in the cedarling code base are quite often in yaml rather than in json. yaml is intended for cedarling internal use only . The rationale is that yaml has excellent support for embedded, indented, multiline string values. That is far easier to read than base64 encoded json strings, and is beneficial for debugging and validation that test cases are correct.", "title": "Note on test fixtures"}, {"location": "cedarling/cedarling-properties/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling", "properties"], "text": "Cedarling Properties # These Bootstrap Properties control default application level behavior. CEDARLING_APPLICATION_NAME : Human friendly identifier for this application CEDARLING_POLICY_STORE_URI : Location of policy store JSON, used if policy store is not local, or retreived from Lock Master. CEDARLING_POLICY_STORE_ID : The identifier of the policy store in case there is more then one policy_store_id in the policy store. CEDARLING_USER_AUTHZ : When enabled , Cedar engine authorization is queried for a User principal. CEDARLING_WORKLOAD_AUTHZ : When enabled , Cedar engine authorization is queried for a Workload principal. CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION : AND , OR CEDARLING_MAPPING_USER : Name of Cedar User schema entity if we don't want to use default. When specified cedarling try build defined entity (from schema) as user instead of default User entity defined in cedar schema. Works in namespace defined in the policy store. CEDARLING_MAPPING_WORKLOAD : Name of Cedar Workload schema entity CEDARLING_MAPPING_ID_TOKEN : Name of Cedar id_token schema entity CEDARLING_MAPPING_ACCESS_TOKEN : Name of Cedar access_token schema entity CEDARLING_MAPPING_USERINFO_TOKEN : Name of Cedar userinfo schema entity The following bootstrap properties are needed to configure log behavior: CEDARLING_LOG_STORAGE : off , memory , std_out CEDARLING_LOG_LEVEL : System Log Level See here . Default to WARN CEDARLING_LOG_STDOUT_TYPE : Either System , Metric , or Decision . Default to System. CEDARLING_LOG_LEVEL : Log level filter for logging. Log level has only System log type entries. TRACE is lowest. FATAL is highest. Possible variants: FATAL ERROR WARN INFO DEBUG TRACE CEDARLING_DECISION_LOG_USER_CLAIMS : List of claims to map from user entity, such as [\"sub\", \"email\", \"username\", ...] CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS : List of claims to map from user entity, such as [\"client_id\", \"rp_id\", ...] CEDARLING_DECISION_LOG_DEFAULT_JWT_ID : Token claims that will be used for decision logging. Default is \"jti\", but perhaps some other claim is needed. CEDARLING_LOG_TTL : in case of memory store, TTL (time to live) of log entities in seconds. The following bootstrap properties are needed to configure JWT and cryptographic behavior: CEDARLING_LOCAL_JWKS : JWKS file with public keys CEDARLING_LOCAL_POLICY_STORE : JSON object with policy store CEDARLING_POLICY_STORE_LOCAL_FN : Local file with JSON object with policy store CEDARLING_JWT_SIG_VALIDATION : Enabled | Disabled -- Whether to check the signature of all JWT tokens. This requires an iss is present. CEDARLING_JWT_STATUS_VALIDATION : Enabled | Disabled -- Whether to check the status of the JWT. On startup, the Cedarling should fetch and retreive the latest Status List JWT from the .well-known/openid-configuration via the status_list_endpoint claim and cache it. See the IETF Draft for more info. CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED : Only tokens signed with these algorithms are acceptable to the Cedarling. CEDARLING_AT_ISS_VALIDATION : When enabled, the iss claim must be present in access token and the scheme must be https . CEDARLING_AT_JTI_VALIDATION : When enabled, the jti claim must be present in access token. CEDARLING_AT_NBF_VALIDATION : When enabled, the nbf claim must be present in access token and the Cedarling should verify that the current date is after the nbf . CEDARLING_AT_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_IDT_ISS_VALIDATION : When enabled, the iss claim must be present in id_token and the scheme must be https . CEDARLING_IDT_SUB_VALIDATION : When enabled, the sub claim must be present in id_token. CEDARLING_IDT_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_IDT_IAT_VALIDATION : When enabled, the iat claim must be present in id_token. CEDARLING_IDT_AUD_VALIDATION : When enabled, the aud claim must be present in id_token. CEDARLING_USERINFO_ISS_VALIDATION : When enabled, the iss claim must be present and the scheme must be https . CEDARLING_USERINFO_SUB_VALIDATION : When enabled, the sub claim must be present in Userinfo JWT. CEDARLING_USERINFO_AUD_VALIDATION : When enabled, the aud claim must be present in Userinfo JWT. CEDARLING_USERINFO_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_ID_TOKEN_TRUST_MODE : Strict | None . Varying levels of validations based on the preference of the developer. Strict mode requires (1) id_token aud matches the access_token client_id ; (2) if a Userinfo token is present, the sub matches the id_token, and that the aud matches the access token client_id. The following bootstrap properties are only needed for enterprise deployments. CEDARLING_LOCK : Enabled | Disabled. If Enabled, the Cedarling will connect to the Lock Master for policies, and subscribe for SSE events. CEDARLING_LOCK_MASTER_CONFIGURATION_URI : Required if LOCK == Enabled . URI where Cedarling can get JSON file with all required metadata about Lock Master, i.e. .well-known/lock-master-configuration . CEDARLING_LOCK_DYNAMIC_CONFIGURATION : Enabled | Disabled, controls whether Cedarling should listen for SSE config updates. CEDARLING_LOCK_SSA_JWT : SSA for DCR in a Lock Master deployment. The Cedarling will validate this SSA JWT prior to DCR. CEDARLING_LOCK_LOG_INTERVAL : How often to send log messages to Lock Master (0 to turn off trasmission). CEDARLING_LOCK_HEALTH_INTERVAL : How often to send health messages to Lock Master (0 to turn off transmission). CEDARLING_LOCK_TELEMETRY_INTERVAL : How often to send telemetry messages to Lock Master (0 to turn off transmission). CEDARLING_LOCK_LISTEN_SSE : Enabled | Disabled: controls whether Cedarling should listen for updates from the Lock Server. User-Workload Boolean Operation # The CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION property specifies what boolean operation to use for the USER and WORKLOAD when making authz (authorization) decisions. Available Operations # AND : authz will be successful if USER AND WORKLOAD is valid. OR : authz will be successful if USER OR WORKLOAD is valid. ID Token Trust Mode # The level of validation for the ID Token JWT can be set to either None or Strict . None Mode # Setting the validation level to None will not check for the conditions outlined in Strict Mode . Strict Mode # Strict mode requires: The id_token 's aud matches the access_token 's client_id ; if a Userinfo token is present, the sub matches the id_token , and that the aud matches the access token's client_id . Local JWKS # A local JWKS can be used by setting the CEDARLING_LOCAL_JWKS bootstrap property to a path to a local JSON file. When providing a local Json Web Key Store (JWKS), the file must follow the following schema: { \"trusted_issuer_id\" : [ ... ] \"another_trusted_issuer_id\" : [ ... ] } Where keys are Trusted Issuer IDs assigned to each key store and the values contains the JSON Web Keys as defined in RFC 7517 . The trusted_issuers_id is used to tag a JWKS with a unique identifier and enables using multiple key stores. Loading the bootstrap config # There are multiple ways to load your bootstrap config: From a JSON file From a YAML file You can load from both file types using the following code snippet: use cedarling :: BootstrapConfig ; let config = BootstrapConfig :: load_from_file ( \"./path/to/your/config.json\" ). unwrap (); Loading From JSON # Below is an example of a bootstrap config in JSON format. Not all fields should be specified, almost all have default value. { \"CEDARLING_APPLICATION_NAME\" : \"My App\" , \"CEDARLING_POLICY_STORE_URI\" : \"\" , \"CEDARLING_POLICY_STORE_ID\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"CEDARLING_LOG_TYPE\" : \"memory\" , \"CEDARLING_LOG_LEVEL\" : \"INFO\" , \"CEDARLING_DECISION_LOG_USER_CLAIMS\" : [ \"sub\" , \"email\" , \"username\" ], \"CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS\" : [ \"client_id\" , \"rp_id\" ], \"CEDARLING_DECISION_LOG_DEFAULT_JWT_ID\" : \"jti\" , \"CEDARLING_LOG_TTL\" : 60 , \"CEDARLING_USER_AUTHZ\" : \"enabled\" , \"CEDARLING_WORKLOAD_AUTHZ\" : \"enabled\" , \"CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION\" : \"AND\" , \"CEDARLING_MAPPING_USER\" : \"CustomUser\" , \"CEDARLING_MAPPING_WORKLOAD\" : \"CustomWorkload\" , \"CEDARLING_MAPPING_ID_TOKEN\" : \"CustomIdToken\" , \"CEDARLING_MAPPING_ACCESS_TOKEN\" : \"CustomAccessToken\" , \"CEDARLING_MAPPING_USERINFO_TOKEN\" : \"CustomUserinfoToken\" , \"CEDARLING_LOCAL_JWKS\" : \"../test_files/local_jwks.json\" , \"CEDARLING_LOCAL_POLICY_STORE\" : null , \"CEDARLING_POLICY_STORE_LOCAL_FN\" : \"../test_files/policy-store_blobby.json\" , \"CEDARLING_JWT_SIG_VALIDATION\" : \"enabled\" , \"CEDARLING_JWT_STATUS_VALIDATION\" : \"disabled\" , \"CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED\" : [ \"HS256\" , \"RS256\" ], \"CEDARLING_AT_ISS_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_JTI_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_NBF_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_ISS_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_SUB_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_IAT_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_AUD_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_ISS_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_SUB_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_AUD_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_ID_TOKEN_TRUST_MODE\" : \"Strict\" , \"CEDARLING_LOCK\" : \"disabled\" , \"CEDARLING_LOCK_MASTER_CONFIGURATION_URI\" : null , \"CEDARLING_DYNAMIC_CONFIGURATION\" : \"disabled\" , \"CEDARLING_LOCK_SSA_JWT\" : null , \"CEDARLING_AUDIT_HEALTH_INTERVAL\" : 0 , \"CEDARLING_AUDIT_TELEMETRY_INTERVAL\" : 0 , \"CEDARLING_LISTEN_SSE\" : \"disabled\" } Note that properties set to \"disabled\" , an empty string \"\" , zero 0 , and null can be ommited since they are the defaults. Local JWKS # A local JWKS can be used by setting the CEDARLING_LOCAL_JWKS bootstrap property to a path to a local JSON file. When providing a local Json Web Key Store (JWKS), the file must follow the following schema: { \"trusted_issuer_id\" : [ ... ] \"another_trusted_issuer_id\" : [ ... ] } Where keys are Trusted Issuer IDs assigned to each key store and the values contains the JSON Web Keys as defined in RFC 7517 . The trusted_issuers_id is used to tag a JWKS with a unique identifier and enables using multiple key stores. Note that properties set to \"disabled\" , an empty string \"\" , zero 0 , and null can be ommited since they are the defaults. Loading From YAML # Below is an example of a bootstrap config in YAML format. Not all fields should be specified, almost all have default value. CEDARLING_APPLICATION_NAME : My App CEDARLING_POLICY_STORE_URI : '' CEDARLING_POLICY_STORE_ID : '840da5d85403f35ea76519ed1a18a33989f855bf1cf8' CEDARLING_LOG_TYPE : 'memory' CEDARLING_LOG_LEVEL : 'INFO' CEDARLING_DECISION_LOG_USER_CLAIMS : [ \"sub\" , \"email\" ] CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS : [ \"client_id\" , \"rp_id\" ] CEDARLING_LOG_TTL : 60 CEDARLING_USER_AUTHZ : 'enabled' CEDARLING_WORKLOAD_AUTHZ : 'enabled' CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION : 'AND' CEDARLING_MAPPING_USER : 'CustomUser' CEDARLING_MAPPING_WORKLOAD : 'CustomWorkload' CEDARLING_MAPPING_ID_TOKEN : 'CustomIdToken' CEDARLING_MAPPING_ACCESS_TOKEN : 'CustomAccessToken' CEDARLING_MAPPING_USERINFO_TOKEN : 'CustomUserinfoToken' CEDARLING_LOCAL_JWKS : '../test_files/local_jwks.json' CEDARLING_LOCAL_POLICY_STORE : null CEDARLING_POLICY_STORE_LOCAL_FN : '../test_files/policy-store_blobby.json' CEDARLING_JWT_SIG_VALIDATION : 'enabled' CEDARLING_JWT_STATUS_VALIDATION : 'disabled' CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED : - 'HS256' - 'RS256' CEDARLING_AT_ISS_VALIDATION : 'disabled' CEDARLING_AT_JTI_VALIDATION : 'disabled' CEDARLING_AT_NBF_VALIDATION : 'disabled' CEDARLING_AT_EXP_VALIDATION : 'enabled' CEDARLING_IDT_ISS_VALIDATION : 'enabled' CEDARLING_IDT_SUB_VALIDATION : 'enabled' CEDARLING_IDT_EXP_VALIDATION : 'enabled' CEDARLING_IDT_IAT_VALIDATION : 'enabled' CEDARLING_IDT_AUD_VALIDATION : 'enabled' CEDARLING_USERINFO_ISS_VALIDATION : 'enabled' CEDARLING_USERINFO_SUB_VALIDATION : 'enabled' CEDARLING_USERINFO_AUD_VALIDATION : 'enabled' CEDARLING_USERINFO_EXP_VALIDATION : 'enabled' CEDARLING_ID_TOKEN_TRUST_MODE : 'Strict' CEDARLING_LOCK : 'disabled' CEDARLING_LOCK_MASTER_CONFIGURATION_URI : null CEDARLING_DYNAMIC_CONFIGURATION : 'disabled' CEDARLING_LOCK_SSA_JWT : 0 CEDARLING_AUDIT_HEALTH_INTERVAL : 0 CEDARLING_AUDIT_TELEMETRY_INTERVAL : 0 CEDARLING_LISTEN_SSE : 'disabled' Note that properties set to 'disabled' , an empty string '' , zero 0 , and null can be ommited since they are the defaults.", "title": "Properties"}, {"location": "cedarling/cedarling-properties/#cedarling-properties", "text": "These Bootstrap Properties control default application level behavior. CEDARLING_APPLICATION_NAME : Human friendly identifier for this application CEDARLING_POLICY_STORE_URI : Location of policy store JSON, used if policy store is not local, or retreived from Lock Master. CEDARLING_POLICY_STORE_ID : The identifier of the policy store in case there is more then one policy_store_id in the policy store. CEDARLING_USER_AUTHZ : When enabled , Cedar engine authorization is queried for a User principal. CEDARLING_WORKLOAD_AUTHZ : When enabled , Cedar engine authorization is queried for a Workload principal. CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION : AND , OR CEDARLING_MAPPING_USER : Name of Cedar User schema entity if we don't want to use default. When specified cedarling try build defined entity (from schema) as user instead of default User entity defined in cedar schema. Works in namespace defined in the policy store. CEDARLING_MAPPING_WORKLOAD : Name of Cedar Workload schema entity CEDARLING_MAPPING_ID_TOKEN : Name of Cedar id_token schema entity CEDARLING_MAPPING_ACCESS_TOKEN : Name of Cedar access_token schema entity CEDARLING_MAPPING_USERINFO_TOKEN : Name of Cedar userinfo schema entity The following bootstrap properties are needed to configure log behavior: CEDARLING_LOG_STORAGE : off , memory , std_out CEDARLING_LOG_LEVEL : System Log Level See here . Default to WARN CEDARLING_LOG_STDOUT_TYPE : Either System , Metric , or Decision . Default to System. CEDARLING_LOG_LEVEL : Log level filter for logging. Log level has only System log type entries. TRACE is lowest. FATAL is highest. Possible variants: FATAL ERROR WARN INFO DEBUG TRACE CEDARLING_DECISION_LOG_USER_CLAIMS : List of claims to map from user entity, such as [\"sub\", \"email\", \"username\", ...] CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS : List of claims to map from user entity, such as [\"client_id\", \"rp_id\", ...] CEDARLING_DECISION_LOG_DEFAULT_JWT_ID : Token claims that will be used for decision logging. Default is \"jti\", but perhaps some other claim is needed. CEDARLING_LOG_TTL : in case of memory store, TTL (time to live) of log entities in seconds. The following bootstrap properties are needed to configure JWT and cryptographic behavior: CEDARLING_LOCAL_JWKS : JWKS file with public keys CEDARLING_LOCAL_POLICY_STORE : JSON object with policy store CEDARLING_POLICY_STORE_LOCAL_FN : Local file with JSON object with policy store CEDARLING_JWT_SIG_VALIDATION : Enabled | Disabled -- Whether to check the signature of all JWT tokens. This requires an iss is present. CEDARLING_JWT_STATUS_VALIDATION : Enabled | Disabled -- Whether to check the status of the JWT. On startup, the Cedarling should fetch and retreive the latest Status List JWT from the .well-known/openid-configuration via the status_list_endpoint claim and cache it. See the IETF Draft for more info. CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED : Only tokens signed with these algorithms are acceptable to the Cedarling. CEDARLING_AT_ISS_VALIDATION : When enabled, the iss claim must be present in access token and the scheme must be https . CEDARLING_AT_JTI_VALIDATION : When enabled, the jti claim must be present in access token. CEDARLING_AT_NBF_VALIDATION : When enabled, the nbf claim must be present in access token and the Cedarling should verify that the current date is after the nbf . CEDARLING_AT_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_IDT_ISS_VALIDATION : When enabled, the iss claim must be present in id_token and the scheme must be https . CEDARLING_IDT_SUB_VALIDATION : When enabled, the sub claim must be present in id_token. CEDARLING_IDT_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_IDT_IAT_VALIDATION : When enabled, the iat claim must be present in id_token. CEDARLING_IDT_AUD_VALIDATION : When enabled, the aud claim must be present in id_token. CEDARLING_USERINFO_ISS_VALIDATION : When enabled, the iss claim must be present and the scheme must be https . CEDARLING_USERINFO_SUB_VALIDATION : When enabled, the sub claim must be present in Userinfo JWT. CEDARLING_USERINFO_AUD_VALIDATION : When enabled, the aud claim must be present in Userinfo JWT. CEDARLING_USERINFO_EXP_VALIDATION : When enabled, the exp claim must be present and not past the date specified. CEDARLING_ID_TOKEN_TRUST_MODE : Strict | None . Varying levels of validations based on the preference of the developer. Strict mode requires (1) id_token aud matches the access_token client_id ; (2) if a Userinfo token is present, the sub matches the id_token, and that the aud matches the access token client_id. The following bootstrap properties are only needed for enterprise deployments. CEDARLING_LOCK : Enabled | Disabled. If Enabled, the Cedarling will connect to the Lock Master for policies, and subscribe for SSE events. CEDARLING_LOCK_MASTER_CONFIGURATION_URI : Required if LOCK == Enabled . URI where Cedarling can get JSON file with all required metadata about Lock Master, i.e. .well-known/lock-master-configuration . CEDARLING_LOCK_DYNAMIC_CONFIGURATION : Enabled | Disabled, controls whether Cedarling should listen for SSE config updates. CEDARLING_LOCK_SSA_JWT : SSA for DCR in a Lock Master deployment. The Cedarling will validate this SSA JWT prior to DCR. CEDARLING_LOCK_LOG_INTERVAL : How often to send log messages to Lock Master (0 to turn off trasmission). CEDARLING_LOCK_HEALTH_INTERVAL : How often to send health messages to Lock Master (0 to turn off transmission). CEDARLING_LOCK_TELEMETRY_INTERVAL : How often to send telemetry messages to Lock Master (0 to turn off transmission). CEDARLING_LOCK_LISTEN_SSE : Enabled | Disabled: controls whether Cedarling should listen for updates from the Lock Server.", "title": "Cedarling Properties"}, {"location": "cedarling/cedarling-properties/#user-workload-boolean-operation", "text": "The CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION property specifies what boolean operation to use for the USER and WORKLOAD when making authz (authorization) decisions.", "title": "User-Workload Boolean Operation"}, {"location": "cedarling/cedarling-properties/#available-operations", "text": "AND : authz will be successful if USER AND WORKLOAD is valid. OR : authz will be successful if USER OR WORKLOAD is valid.", "title": "Available Operations"}, {"location": "cedarling/cedarling-properties/#id-token-trust-mode", "text": "The level of validation for the ID Token JWT can be set to either None or Strict .", "title": "ID Token Trust Mode"}, {"location": "cedarling/cedarling-properties/#none-mode", "text": "Setting the validation level to None will not check for the conditions outlined in Strict Mode .", "title": "None Mode"}, {"location": "cedarling/cedarling-properties/#strict-mode", "text": "Strict mode requires: The id_token 's aud matches the access_token 's client_id ; if a Userinfo token is present, the sub matches the id_token , and that the aud matches the access token's client_id .", "title": "Strict Mode"}, {"location": "cedarling/cedarling-properties/#local-jwks", "text": "A local JWKS can be used by setting the CEDARLING_LOCAL_JWKS bootstrap property to a path to a local JSON file. When providing a local Json Web Key Store (JWKS), the file must follow the following schema: { \"trusted_issuer_id\" : [ ... ] \"another_trusted_issuer_id\" : [ ... ] } Where keys are Trusted Issuer IDs assigned to each key store and the values contains the JSON Web Keys as defined in RFC 7517 . The trusted_issuers_id is used to tag a JWKS with a unique identifier and enables using multiple key stores.", "title": "Local JWKS"}, {"location": "cedarling/cedarling-properties/#loading-the-bootstrap-config", "text": "There are multiple ways to load your bootstrap config: From a JSON file From a YAML file You can load from both file types using the following code snippet: use cedarling :: BootstrapConfig ; let config = BootstrapConfig :: load_from_file ( \"./path/to/your/config.json\" ). unwrap ();", "title": "Loading the bootstrap config"}, {"location": "cedarling/cedarling-properties/#loading-from-json", "text": "Below is an example of a bootstrap config in JSON format. Not all fields should be specified, almost all have default value. { \"CEDARLING_APPLICATION_NAME\" : \"My App\" , \"CEDARLING_POLICY_STORE_URI\" : \"\" , \"CEDARLING_POLICY_STORE_ID\" : \"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\" , \"CEDARLING_LOG_TYPE\" : \"memory\" , \"CEDARLING_LOG_LEVEL\" : \"INFO\" , \"CEDARLING_DECISION_LOG_USER_CLAIMS\" : [ \"sub\" , \"email\" , \"username\" ], \"CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS\" : [ \"client_id\" , \"rp_id\" ], \"CEDARLING_DECISION_LOG_DEFAULT_JWT_ID\" : \"jti\" , \"CEDARLING_LOG_TTL\" : 60 , \"CEDARLING_USER_AUTHZ\" : \"enabled\" , \"CEDARLING_WORKLOAD_AUTHZ\" : \"enabled\" , \"CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION\" : \"AND\" , \"CEDARLING_MAPPING_USER\" : \"CustomUser\" , \"CEDARLING_MAPPING_WORKLOAD\" : \"CustomWorkload\" , \"CEDARLING_MAPPING_ID_TOKEN\" : \"CustomIdToken\" , \"CEDARLING_MAPPING_ACCESS_TOKEN\" : \"CustomAccessToken\" , \"CEDARLING_MAPPING_USERINFO_TOKEN\" : \"CustomUserinfoToken\" , \"CEDARLING_LOCAL_JWKS\" : \"../test_files/local_jwks.json\" , \"CEDARLING_LOCAL_POLICY_STORE\" : null , \"CEDARLING_POLICY_STORE_LOCAL_FN\" : \"../test_files/policy-store_blobby.json\" , \"CEDARLING_JWT_SIG_VALIDATION\" : \"enabled\" , \"CEDARLING_JWT_STATUS_VALIDATION\" : \"disabled\" , \"CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED\" : [ \"HS256\" , \"RS256\" ], \"CEDARLING_AT_ISS_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_JTI_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_NBF_VALIDATION\" : \"disabled\" , \"CEDARLING_AT_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_ISS_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_SUB_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_IAT_VALIDATION\" : \"enabled\" , \"CEDARLING_IDT_AUD_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_ISS_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_SUB_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_AUD_VALIDATION\" : \"enabled\" , \"CEDARLING_USERINFO_EXP_VALIDATION\" : \"enabled\" , \"CEDARLING_ID_TOKEN_TRUST_MODE\" : \"Strict\" , \"CEDARLING_LOCK\" : \"disabled\" , \"CEDARLING_LOCK_MASTER_CONFIGURATION_URI\" : null , \"CEDARLING_DYNAMIC_CONFIGURATION\" : \"disabled\" , \"CEDARLING_LOCK_SSA_JWT\" : null , \"CEDARLING_AUDIT_HEALTH_INTERVAL\" : 0 , \"CEDARLING_AUDIT_TELEMETRY_INTERVAL\" : 0 , \"CEDARLING_LISTEN_SSE\" : \"disabled\" } Note that properties set to \"disabled\" , an empty string \"\" , zero 0 , and null can be ommited since they are the defaults.", "title": "Loading From JSON"}, {"location": "cedarling/cedarling-properties/#local-jwks_1", "text": "A local JWKS can be used by setting the CEDARLING_LOCAL_JWKS bootstrap property to a path to a local JSON file. When providing a local Json Web Key Store (JWKS), the file must follow the following schema: { \"trusted_issuer_id\" : [ ... ] \"another_trusted_issuer_id\" : [ ... ] } Where keys are Trusted Issuer IDs assigned to each key store and the values contains the JSON Web Keys as defined in RFC 7517 . The trusted_issuers_id is used to tag a JWKS with a unique identifier and enables using multiple key stores. Note that properties set to \"disabled\" , an empty string \"\" , zero 0 , and null can be ommited since they are the defaults.", "title": "Local JWKS"}, {"location": "cedarling/cedarling-properties/#loading-from-yaml", "text": "Below is an example of a bootstrap config in YAML format. Not all fields should be specified, almost all have default value. CEDARLING_APPLICATION_NAME : My App CEDARLING_POLICY_STORE_URI : '' CEDARLING_POLICY_STORE_ID : '840da5d85403f35ea76519ed1a18a33989f855bf1cf8' CEDARLING_LOG_TYPE : 'memory' CEDARLING_LOG_LEVEL : 'INFO' CEDARLING_DECISION_LOG_USER_CLAIMS : [ \"sub\" , \"email\" ] CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS : [ \"client_id\" , \"rp_id\" ] CEDARLING_LOG_TTL : 60 CEDARLING_USER_AUTHZ : 'enabled' CEDARLING_WORKLOAD_AUTHZ : 'enabled' CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION : 'AND' CEDARLING_MAPPING_USER : 'CustomUser' CEDARLING_MAPPING_WORKLOAD : 'CustomWorkload' CEDARLING_MAPPING_ID_TOKEN : 'CustomIdToken' CEDARLING_MAPPING_ACCESS_TOKEN : 'CustomAccessToken' CEDARLING_MAPPING_USERINFO_TOKEN : 'CustomUserinfoToken' CEDARLING_LOCAL_JWKS : '../test_files/local_jwks.json' CEDARLING_LOCAL_POLICY_STORE : null CEDARLING_POLICY_STORE_LOCAL_FN : '../test_files/policy-store_blobby.json' CEDARLING_JWT_SIG_VALIDATION : 'enabled' CEDARLING_JWT_STATUS_VALIDATION : 'disabled' CEDARLING_JWT_SIGNATURE_ALGORITHMS_SUPPORTED : - 'HS256' - 'RS256' CEDARLING_AT_ISS_VALIDATION : 'disabled' CEDARLING_AT_JTI_VALIDATION : 'disabled' CEDARLING_AT_NBF_VALIDATION : 'disabled' CEDARLING_AT_EXP_VALIDATION : 'enabled' CEDARLING_IDT_ISS_VALIDATION : 'enabled' CEDARLING_IDT_SUB_VALIDATION : 'enabled' CEDARLING_IDT_EXP_VALIDATION : 'enabled' CEDARLING_IDT_IAT_VALIDATION : 'enabled' CEDARLING_IDT_AUD_VALIDATION : 'enabled' CEDARLING_USERINFO_ISS_VALIDATION : 'enabled' CEDARLING_USERINFO_SUB_VALIDATION : 'enabled' CEDARLING_USERINFO_AUD_VALIDATION : 'enabled' CEDARLING_USERINFO_EXP_VALIDATION : 'enabled' CEDARLING_ID_TOKEN_TRUST_MODE : 'Strict' CEDARLING_LOCK : 'disabled' CEDARLING_LOCK_MASTER_CONFIGURATION_URI : null CEDARLING_DYNAMIC_CONFIGURATION : 'disabled' CEDARLING_LOCK_SSA_JWT : 0 CEDARLING_AUDIT_HEALTH_INTERVAL : 0 CEDARLING_AUDIT_TELEMETRY_INTERVAL : 0 CEDARLING_LISTEN_SSE : 'disabled' Note that properties set to 'disabled' , an empty string '' , zero 0 , and null can be ommited since they are the defaults.", "title": "Loading From YAML"}, {"location": "cedarling/cedarling-wasm/", "tags": ["cedarling", "wasm"], "text": "WASM for Cedarling # Cedarling provides a binding for JavaScript programs via the wasm-pack tool. This allows browser developers to use the cedarling crate in their code directly. Requirements # Rust 1.63 or greater Installed wasm-pack via cargo clang with wasm target support Building # Install wasm-pack by: cargo install wasm-pack Build cedarling wasm in release: wasm-pack build --release --target web wasm-pack automatically make optimization of wasm binary file, using wasm-opt . - Get result in the pkg folder. Including in projects # For using result files in browser project you need make result pkg folder accessible for loading in the browser so that you can later import the corresponding file from the browser. Here is example of code snippet: < script type = \"module\" > import initWasm , { init } from \"/pkg/cedarling_wasm.js\" ; async function main () { await initWasm (); // Initialize the WebAssembly module // init cedarling with `BOOTSTRAP` config let instance = await init ({ \"CEDARLING_APPLICATION_NAME\" : \"My App\" , \"CEDARLING_POLICY_STORE_URI\" : \"https://example.com/policy-store.json\" , \"CEDARLING_LOG_TYPE\" : \"memory\" , \"CEDARLING_LOG_LEVEL\" : \"INFO\" , \"CEDARLING_LOG_TTL\" : 120 , \"CEDARLING_DECISION_LOG_USER_CLAIMS \" : [ \"aud\" , \"sub\" , \"email\" , \"username\" ], \"CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS \" : [ \"aud\" , \"client_id\" , \"rp_id\" ], \"CEDARLING_USER_AUTHZ\" : \"enabled\" , \"CEDARLING_WORKLOAD_AUTHZ\" : \"enabled\" , \"CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION\" : \"AND\" , }); // make authorize request let result = await instance . authorize ({ \"tokens\" : { \"access_token\" : \"...\" , \"id_token\" : \"...\" , \"userinfo_token\" : \"...\" , }, \"action\" : 'Jans::Action::\"Read\"' , \"resource\" : { \"type\" : \"Jans::Application\" , \"id\" : \"some_id\" , \"app_id\" : \"application_id\" , \"name\" : \"Some Application\" , \"url\" : { \"host\" : \"jans.test\" , \"path\" : \"/protected-endpoint\" , \"protocol\" : \"http\" } }, \"context\" : { \"current_time\" : Math . floor ( Date . now () / 1000 ), \"device_health\" : [ \"Healthy\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"geolocation\" : [ \"America\" ], \"network\" : \"127.0.0.1\" , \"network_type\" : \"Local\" , \"operating_system\" : \"Linux\" , \"user_agent\" : \"Linux\" }, }); console . log ( \"result:\" , result ); } main (). catch ( console . error ); </ script > Usage # Before usage make sure that you have completed Building steps. You can find usage examples in the following locations: jans-cedarling/bindings/cedarling_wasm/index.html : A simple example demonstrating basic usage. jans-cedarling/bindings/cedarling_wasm/cedarling_app.html : A fully featured Cedarling browser app where you can test and validate your configuration. Defined API # /** * Create a new instance of the Cedarling application. * This function can take as config parameter the eather `Map` other `Object` */ export function init ( config : any ) : Promise < Cedarling > ; /** * The instance of the Cedarling application. */ export class Cedarling { /** * Create a new instance of the Cedarling application. * Assume that config is `Object` */ static new ( config : object ) : Promise < Cedarling > ; /** * Create a new instance of the Cedarling application. * Assume that config is `Map` */ static new_from_map ( config : Map < any , any > ) : Promise < Cedarling > ; /** * Authorize request * makes authorization decision based on the [`Request`] */ authorize ( request : any ) : Promise < AuthorizeResult > ; /** * Get logs and remove them from the storage. * Returns `Array` of `Map` */ pop_logs () : Array < any > ; /** * Get specific log entry. * Returns `Map` with values or `null`. */ get_log_by_id ( id : string ) : any ; /** * Returns a list of all log ids. * Returns `Array` of `String` */ get_log_ids () : Array < any > ; } /** * A WASM wrapper for the Rust `cedarling::AuthorizeResult` struct. * Represents the result of an authorization request. */ export class AuthorizeResult { /** * Convert `AuthorizeResult` to json string value */ json_string () : string ; /** * Result of authorization where principal is `Jans::Workload` */ workload? : AuthorizeResultResponse ; /** * Result of authorization where principal is `Jans::User` */ person? : AuthorizeResultResponse ; /** * Result of authorization * true means `ALLOW` * false means `Deny` * * this field is [`bool`] type to be compatible with [authzen Access Evaluation Decision](https://openid.github.io/authzen/#section-6.2.1). */ decision : boolean ; } /** * A WASM wrapper for the Rust `cedar_policy::Response` struct. * Represents the result of an authorization request. */ export class AuthorizeResultResponse { /** * Authorization decision */ readonly decision : boolean ; /** * Diagnostics providing more information on how this decision was reached */ readonly diagnostics : Diagnostics ; } /** * Diagnostics * =========== * * Provides detailed information about how a policy decision was made, including policies that contributed to the decision and any errors encountered during evaluation. */ export class Diagnostics { /** * `PolicyId`s of the policies that contributed to the decision. * If no policies applied to the request, this set will be empty. * * The ids should be treated as unordered, */ readonly reason : ( string )[]; /** * Errors that occurred during authorization. The errors should be * treated as unordered, since policies may be evaluated in any order. */ readonly errors : ( PolicyEvaluationError )[]; } /** * PolicyEvaluationError * ===================== * * Represents an error that occurred when evaluating a Cedar policy. */ export class PolicyEvaluationError { /** * Id of the policy with an error */ readonly id : string ; /** * Underlying evaluation error string representation */ readonly error : string ; }", "title": "WASM"}, {"location": "cedarling/cedarling-wasm/#wasm-for-cedarling", "text": "Cedarling provides a binding for JavaScript programs via the wasm-pack tool. This allows browser developers to use the cedarling crate in their code directly.", "title": "WASM for Cedarling"}, {"location": "cedarling/cedarling-wasm/#requirements", "text": "Rust 1.63 or greater Installed wasm-pack via cargo clang with wasm target support", "title": "Requirements"}, {"location": "cedarling/cedarling-wasm/#building", "text": "Install wasm-pack by: cargo install wasm-pack Build cedarling wasm in release: wasm-pack build --release --target web wasm-pack automatically make optimization of wasm binary file, using wasm-opt . - Get result in the pkg folder.", "title": "Building"}, {"location": "cedarling/cedarling-wasm/#including-in-projects", "text": "For using result files in browser project you need make result pkg folder accessible for loading in the browser so that you can later import the corresponding file from the browser. Here is example of code snippet: < script type = \"module\" > import initWasm , { init } from \"/pkg/cedarling_wasm.js\" ; async function main () { await initWasm (); // Initialize the WebAssembly module // init cedarling with `BOOTSTRAP` config let instance = await init ({ \"CEDARLING_APPLICATION_NAME\" : \"My App\" , \"CEDARLING_POLICY_STORE_URI\" : \"https://example.com/policy-store.json\" , \"CEDARLING_LOG_TYPE\" : \"memory\" , \"CEDARLING_LOG_LEVEL\" : \"INFO\" , \"CEDARLING_LOG_TTL\" : 120 , \"CEDARLING_DECISION_LOG_USER_CLAIMS \" : [ \"aud\" , \"sub\" , \"email\" , \"username\" ], \"CEDARLING_DECISION_LOG_WORKLOAD_CLAIMS \" : [ \"aud\" , \"client_id\" , \"rp_id\" ], \"CEDARLING_USER_AUTHZ\" : \"enabled\" , \"CEDARLING_WORKLOAD_AUTHZ\" : \"enabled\" , \"CEDARLING_USER_WORKLOAD_BOOLEAN_OPERATION\" : \"AND\" , }); // make authorize request let result = await instance . authorize ({ \"tokens\" : { \"access_token\" : \"...\" , \"id_token\" : \"...\" , \"userinfo_token\" : \"...\" , }, \"action\" : 'Jans::Action::\"Read\"' , \"resource\" : { \"type\" : \"Jans::Application\" , \"id\" : \"some_id\" , \"app_id\" : \"application_id\" , \"name\" : \"Some Application\" , \"url\" : { \"host\" : \"jans.test\" , \"path\" : \"/protected-endpoint\" , \"protocol\" : \"http\" } }, \"context\" : { \"current_time\" : Math . floor ( Date . now () / 1000 ), \"device_health\" : [ \"Healthy\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"geolocation\" : [ \"America\" ], \"network\" : \"127.0.0.1\" , \"network_type\" : \"Local\" , \"operating_system\" : \"Linux\" , \"user_agent\" : \"Linux\" }, }); console . log ( \"result:\" , result ); } main (). catch ( console . error ); </ script >", "title": "Including in projects"}, {"location": "cedarling/cedarling-wasm/#usage", "text": "Before usage make sure that you have completed Building steps. You can find usage examples in the following locations: jans-cedarling/bindings/cedarling_wasm/index.html : A simple example demonstrating basic usage. jans-cedarling/bindings/cedarling_wasm/cedarling_app.html : A fully featured Cedarling browser app where you can test and validate your configuration.", "title": "Usage"}, {"location": "cedarling/cedarling-wasm/#defined-api", "text": "/** * Create a new instance of the Cedarling application. * This function can take as config parameter the eather `Map` other `Object` */ export function init ( config : any ) : Promise < Cedarling > ; /** * The instance of the Cedarling application. */ export class Cedarling { /** * Create a new instance of the Cedarling application. * Assume that config is `Object` */ static new ( config : object ) : Promise < Cedarling > ; /** * Create a new instance of the Cedarling application. * Assume that config is `Map` */ static new_from_map ( config : Map < any , any > ) : Promise < Cedarling > ; /** * Authorize request * makes authorization decision based on the [`Request`] */ authorize ( request : any ) : Promise < AuthorizeResult > ; /** * Get logs and remove them from the storage. * Returns `Array` of `Map` */ pop_logs () : Array < any > ; /** * Get specific log entry. * Returns `Map` with values or `null`. */ get_log_by_id ( id : string ) : any ; /** * Returns a list of all log ids. * Returns `Array` of `String` */ get_log_ids () : Array < any > ; } /** * A WASM wrapper for the Rust `cedarling::AuthorizeResult` struct. * Represents the result of an authorization request. */ export class AuthorizeResult { /** * Convert `AuthorizeResult` to json string value */ json_string () : string ; /** * Result of authorization where principal is `Jans::Workload` */ workload? : AuthorizeResultResponse ; /** * Result of authorization where principal is `Jans::User` */ person? : AuthorizeResultResponse ; /** * Result of authorization * true means `ALLOW` * false means `Deny` * * this field is [`bool`] type to be compatible with [authzen Access Evaluation Decision](https://openid.github.io/authzen/#section-6.2.1). */ decision : boolean ; } /** * A WASM wrapper for the Rust `cedar_policy::Response` struct. * Represents the result of an authorization request. */ export class AuthorizeResultResponse { /** * Authorization decision */ readonly decision : boolean ; /** * Diagnostics providing more information on how this decision was reached */ readonly diagnostics : Diagnostics ; } /** * Diagnostics * =========== * * Provides detailed information about how a policy decision was made, including policies that contributed to the decision and any errors encountered during evaluation. */ export class Diagnostics { /** * `PolicyId`s of the policies that contributed to the decision. * If no policies applied to the request, this set will be empty. * * The ids should be treated as unordered, */ readonly reason : ( string )[]; /** * Errors that occurred during authorization. The errors should be * treated as unordered, since policies may be evaluated in any order. */ readonly errors : ( PolicyEvaluationError )[]; } /** * PolicyEvaluationError * ===================== * * Represents an error that occurred when evaluating a Cedar policy. */ export class PolicyEvaluationError { /** * Id of the policy with an error */ readonly id : string ; /** * Underlying evaluation error string representation */ readonly error : string ; }", "title": "Defined API"}, {"location": "cedarling/python/sidecar/", "tags": ["cedarling", "python", "sidecar"], "text": "Flask Sidecar # The sidecar is a containerized Flask project that uses the cedarling_python binding and implements the AuthZen specification. This image can run alongside another service and uses cedarling to validate evaluation requests against a policy store. Docker setup # Ensure that you have installed docker and docker compose . Clone the Janssen repository Navigate to jans/jans-cedarling/flask-sidecar Edit the provided secrets/bootstrap.json file to your specifications. The configuration keys are described here . Run docker compose up For cloud deployments, please use the provided Dockerfile and pass your bootstrap configuration via the environment variable CEDARLING_BOOTSTRAP_CONFIG_FILE . The sidecar runs on port 5000. OpenAPI documentation is available at http://0.0.0.0:5000/swagger-ui Usage # The sidecar has one endpoint: /cedarling/evaluation . Example request to the evaluation endpoint: { \"subject\": { \"type\": \"JWT\", \"id\": \"cedarling\", \"properties\": { \"access_token\": \"\", \"id_token\": \"\", \"userinfo_token\": \"\" } }, \"resource\": { \"type\": \"Jans::Application\", \"id\": \"some_id\", \"properties\": { \"app_id\": \"application_id\", \"name\": \"Some Application\", \"url\": { \"host\": \"jans.test\", \"path\": \"/protected-endpoint\", \"protocol\": \"http\" } } }, \"action\": { \"name\": \"Jans::Action::\\\"Read\\\"\" }, \"context\": { \"device_health\": [ \"Healthy\" ], \"fraud_indicators\": [ \"Allowed\" ], \"geolocation\": [ \"America\" ], \"network\": \"127.0.0.1\", \"network_type\": \"Local\", \"operating_system\": \"Linux\", \"user_agent\": \"Linux\", \"current_time\": 1 } } Cedarling requires OpenID Userinfo, Access, and ID tokens to construct the principal entity, as described here . As per AuthZen specification, these values are sent in the context field of the payload. Conversely, the subject field is currently not used by cedarling. These 3 tokens are subsequently removed from the context object before it is passed to cedarling. Upon creating the principal, action, resource, and context entities, cedarling will evaluate these entities against the policies defined in the policy store. Then it will return a true/false decision. If the decision is false, the sidecar will analyze cedarling diagnostics and provide additional information for the admin. Example of true case: { \"decision\": true } Example of false case: { \"context\": { \"reason_admin\": { \"person diagnostics\": [], \"person error\": [], \"person evaluation\": \"DENY\", \"workload diagnostics\": [], \"workload evaluation\": \"DENY\", \"workload_error\": [] } }, \"decision\": false } In this example both the person and workload evaluations were DENY , so the decision was false. Additional information is returned in the context field as per AuthZen specification.", "title": "Sidecar"}, {"location": "cedarling/python/sidecar/#flask-sidecar", "text": "The sidecar is a containerized Flask project that uses the cedarling_python binding and implements the AuthZen specification. This image can run alongside another service and uses cedarling to validate evaluation requests against a policy store.", "title": "Flask Sidecar"}, {"location": "cedarling/python/sidecar/#docker-setup", "text": "Ensure that you have installed docker and docker compose . Clone the Janssen repository Navigate to jans/jans-cedarling/flask-sidecar Edit the provided secrets/bootstrap.json file to your specifications. The configuration keys are described here . Run docker compose up For cloud deployments, please use the provided Dockerfile and pass your bootstrap configuration via the environment variable CEDARLING_BOOTSTRAP_CONFIG_FILE . The sidecar runs on port 5000. OpenAPI documentation is available at http://0.0.0.0:5000/swagger-ui", "title": "Docker setup"}, {"location": "cedarling/python/sidecar/#usage", "text": "The sidecar has one endpoint: /cedarling/evaluation . Example request to the evaluation endpoint: { \"subject\": { \"type\": \"JWT\", \"id\": \"cedarling\", \"properties\": { \"access_token\": \"\", \"id_token\": \"\", \"userinfo_token\": \"\" } }, \"resource\": { \"type\": \"Jans::Application\", \"id\": \"some_id\", \"properties\": { \"app_id\": \"application_id\", \"name\": \"Some Application\", \"url\": { \"host\": \"jans.test\", \"path\": \"/protected-endpoint\", \"protocol\": \"http\" } } }, \"action\": { \"name\": \"Jans::Action::\\\"Read\\\"\" }, \"context\": { \"device_health\": [ \"Healthy\" ], \"fraud_indicators\": [ \"Allowed\" ], \"geolocation\": [ \"America\" ], \"network\": \"127.0.0.1\", \"network_type\": \"Local\", \"operating_system\": \"Linux\", \"user_agent\": \"Linux\", \"current_time\": 1 } } Cedarling requires OpenID Userinfo, Access, and ID tokens to construct the principal entity, as described here . As per AuthZen specification, these values are sent in the context field of the payload. Conversely, the subject field is currently not used by cedarling. These 3 tokens are subsequently removed from the context object before it is passed to cedarling. Upon creating the principal, action, resource, and context entities, cedarling will evaluate these entities against the policies defined in the policy store. Then it will return a true/false decision. If the decision is false, the sidecar will analyze cedarling diagnostics and provide additional information for the admin. Example of true case: { \"decision\": true } Example of false case: { \"context\": { \"reason_admin\": { \"person diagnostics\": [], \"person error\": [], \"person evaluation\": \"DENY\", \"workload diagnostics\": [], \"workload evaluation\": \"DENY\", \"workload_error\": [] } }, \"decision\": false } In this example both the person and workload evaluations were DENY , so the decision was false. Additional information is returned in the context field as per AuthZen specification.", "title": "Usage"}, {"location": "cedarling/python/usage/", "tags": ["cedarling", "python", "usage"], "text": "Python usage # In this example, we will show an example Python script that calls the cedarling_python module and calls the authorize() function. Before beginning, ensure that you have completed the building steps and are currently in a virtual Python environment that has the cedarling_python module installed. You can confirm this with pip list . Run the script jans/jans-cedarling/bindings/cedarling_python/example.py from within the virtual environment. Output # (venv) $ python example.py Policy store location not provided, use 'CEDARLING_LOCAL_POLICY_STORE' environment variable Used default policy store path: example_files/policy-store.json {\"id\":\"0193414e-9672-786a-986c-57f48d41c4e4\",\"time\":1731967489,\"log_type\":\"System\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"configuration parsed successfully\"} {\"id\":\"0193414e-9672-786a-986c-57f5379086c3\",\"time\":1731967489,\"log_type\":\"System\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"Cedarling Authz initialized successfully\",\"application_id\":\"TestApp\"} {\"id\":\"0193414e-9676-7d8a-b55b-3f0097355851\",\"time\":1731967489,\"log_type\":\"Decision\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"Result of authorize.\",\"application_id\":\"TestApp\",\"action\":\"Jans::Action::\\\"Read\\\"\",\"resource\":\"Jans::Application::\\\"some_id\\\"\",\"context\":{\"user_agent\":\"Linux\",\"operating_system\":\"Linux\",\"network_type\":\"Local\",\"network\":\"127.0.0.1\",\"geolocation\":[\"America\"],\"fraud_indicators\":[\"Allowed\"],\"device_health\":[\"Healthy\"],\"current_time\":1731967489},\"person_principal\":\"Jans::User::\\\"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\\\"\",\"person_diagnostics\":{\"reason\":[\"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\"],\"errors\":[]},\"person_decision\":\"ALLOW\",\"workload_principal\":\"Jans::Workload::\\\"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\\\"\",\"workload_diagnostics\":{\"reason\":[\"444da5d85403f35ea76519ed1a18a33989f855bf1cf8\"],\"errors\":[]},\"workload_decision\":\"ALLOW\",\"authorized\":true} Result of workload authorization: ALLOW Policy ID used: 444da5d85403f35ea76519ed1a18a33989f855bf1cf8 Errors during authorization: 0 Result of person authorization: ALLOW Policy ID used: 840da5d85403f35ea76519ed1a18a33989f855bf1cf8 Errors during authorization: 0 Explanation # Cedarling creates principal entities from the access, ID and userinfo tokens. The action, resource and context entities are declared in code. These four entities together form the PARC format that cedarling evaluates against policies provided in the policy store. The principal entities can be either User, Workload or Role. After forming the entities, cedarling evaluates them against the policies provided in the policy store. If entity is explicitly permitted by a policy, the result of the evaluation is ALLOW , otherwise it is DENY . In this case there are two policies in the store, one for User entities and one for Workload entities: @444da5d85403f35ea76519ed1a18a33989f855bf1cf8 permit( principal is Jans::Workload, action in [Jans::Action::\"Read\"], resource is Jans::Application )when{ resource.name == \"Some Application\" }; @840da5d85403f35ea76519ed1a18a33989f855bf1cf8 permit( principal is Jans::User, action in [Jans::Action::\"Read\"], resource is Jans::Application )when{ resource.name == \"Some Application\" }; These two policies say that a Principal entity (User or Workload) is allowed to execute a Read action on an Application resource when the resource is named \"Some Application\". As there are no policies for Role entities, the result of the evaluation for the Role entity is DENY . In the script, the action, resource and context entities are used to create the request and execute the authorize() call: action = 'Jans::Action::\"Read\"' resource = ResourceData . from_dict ({ \"type\" : \"Jans::Application\" , \"id\" : \"some_id\" , \"app_id\" : \"application_id\" , \"name\" : \"Some Application\" , \"url\" : { \"host\" : \"jans.test\" , \"path\" : \"/protected-endpoint\" , \"protocol\" : \"http\" } }) context = { \"current_time\" : int ( time . time ()), \"device_health\" : [ \"Healthy\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"geolocation\" : [ \"America\" ], \"network\" : \"127.0.0.1\" , \"network_type\" : \"Local\" , \"operating_system\" : \"Linux\" , \"user_agent\" : \"Linux\" } request = Request ( access_token , id_token , userinfo_token , action = action , resource = resource , context = context ) authorize_result = instance . authorize ( request ) assert authorize_result . is_allowed () Cedarling will return is_allowed() as True only if both the User and Workload entity evaluations are ALLOW . Exposed functions # The pyo3 binding for cedarling exposes a number of cedarling functions for you to use. The documentation on this can be found here .", "title": "How to use"}, {"location": "cedarling/python/usage/#python-usage", "text": "In this example, we will show an example Python script that calls the cedarling_python module and calls the authorize() function. Before beginning, ensure that you have completed the building steps and are currently in a virtual Python environment that has the cedarling_python module installed. You can confirm this with pip list . Run the script jans/jans-cedarling/bindings/cedarling_python/example.py from within the virtual environment.", "title": "Python usage"}, {"location": "cedarling/python/usage/#output", "text": "(venv) $ python example.py Policy store location not provided, use 'CEDARLING_LOCAL_POLICY_STORE' environment variable Used default policy store path: example_files/policy-store.json {\"id\":\"0193414e-9672-786a-986c-57f48d41c4e4\",\"time\":1731967489,\"log_type\":\"System\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"configuration parsed successfully\"} {\"id\":\"0193414e-9672-786a-986c-57f5379086c3\",\"time\":1731967489,\"log_type\":\"System\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"Cedarling Authz initialized successfully\",\"application_id\":\"TestApp\"} {\"id\":\"0193414e-9676-7d8a-b55b-3f0097355851\",\"time\":1731967489,\"log_type\":\"Decision\",\"pdp_id\":\"c0ec33ff-9482-4bdc-83f6-2925a41a3280\",\"msg\":\"Result of authorize.\",\"application_id\":\"TestApp\",\"action\":\"Jans::Action::\\\"Read\\\"\",\"resource\":\"Jans::Application::\\\"some_id\\\"\",\"context\":{\"user_agent\":\"Linux\",\"operating_system\":\"Linux\",\"network_type\":\"Local\",\"network\":\"127.0.0.1\",\"geolocation\":[\"America\"],\"fraud_indicators\":[\"Allowed\"],\"device_health\":[\"Healthy\"],\"current_time\":1731967489},\"person_principal\":\"Jans::User::\\\"qzxn1Scrb9lWtGxVedMCky-Ql_ILspZaQA6fyuYktw0\\\"\",\"person_diagnostics\":{\"reason\":[\"840da5d85403f35ea76519ed1a18a33989f855bf1cf8\"],\"errors\":[]},\"person_decision\":\"ALLOW\",\"workload_principal\":\"Jans::Workload::\\\"d7f71bea-c38d-4caf-a1ba-e43c74a11a62\\\"\",\"workload_diagnostics\":{\"reason\":[\"444da5d85403f35ea76519ed1a18a33989f855bf1cf8\"],\"errors\":[]},\"workload_decision\":\"ALLOW\",\"authorized\":true} Result of workload authorization: ALLOW Policy ID used: 444da5d85403f35ea76519ed1a18a33989f855bf1cf8 Errors during authorization: 0 Result of person authorization: ALLOW Policy ID used: 840da5d85403f35ea76519ed1a18a33989f855bf1cf8 Errors during authorization: 0", "title": "Output"}, {"location": "cedarling/python/usage/#explanation", "text": "Cedarling creates principal entities from the access, ID and userinfo tokens. The action, resource and context entities are declared in code. These four entities together form the PARC format that cedarling evaluates against policies provided in the policy store. The principal entities can be either User, Workload or Role. After forming the entities, cedarling evaluates them against the policies provided in the policy store. If entity is explicitly permitted by a policy, the result of the evaluation is ALLOW , otherwise it is DENY . In this case there are two policies in the store, one for User entities and one for Workload entities: @444da5d85403f35ea76519ed1a18a33989f855bf1cf8 permit( principal is Jans::Workload, action in [Jans::Action::\"Read\"], resource is Jans::Application )when{ resource.name == \"Some Application\" }; @840da5d85403f35ea76519ed1a18a33989f855bf1cf8 permit( principal is Jans::User, action in [Jans::Action::\"Read\"], resource is Jans::Application )when{ resource.name == \"Some Application\" }; These two policies say that a Principal entity (User or Workload) is allowed to execute a Read action on an Application resource when the resource is named \"Some Application\". As there are no policies for Role entities, the result of the evaluation for the Role entity is DENY . In the script, the action, resource and context entities are used to create the request and execute the authorize() call: action = 'Jans::Action::\"Read\"' resource = ResourceData . from_dict ({ \"type\" : \"Jans::Application\" , \"id\" : \"some_id\" , \"app_id\" : \"application_id\" , \"name\" : \"Some Application\" , \"url\" : { \"host\" : \"jans.test\" , \"path\" : \"/protected-endpoint\" , \"protocol\" : \"http\" } }) context = { \"current_time\" : int ( time . time ()), \"device_health\" : [ \"Healthy\" ], \"fraud_indicators\" : [ \"Allowed\" ], \"geolocation\" : [ \"America\" ], \"network\" : \"127.0.0.1\" , \"network_type\" : \"Local\" , \"operating_system\" : \"Linux\" , \"user_agent\" : \"Linux\" } request = Request ( access_token , id_token , userinfo_token , action = action , resource = resource , context = context ) authorize_result = instance . authorize ( request ) assert authorize_result . is_allowed () Cedarling will return is_allowed() as True only if both the User and Workload entity evaluations are ALLOW .", "title": "Explanation"}, {"location": "cedarling/python/usage/#exposed-functions", "text": "The pyo3 binding for cedarling exposes a number of cedarling functions for you to use. The documentation on this can be found here .", "title": "Exposed functions"}, {"location": "contribute/developer-faq/", "tags": ["developer", "faq"], "text": "Developer FAQs # How to enable debug logs for jans-cli and TUI configuration tools # By default, logging is not enabled for CLI or TUI tools on Janssen Server. Follow the steps below to enable and configure logging for CLI and TUI tools: Log in as root user open config file for editing ~/.config/jans-cli.ini Update value for debug to true and add new entry for log_dir key with value pointing to directory where logs need to be generated. e.g debug = true log_dir = /opt/jans Close currently open TUI session if any and open a new one Logs should get available at location configured in log_dir in files cli_debug.log and dev-tui.log How to get certificate from Let's encrypt # Let's Encrypt is a CA that provides free CA certificates. You can use these certificates to enable HTTPS communication with Janssen Server. Refer to this guide from Let's Encrypt to know more. We have compiled a set of commands for different OS platforms to help you as a quick reference to generate Let's Encrypt CA certificates. Suse # sudo zypper -n install certbot sudo certbot certonly --webroot -w /srv/www/htdocs -d FQDN Ubuntu # sudo apt update && sudo apt install certbot python3-certbot-apache sudo certbot --apache -d FQDN To check certbot status sudo systemctl status certbot.timer To renew certificate run sudo certbot renew --dry-run RHEL # sudo yum install certbot python3-certbot-apache sudo certbot certonly --apache How to install Janssen Server OpenBanking for testing? # Note Use this installation for testing only Good understanding of Janssen Server installation process in general is a prerequisite. Here we are just highlighting steps without a lot of details. Visit installation documentation for complete understanding. This installation uses Gluu Testing certificate. Download Installer # wget https://raw.githubusercontent.com/JanssenProject/jans/vreplace-janssen-version/jans-linux-setup/jans_setup/install.py -O install.py Execute Installer # python3 install.py --profile=openbanking --args=\"-ob-key-fn=/opt/jans/jans-setup/openbanking/static/ob-gluu-test.key -static-kid=ob-gluu-test -jwks-uri=https://ox.gluu.org/icrby8xcvbcv/ob/ob-gluu-test.jwks --disable-ob-auth-script -ob-alias=ob-gluu-test\" Please enter defaults for the following questions (press just enter key), it will download certificate from jwksUri Use external key? [Y|n] : y Openbanking Key File [/opt/jans/jans-setup/openbanking/static/ob-gluu-test.key] : Openbanking Certificate File [/root/obsigning.pem] : Openbanking Key Alias [ob-gluu-test] : Configure Certificate # jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key Test # This test uses Gluu Testing certificate. device authentication # After installation we have to complete device authentication to use openbanking. Testing using IM mode # launch jans-cli using below command jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key further testing is same as jans server Testing using command line mode # we can run below command at command line. for ex: jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key \u2013operation-id get-oauth-openid-clients same way we can run other commands. rest is same for jans and openbanking", "title": "Developer FAQ"}, {"location": "contribute/developer-faq/#developer-faqs", "text": "", "title": "Developer FAQs"}, {"location": "contribute/developer-faq/#how-to-enable-debug-logs-for-jans-cli-and-tui-configuration-tools", "text": "By default, logging is not enabled for CLI or TUI tools on Janssen Server. Follow the steps below to enable and configure logging for CLI and TUI tools: Log in as root user open config file for editing ~/.config/jans-cli.ini Update value for debug to true and add new entry for log_dir key with value pointing to directory where logs need to be generated. e.g debug = true log_dir = /opt/jans Close currently open TUI session if any and open a new one Logs should get available at location configured in log_dir in files cli_debug.log and dev-tui.log", "title": "How to enable debug logs for jans-cli and TUI configuration tools"}, {"location": "contribute/developer-faq/#how-to-get-certificate-from-lets-encrypt", "text": "Let's Encrypt is a CA that provides free CA certificates. You can use these certificates to enable HTTPS communication with Janssen Server. Refer to this guide from Let's Encrypt to know more. We have compiled a set of commands for different OS platforms to help you as a quick reference to generate Let's Encrypt CA certificates.", "title": "How to get certificate from Let's encrypt"}, {"location": "contribute/developer-faq/#suse", "text": "sudo zypper -n install certbot sudo certbot certonly --webroot -w /srv/www/htdocs -d FQDN", "title": "Suse"}, {"location": "contribute/developer-faq/#ubuntu", "text": "sudo apt update && sudo apt install certbot python3-certbot-apache sudo certbot --apache -d FQDN To check certbot status sudo systemctl status certbot.timer To renew certificate run sudo certbot renew --dry-run", "title": "Ubuntu"}, {"location": "contribute/developer-faq/#rhel", "text": "sudo yum install certbot python3-certbot-apache sudo certbot certonly --apache", "title": "RHEL"}, {"location": "contribute/developer-faq/#how-to-install-janssen-server-openbanking-for-testing", "text": "Note Use this installation for testing only Good understanding of Janssen Server installation process in general is a prerequisite. Here we are just highlighting steps without a lot of details. Visit installation documentation for complete understanding. This installation uses Gluu Testing certificate.", "title": "How to install Janssen Server OpenBanking for testing?"}, {"location": "contribute/developer-faq/#download-installer", "text": "wget https://raw.githubusercontent.com/JanssenProject/jans/vreplace-janssen-version/jans-linux-setup/jans_setup/install.py -O install.py", "title": "Download Installer"}, {"location": "contribute/developer-faq/#execute-installer", "text": "python3 install.py --profile=openbanking --args=\"-ob-key-fn=/opt/jans/jans-setup/openbanking/static/ob-gluu-test.key -static-kid=ob-gluu-test -jwks-uri=https://ox.gluu.org/icrby8xcvbcv/ob/ob-gluu-test.jwks --disable-ob-auth-script -ob-alias=ob-gluu-test\" Please enter defaults for the following questions (press just enter key), it will download certificate from jwksUri Use external key? [Y|n] : y Openbanking Key File [/opt/jans/jans-setup/openbanking/static/ob-gluu-test.key] : Openbanking Certificate File [/root/obsigning.pem] : Openbanking Key Alias [ob-gluu-test] :", "title": "Execute Installer"}, {"location": "contribute/developer-faq/#configure-certificate", "text": "jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key", "title": "Configure Certificate"}, {"location": "contribute/developer-faq/#test", "text": "This test uses Gluu Testing certificate.", "title": "Test"}, {"location": "contribute/developer-faq/#device-authentication", "text": "After installation we have to complete device authentication to use openbanking.", "title": "device authentication"}, {"location": "contribute/developer-faq/#testing-using-im-mode", "text": "launch jans-cli using below command jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key further testing is same as jans server", "title": "Testing using IM mode"}, {"location": "contribute/developer-faq/#testing-using-command-line-mode", "text": "we can run below command at command line. for ex: jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key \u2013operation-id get-oauth-openid-clients same way we can run other commands. rest is same for jans and openbanking", "title": "Testing using command line mode"}, {"location": "contribute/development/", "text": "Developing for Janssen Project # Remote Debugging # Janssen Server modules run as Java processes. Hence, like any other Java process the JVM running the module can be configured to open a debug port where a remote debugger can be attached. The steps below will show how to configure auth-server module for remote debugging. Pass the command-line options to the JVM On the Janssen Server host, open the service config file /etc/default/jans-auth and add the following JVM parameters to as JAVA_OPTIONS -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=6001 This will open the port 6001 for the remote debugger. Any other port can also be used based on availability. Restart jans-auth services systemctl restart jans-auth.service Check if the port is open and accessible from within the Janssen Server host Use the jdb tool from JDK to test if the JVM port has been opened ./<path-to-JDK>/bin/jdb -attach 6001 if the port is open, it'll give you output like the below: Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... > press ctrl+c to come out of it. Ensure that the port is accessible from outside the host VM as well and firewalls are configured accordingly Connect to the remote port on the Janssen Server host from the developer workstation. Use any IDE (Intellij, Eclipse, etc.) to create and run a remote debugging profile. Provide IP and debug port of the Janssen Server host. For IntelliJIdea, create a debug configuration as below: Run Integration Tests with a Janssen Server VM # In this guide, we will look at steps to run the Janssen integration test suite against an installed Janssen Server. Component Setup # Instructions in this guide can be used if Janssen Server is installed on a VM. Developers can use a virtualization software (like VMWare) or use LxD containers to create VM on developer workstation or use a remote cloud VM. OS platform for Developer Workstation Steps in this guide are applicable to any OS platform a Developer workstation may have. Example commands given in this guide are for Ubuntu Linux based workstation. Install Janssen Server # Install the Janssen server using one of the methods described in the VM installation guide. Note the points below when following installation instructions. Make a note of the host name that you assign to the Janssen server during the installation. For this guide, the Janssen hostname would be janssen.op.io Choose to install with test data load. This can be achieved by using the -t switch when invoking the setup script from installation instructions. Use the VM installation guide for the complete set of instructions. Once the installation is complete, check if the .well-known end-points of the Janssen server from the browser. A successful response will ascertain that the The Janssen server running inside the local VM is healthy and also accessible from the developer's machine. Note Based on developer setup it may be necessary to add appropriate IP-HOST mapping to the developer workstation. For instance, on a Linux-based developer workstation, this means adding a mapping to /etc/hosts file. Make sure that VM's IP is mapped to a FQDN like janssen.op.io . Refering to VM with localhost or just IP will not work. URI for OpenID configuration .well-known endpoint: https://janssen.op.io/jans-auth/.well-known/openid-configuration The response received should be JSON formatted Janssen configuration details, similar to those below. { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://janssen.op.io\", \"userinfo_encryption_enc_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"authorization_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_generation_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/id\", \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"user_name\", \"formatted\", \"phone_mobile_number\", \"preferred_username\", \"inum\", \"locale\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"scope_to_claims_mapping\" : [ { \"user_name\" : [ \"user_name\" ] }, { \"https://jans.io/scim/users.write\" : [ ] }, { \"https://jans.io/scim/groups.read\" : [ ] }, { \"https://jans.io/scim/all-resources.search\" : [ ] }, { \"https://jans.io/scim/fido.write\" : [ ] }, { \"https://jans.io/scim/groups.write\" : [ ] }, { \"https://jans.io/scim/fido2.read\" : [ ] }, { \"https://jans.io/scim/fido.read\" : [ ] }, { \"https://jans.io/scim/fido2.write\" : [ ] Setup The Certificates # To run the tests against the installed Janssen Server, the workstation JRE needs to have the appropriate certificate installed. Update cacerts using the steps below: extract certificate for Janssen server with name janssen.op.io On Developer Workstation openssl s_client -connect test.local.jans.io:443 2 > & 1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/httpd.crt this command takes a few seconds to return. Update cacerts of your JRE which is being used by the code workspace. For example, /usr/lib/jvm/java-11-amazon-corretto . When running the command below, it will prompt for cert store password. Provide the correct password. The default password is changeit . keytool -import -alias janssen.op.io -keystore /usr/lib/jvm/java-11-amazon-corretto/lib/security/cacerts -file /tmp/httpd.crt Configure developer workspace # Now that we have Janssen Server running in a VM and it is accessible from the developer workstation as well, we will create and configure the code base on the developer workspace to run integration tests. Get Janssen server code from Janssen GitHub repository . Note the path to this location, we will refer to it as source-base . Janssen Server is composed of multiple modules. For example source-base/jans-auth-server , source-base/jans-link etc. Each module has its own set of tests. Below are the instructions for configuring each module for tests. What is a Profile directory? To run integration tests, the developer workspace needs to know details about he Janssen Server agaist which the tests are to be run. Janssen Server workspace holds this information in source-base/module/sub-module/profiles directory. The profiles directory can contain one or more sub-directories, each representing a profile(i.e a target Janssen Server). These profile directories are used to hold files that contain important information required to run tests. Developers can create one or more profiles and use them to run tests against different Janssen Servers. This guide uses Janssen Server hostname, janssen.op.io , as profile name. Configuring the jans-auth-server module # Configuring jans-auth-server module involves setting up profiles for client , server and agama sub-modules. Follow the steps below to configure the profile for the client and server sub-modules. Move to the module directory cd source-base/jans-auth-server As a precautionary measure, let's first remove any old profile artifacts from the jans-auth-server workspace. rm -rf ./jans-auth rm -rf ./client/profiles/janssen.op.io rm -rf ./server/profiles/janssen.op.io rm -rf ./agama/engine/profiles/janssen.op.io Since Janssen Server has been installed with test data, the installer also created the profile files required to run the test. These files are kept on the VM under /opt/jans/jans-setup/output/test/jans-auth directory. Copy over jans-auth directory from Janssen Server VM to source-base/jans-auth-server on developer workstation. Create new profile directories. mkdir -p ./client/profiles/janssen.op.io mkdir -p ./server/profiles/janssen.op.io mkdir -p ./agama/engine/profiles/janssen.op.io Copy the contents of jans-auth directory into the respective sub-module's janssen.op.io profile directory cp ./jans-auth/client/* ./client/profiles/janssen.op.io cp ./jans-auth/server/* ./server/profiles/janssen.op.io cp ./jans-auth/config-agama-test.properties ./agama/engine/profiles/janssen.op.io/config-agama-test.properties Copy keystore file profiles/default/client_keystore.p12 from default profile directory to the janssen.op.io profile directory cp -f ./client/profiles/default/client_keystore.p12 ./client/profiles/janssen.op.io cp -f ./server/profiles/default/client_keystore.p12 ./server/profiles/janssen.op.io Running The Tests # Each module in Janssen Server has its tests that have to be executed separately. For example, to run integration tests for jans-auth-server module, run the following maven command at the directory level: mvn -Dcfg=janssen.op.io test Configuring the jans-core module # This module does not require a profile setup. It can be built with below maven command. mvn clean compile install Configuring the jans-link module # This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install Configuring the jans-orm module # This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install Configuring the agama module # This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install Configuring the SCIM module # This module does not require a profile setup. It can be built with the below maven command. Profile setup for client and server modules # Many Janssen Server modules and sub-modules use test configuration stored in a directory named profile . The profile directory contains files that hold important information required to run tests. Developers can create one or more profiles and use them to run tests against different Janssen Servers. Since Janssen Server has been installed with test data, the installer also created the profile files required to run the test. For SCIM/client module, these files are kept on the VM under /opt/jans/jans-setup/output/test/scim-client directory. Copy over this directory to any location on the developer workstation. Follow the steps below to configure the profile for the client module. The same steps should be followed for setting up a profile for the server module. Under jans-scim/client/profiles directory, create a new directory and name it janssen.op.io Copy the contents of scim-client/client directory into the newly created janssen.op.io directory Post this, remove the scim-client directory. Now as the profile is setup, to build the jans-scim module and run tests, use the command below: mvn -Dcfg=janssen.op.io test Setup Janssen Schema with Test data # Useful Tools # While working with Janssen Server, either as developer or administrator, following tools can come in handy. jsonbin.io jwt.io oidcdebugger.com keytool.online", "title": "Development"}, {"location": "contribute/development/#developing-for-janssen-project", "text": "", "title": "Developing for Janssen Project"}, {"location": "contribute/development/#remote-debugging", "text": "Janssen Server modules run as Java processes. Hence, like any other Java process the JVM running the module can be configured to open a debug port where a remote debugger can be attached. The steps below will show how to configure auth-server module for remote debugging. Pass the command-line options to the JVM On the Janssen Server host, open the service config file /etc/default/jans-auth and add the following JVM parameters to as JAVA_OPTIONS -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=6001 This will open the port 6001 for the remote debugger. Any other port can also be used based on availability. Restart jans-auth services systemctl restart jans-auth.service Check if the port is open and accessible from within the Janssen Server host Use the jdb tool from JDK to test if the JVM port has been opened ./<path-to-JDK>/bin/jdb -attach 6001 if the port is open, it'll give you output like the below: Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... > press ctrl+c to come out of it. Ensure that the port is accessible from outside the host VM as well and firewalls are configured accordingly Connect to the remote port on the Janssen Server host from the developer workstation. Use any IDE (Intellij, Eclipse, etc.) to create and run a remote debugging profile. Provide IP and debug port of the Janssen Server host. For IntelliJIdea, create a debug configuration as below:", "title": "Remote Debugging"}, {"location": "contribute/development/#run-integration-tests-with-a-janssen-server-vm", "text": "In this guide, we will look at steps to run the Janssen integration test suite against an installed Janssen Server.", "title": "Run Integration Tests with a Janssen Server VM"}, {"location": "contribute/development/#component-setup", "text": "Instructions in this guide can be used if Janssen Server is installed on a VM. Developers can use a virtualization software (like VMWare) or use LxD containers to create VM on developer workstation or use a remote cloud VM. OS platform for Developer Workstation Steps in this guide are applicable to any OS platform a Developer workstation may have. Example commands given in this guide are for Ubuntu Linux based workstation.", "title": "Component Setup"}, {"location": "contribute/development/#install-janssen-server", "text": "Install the Janssen server using one of the methods described in the VM installation guide. Note the points below when following installation instructions. Make a note of the host name that you assign to the Janssen server during the installation. For this guide, the Janssen hostname would be janssen.op.io Choose to install with test data load. This can be achieved by using the -t switch when invoking the setup script from installation instructions. Use the VM installation guide for the complete set of instructions. Once the installation is complete, check if the .well-known end-points of the Janssen server from the browser. A successful response will ascertain that the The Janssen server running inside the local VM is healthy and also accessible from the developer's machine. Note Based on developer setup it may be necessary to add appropriate IP-HOST mapping to the developer workstation. For instance, on a Linux-based developer workstation, this means adding a mapping to /etc/hosts file. Make sure that VM's IP is mapped to a FQDN like janssen.op.io . Refering to VM with localhost or just IP will not work. URI for OpenID configuration .well-known endpoint: https://janssen.op.io/jans-auth/.well-known/openid-configuration The response received should be JSON formatted Janssen configuration details, similar to those below. { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://janssen.op.io\", \"userinfo_encryption_enc_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"authorization_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_generation_endpoint\" : \"https://janssen.op.io/jans-auth/restv1/id\", \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"user_name\", \"formatted\", \"phone_mobile_number\", \"preferred_username\", \"inum\", \"locale\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"scope_to_claims_mapping\" : [ { \"user_name\" : [ \"user_name\" ] }, { \"https://jans.io/scim/users.write\" : [ ] }, { \"https://jans.io/scim/groups.read\" : [ ] }, { \"https://jans.io/scim/all-resources.search\" : [ ] }, { \"https://jans.io/scim/fido.write\" : [ ] }, { \"https://jans.io/scim/groups.write\" : [ ] }, { \"https://jans.io/scim/fido2.read\" : [ ] }, { \"https://jans.io/scim/fido.read\" : [ ] }, { \"https://jans.io/scim/fido2.write\" : [ ]", "title": "Install Janssen Server"}, {"location": "contribute/development/#setup-the-certificates", "text": "To run the tests against the installed Janssen Server, the workstation JRE needs to have the appropriate certificate installed. Update cacerts using the steps below: extract certificate for Janssen server with name janssen.op.io On Developer Workstation openssl s_client -connect test.local.jans.io:443 2 > & 1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/httpd.crt this command takes a few seconds to return. Update cacerts of your JRE which is being used by the code workspace. For example, /usr/lib/jvm/java-11-amazon-corretto . When running the command below, it will prompt for cert store password. Provide the correct password. The default password is changeit . keytool -import -alias janssen.op.io -keystore /usr/lib/jvm/java-11-amazon-corretto/lib/security/cacerts -file /tmp/httpd.crt", "title": "Setup The Certificates"}, {"location": "contribute/development/#configure-developer-workspace", "text": "Now that we have Janssen Server running in a VM and it is accessible from the developer workstation as well, we will create and configure the code base on the developer workspace to run integration tests. Get Janssen server code from Janssen GitHub repository . Note the path to this location, we will refer to it as source-base . Janssen Server is composed of multiple modules. For example source-base/jans-auth-server , source-base/jans-link etc. Each module has its own set of tests. Below are the instructions for configuring each module for tests. What is a Profile directory? To run integration tests, the developer workspace needs to know details about he Janssen Server agaist which the tests are to be run. Janssen Server workspace holds this information in source-base/module/sub-module/profiles directory. The profiles directory can contain one or more sub-directories, each representing a profile(i.e a target Janssen Server). These profile directories are used to hold files that contain important information required to run tests. Developers can create one or more profiles and use them to run tests against different Janssen Servers. This guide uses Janssen Server hostname, janssen.op.io , as profile name.", "title": "Configure developer workspace"}, {"location": "contribute/development/#configuring-the-jans-auth-server-module", "text": "Configuring jans-auth-server module involves setting up profiles for client , server and agama sub-modules. Follow the steps below to configure the profile for the client and server sub-modules. Move to the module directory cd source-base/jans-auth-server As a precautionary measure, let's first remove any old profile artifacts from the jans-auth-server workspace. rm -rf ./jans-auth rm -rf ./client/profiles/janssen.op.io rm -rf ./server/profiles/janssen.op.io rm -rf ./agama/engine/profiles/janssen.op.io Since Janssen Server has been installed with test data, the installer also created the profile files required to run the test. These files are kept on the VM under /opt/jans/jans-setup/output/test/jans-auth directory. Copy over jans-auth directory from Janssen Server VM to source-base/jans-auth-server on developer workstation. Create new profile directories. mkdir -p ./client/profiles/janssen.op.io mkdir -p ./server/profiles/janssen.op.io mkdir -p ./agama/engine/profiles/janssen.op.io Copy the contents of jans-auth directory into the respective sub-module's janssen.op.io profile directory cp ./jans-auth/client/* ./client/profiles/janssen.op.io cp ./jans-auth/server/* ./server/profiles/janssen.op.io cp ./jans-auth/config-agama-test.properties ./agama/engine/profiles/janssen.op.io/config-agama-test.properties Copy keystore file profiles/default/client_keystore.p12 from default profile directory to the janssen.op.io profile directory cp -f ./client/profiles/default/client_keystore.p12 ./client/profiles/janssen.op.io cp -f ./server/profiles/default/client_keystore.p12 ./server/profiles/janssen.op.io", "title": "Configuring the jans-auth-server module"}, {"location": "contribute/development/#running-the-tests", "text": "Each module in Janssen Server has its tests that have to be executed separately. For example, to run integration tests for jans-auth-server module, run the following maven command at the directory level: mvn -Dcfg=janssen.op.io test", "title": "Running The Tests"}, {"location": "contribute/development/#configuring-the-jans-core-module", "text": "This module does not require a profile setup. It can be built with below maven command. mvn clean compile install", "title": "Configuring the jans-core module"}, {"location": "contribute/development/#configuring-the-jans-link-module", "text": "This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install", "title": "Configuring the jans-link module"}, {"location": "contribute/development/#configuring-the-jans-orm-module", "text": "This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install", "title": "Configuring the jans-orm module"}, {"location": "contribute/development/#configuring-the-agama-module", "text": "This module does not require a profile setup. It can be built with the below maven command. mvn clean compile install", "title": "Configuring the agama module"}, {"location": "contribute/development/#configuring-the-scim-module", "text": "This module does not require a profile setup. It can be built with the below maven command.", "title": "Configuring the SCIM module"}, {"location": "contribute/development/#profile-setup-for-client-and-server-modules", "text": "Many Janssen Server modules and sub-modules use test configuration stored in a directory named profile . The profile directory contains files that hold important information required to run tests. Developers can create one or more profiles and use them to run tests against different Janssen Servers. Since Janssen Server has been installed with test data, the installer also created the profile files required to run the test. For SCIM/client module, these files are kept on the VM under /opt/jans/jans-setup/output/test/scim-client directory. Copy over this directory to any location on the developer workstation. Follow the steps below to configure the profile for the client module. The same steps should be followed for setting up a profile for the server module. Under jans-scim/client/profiles directory, create a new directory and name it janssen.op.io Copy the contents of scim-client/client directory into the newly created janssen.op.io directory Post this, remove the scim-client directory. Now as the profile is setup, to build the jans-scim module and run tests, use the command below: mvn -Dcfg=janssen.op.io test", "title": "Profile setup for client and server modules"}, {"location": "contribute/development/#setup-janssen-schema-with-test-data", "text": "", "title": "Setup Janssen Schema with Test data"}, {"location": "contribute/development/#useful-tools", "text": "While working with Janssen Server, either as developer or administrator, following tools can come in handy. jsonbin.io jwt.io oidcdebugger.com keytool.online", "title": "Useful Tools"}, {"location": "contribute/testing/", "tags": ["administration", "contribute", "Testing", "Quality Assurance"], "text": "Test And Quality Assurance For Janssen Project # The Janssen Project is a large, complex project with tons of inter-dependency. If we aren't test-driven, anarchy will ensue. Every line of code at Janssen Project goes through various tests at different stages of development. Most of these tests are automated and executed as part of our CI-CD pipeline, while others are executed manually. Unit testing # Do not submit any code without a corresponding unit test. Also, any bug fixes should increment unit test coverage. All unit tests are executed with any subsequent Jenkins build. Component testing # Component testing uses real world use cases to exercise a portion of the software, using typical data inputs. Developers should document component stories and submit them to the component test library for the respective repository. A tester should be able to run component tests manually. Component tests should run automatically with each Jenkins build. The OpenID Foundation certification tests supplement the component testing library, and should be run for each major release of the software for which they are available. Performance testing # Performance tests are critical to optimization of the persistence and caching implementation. All major releases of the software should be tested for performance with all supported database and cache configurations using the Cloud Native distribution. The VM distribution will not be performance tested, as the main goal for this distribution is development and small deployments. The JMeter test tool should be used to generate the load. These tests are published so community members can run their own bench-marking analysis. HA Tests # HA tests should be run against the Cloud Native distribution, which by design is active-active with no single point of failure. The HA testing should simulate taking down various pieces of infrastructure, to see if authentications can still proceed. Also, what happens to transactions that were in progress during the crash? Penetration tests # Penetration testing is highly deployment specific. Depending on different implementations of the Janssen Project software, you may achieve different levels of risk mitigation. Thus it is important that organizations that operate their own IAM platform based on Janssen perform their own penetration testing. Dependency Vulnerabilities # Dependency vulnerabilities are monitored by Gihub. In addition we plan to use the Linux Foundation Community Bridge vulnerability detection platform. Testing Documentation Changes Locally # While contributing documentation to official Janssen Project documentation it is important to make sure that documents meet style guidelines and have been proofread to remove any typographical or grammatical errors. Janssen Project uses Material for MkDocs to create the documenation site. Before new content is pushed to the repository on GitHub, it should be tested locally by the author. Author can do this by deploying Material for MkDocs locally. High-level steps involve: Install Material for MkDocs Install required plugins Preview as you write Open Banking # We are working on developing this content under issue 2548 . If you\u2019d like to contribute the content, get started with the Contribution Guide How to test OpenBanking? # This test uses a Gluu Testing Certificate. device authentication # After installation, we have to complete device authentication to use OpenBanking. Testing using commnd line mode # We can run the below command on the command line. For example: jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key \u2013operation-id get-oauth-openid-clients in the same way we can run other commands. Rest of the testing is same for jans and openbanking. Release Quality Assurance # Once all the code changes for a particular release have been committed, we perform a set of tests and go through a list of checkpoints to make sure release candidate (RC) build is healthy and functioning well. Pre-release QA checklist # As part of pre-release QA check, we run a set of manual sanity checks on test environments with various deployment configurations. Test Environments # # OS Platform Persistance Type Deployment Type (VM/CN) Test 2 SUSE 15 Mysql VM installation and sanity testing 3 SUSE 15 Pgsql VM installation and sanity testing 5 RHEL 8 Mysql VM installation and sanity testing 6 RHEL 8 Pgsql VM installation and sanity testing 8 Ubuntu20 Mysql VM installation and sanity testing 9 Ubuntu20 Pgsql VM installation and sanity testing 11 Ubuntu22 Mysql VM installation and sanity testing 12 Ubuntu22 Pgsql VM installation and sanity testing Sanity checks # Review functioning of .well-known endpoints for OpenId, Fido, UMA, SCIM modules Test device authentication flow using TUI Test password authentication flow using Janssen Server Tent Test Agama project deployment and functioning Post-release QA checklist # # QA Checks 1 Package installation verification on all OS Platforms as in pre-release tests", "title": "Testing"}, {"location": "contribute/testing/#test-and-quality-assurance-for-janssen-project", "text": "The Janssen Project is a large, complex project with tons of inter-dependency. If we aren't test-driven, anarchy will ensue. Every line of code at Janssen Project goes through various tests at different stages of development. Most of these tests are automated and executed as part of our CI-CD pipeline, while others are executed manually.", "title": "Test And Quality Assurance For Janssen Project"}, {"location": "contribute/testing/#unit-testing", "text": "Do not submit any code without a corresponding unit test. Also, any bug fixes should increment unit test coverage. All unit tests are executed with any subsequent Jenkins build.", "title": "Unit testing"}, {"location": "contribute/testing/#component-testing", "text": "Component testing uses real world use cases to exercise a portion of the software, using typical data inputs. Developers should document component stories and submit them to the component test library for the respective repository. A tester should be able to run component tests manually. Component tests should run automatically with each Jenkins build. The OpenID Foundation certification tests supplement the component testing library, and should be run for each major release of the software for which they are available.", "title": "Component testing"}, {"location": "contribute/testing/#performance-testing", "text": "Performance tests are critical to optimization of the persistence and caching implementation. All major releases of the software should be tested for performance with all supported database and cache configurations using the Cloud Native distribution. The VM distribution will not be performance tested, as the main goal for this distribution is development and small deployments. The JMeter test tool should be used to generate the load. These tests are published so community members can run their own bench-marking analysis.", "title": "Performance testing"}, {"location": "contribute/testing/#ha-tests", "text": "HA tests should be run against the Cloud Native distribution, which by design is active-active with no single point of failure. The HA testing should simulate taking down various pieces of infrastructure, to see if authentications can still proceed. Also, what happens to transactions that were in progress during the crash?", "title": "HA Tests"}, {"location": "contribute/testing/#penetration-tests", "text": "Penetration testing is highly deployment specific. Depending on different implementations of the Janssen Project software, you may achieve different levels of risk mitigation. Thus it is important that organizations that operate their own IAM platform based on Janssen perform their own penetration testing.", "title": "Penetration tests"}, {"location": "contribute/testing/#dependency-vulnerabilities", "text": "Dependency vulnerabilities are monitored by Gihub. In addition we plan to use the Linux Foundation Community Bridge vulnerability detection platform.", "title": "Dependency Vulnerabilities"}, {"location": "contribute/testing/#testing-documentation-changes-locally", "text": "While contributing documentation to official Janssen Project documentation it is important to make sure that documents meet style guidelines and have been proofread to remove any typographical or grammatical errors. Janssen Project uses Material for MkDocs to create the documenation site. Before new content is pushed to the repository on GitHub, it should be tested locally by the author. Author can do this by deploying Material for MkDocs locally. High-level steps involve: Install Material for MkDocs Install required plugins Preview as you write", "title": "Testing Documentation Changes Locally"}, {"location": "contribute/testing/#open-banking", "text": "We are working on developing this content under issue 2548 . If you\u2019d like to contribute the content, get started with the Contribution Guide", "title": "Open Banking"}, {"location": "contribute/testing/#how-to-test-openbanking", "text": "This test uses a Gluu Testing Certificate.", "title": "How to test OpenBanking?"}, {"location": "contribute/testing/#device-authentication", "text": "After installation, we have to complete device authentication to use OpenBanking.", "title": "device authentication"}, {"location": "contribute/testing/#testing-using-commnd-line-mode", "text": "We can run the below command on the command line. For example: jans cli -CC /opt/jans/jans-setup/output/CA/client.crt -CK /opt/jans/jans-setup/output/CA/client.key \u2013operation-id get-oauth-openid-clients in the same way we can run other commands. Rest of the testing is same for jans and openbanking.", "title": "Testing using commnd line mode"}, {"location": "contribute/testing/#release-quality-assurance", "text": "Once all the code changes for a particular release have been committed, we perform a set of tests and go through a list of checkpoints to make sure release candidate (RC) build is healthy and functioning well.", "title": "Release Quality Assurance"}, {"location": "contribute/testing/#pre-release-qa-checklist", "text": "As part of pre-release QA check, we run a set of manual sanity checks on test environments with various deployment configurations.", "title": "Pre-release QA checklist"}, {"location": "contribute/testing/#test-environments", "text": "# OS Platform Persistance Type Deployment Type (VM/CN) Test 2 SUSE 15 Mysql VM installation and sanity testing 3 SUSE 15 Pgsql VM installation and sanity testing 5 RHEL 8 Mysql VM installation and sanity testing 6 RHEL 8 Pgsql VM installation and sanity testing 8 Ubuntu20 Mysql VM installation and sanity testing 9 Ubuntu20 Pgsql VM installation and sanity testing 11 Ubuntu22 Mysql VM installation and sanity testing 12 Ubuntu22 Pgsql VM installation and sanity testing", "title": "Test Environments"}, {"location": "contribute/testing/#sanity-checks", "text": "Review functioning of .well-known endpoints for OpenId, Fido, UMA, SCIM modules Test device authentication flow using TUI Test password authentication flow using Janssen Server Tent Test Agama project deployment and functioning", "title": "Sanity checks"}, {"location": "contribute/testing/#post-release-qa-checklist", "text": "# QA Checks 1 Package installation verification on all OS Platforms as in pre-release tests", "title": "Post-release QA checklist"}, {"location": "contribute/ci-cd/release-process/", "tags": ["Release", "faq"], "text": "Release Process # The release process starts on scheduled times detailed in the milestones of the Janssen project. The release manager is responsible for coordinating the release process and ensuring that all steps are completed. The process is as follows: Release Planning : The release manager creates a release plan that normally includes the release date, the version number, and the main features that will be included in the release. The release plan is shared with the team for review and feedback. Feature Freeze : The release manager announces the feature freeze date. After this date, no new features will be added to the release. The team focuses on fixing bugs and improving the quality of the release. QA starts testing the release. Code Freeze : The release manager announces the code freeze date. After this date, no new code will be added to the release. The team focuses on fixing bugs and improving the quality of the release. QA team verifies testing the release. Release Candidate : The release manager creates a release candidate and shares it with the team for testing. The team tests the release candidate and reports any issues found. The release manager fixes the issues and creates a new release candidate. This process continues until the release candidate is stable. This is normally done via a PR process and release branch following the structure release-<version> . Release : The release manager creates the final release and shares it with the team. The team tests the final release and reports any issues found. The release manager fixes the issues and creates a new release. This process continues until the final release is stable. Release Notes : The release manager creates the release notes and shares them with the team. The release notes include the version number, the main features included in the release, and any known issues. The release notes are shared with the community. This process is automated and picked up through conventional commits developers submit. Release Announcement : The release manager announces the release to the community. The announcement includes the version number, the main features included in the release, and any known issues. The announcement is shared on the Janssen website, the Janssen blog, and social media. The release manager also sends an email to the Janssen mailing list. Post-Release : The release manager monitors the release and addresses any issues that arise. The team continues to work on the next release. Release Retrospective : The release manager conducts a retrospective to review the release process and identify areas for improvement. The team provides feedback on the release process. The release manager uses this feedback to improve the release process for future releases. Next Release Planning : The release manager starts planning the next release. The process starts again from step 1. A branch release-<version> is created for the next dev and snapshot release with a similar process from step 1 and is merged into main . Future plans # We are planning a full move to SemVer for all Janssen projects that will be scheduled bi-weekly. In this move, the Google release-please GitHub workflow will be activated to automatically release the projects according to the conventional commits submitted.", "title": "Release Process"}, {"location": "contribute/ci-cd/release-process/#release-process", "text": "The release process starts on scheduled times detailed in the milestones of the Janssen project. The release manager is responsible for coordinating the release process and ensuring that all steps are completed. The process is as follows: Release Planning : The release manager creates a release plan that normally includes the release date, the version number, and the main features that will be included in the release. The release plan is shared with the team for review and feedback. Feature Freeze : The release manager announces the feature freeze date. After this date, no new features will be added to the release. The team focuses on fixing bugs and improving the quality of the release. QA starts testing the release. Code Freeze : The release manager announces the code freeze date. After this date, no new code will be added to the release. The team focuses on fixing bugs and improving the quality of the release. QA team verifies testing the release. Release Candidate : The release manager creates a release candidate and shares it with the team for testing. The team tests the release candidate and reports any issues found. The release manager fixes the issues and creates a new release candidate. This process continues until the release candidate is stable. This is normally done via a PR process and release branch following the structure release-<version> . Release : The release manager creates the final release and shares it with the team. The team tests the final release and reports any issues found. The release manager fixes the issues and creates a new release. This process continues until the final release is stable. Release Notes : The release manager creates the release notes and shares them with the team. The release notes include the version number, the main features included in the release, and any known issues. The release notes are shared with the community. This process is automated and picked up through conventional commits developers submit. Release Announcement : The release manager announces the release to the community. The announcement includes the version number, the main features included in the release, and any known issues. The announcement is shared on the Janssen website, the Janssen blog, and social media. The release manager also sends an email to the Janssen mailing list. Post-Release : The release manager monitors the release and addresses any issues that arise. The team continues to work on the next release. Release Retrospective : The release manager conducts a retrospective to review the release process and identify areas for improvement. The team provides feedback on the release process. The release manager uses this feedback to improve the release process for future releases. Next Release Planning : The release manager starts planning the next release. The process starts again from step 1. A branch release-<version> is created for the next dev and snapshot release with a similar process from step 1 and is merged into main .", "title": "Release Process"}, {"location": "contribute/ci-cd/release-process/#future-plans", "text": "We are planning a full move to SemVer for all Janssen projects that will be scheduled bi-weekly. In this move, the Google release-please GitHub workflow will be activated to automatically release the projects according to the conventional commits submitted.", "title": "Future plans"}, {"location": "contribute/implementation-design/agama/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Agama"}, {"location": "contribute/implementation-design/agama/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/agama/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/agama/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "contribute/implementation-design/jans-auth-server/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "jans-auth-server"}, {"location": "contribute/implementation-design/jans-auth-server/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/jans-auth-server/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/jans-auth-server/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "contribute/implementation-design/jans-cli/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "jans-cli"}, {"location": "contribute/implementation-design/jans-cli/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/jans-cli/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/jans-cli/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "contribute/implementation-design/jans-config-api/", "tags": ["developer", "config-api"], "text": "Overview # Janssen Config API # Janssen(Jans) Config API is an application programming interface (API) gateway managing configuring of various Janssen modules. Diagram reference Jans Config API features: # Jans Config API uses REST endpoints to communicate. Jans Config API endpoint are OAuth 2.0 protected. More details here Jans Config API plugin architecture can be used to add new features. More details here . Config API endpoint can be used to create new user, clients, scopes, etc. This data is stores into the same persistence store as the Jans-Auth server. Jans Config API Flow # sequenceDiagram title Jans Config API request flow autonumber participant Admin participant Admin UI participant Config API participant Auth Server participant Jans Persistence Admin->>Admin UI: Create Client note over Admin UI: Click on plus sign to Create Client and Save button to create new client Config API->>Auth Server: Introspect Token Auth Server->>Config API: Returns Introspection Response Config API->>Config API: Successful validation of token claim with Introspection Response Config API->>Jans Persistence: Validate and persist client data Config API->>Admin UI: Returns persistence status Admin : Administrator of the application. Will use Admin UI to configure application. Admin UI : Gluu graphical user interface for the administrators to manage configuration and other properties of Jans Auth Server via Jans Config API. Config API : Jans API gateway for configuring Janssen modules like Jans Auth Server, fido2, SCIM, etc. Auth Server : Janssen federated identity with comprehensive implementation of OpenID Connect. Used for introspection of access token in this flow. Jans Persistence : Jans Persistence layer to persist data in backend.", "title": "jans-config-api"}, {"location": "contribute/implementation-design/jans-config-api/#overview", "text": "", "title": "Overview"}, {"location": "contribute/implementation-design/jans-config-api/#janssen-config-api", "text": "Janssen(Jans) Config API is an application programming interface (API) gateway managing configuring of various Janssen modules. Diagram reference", "title": "Janssen Config API"}, {"location": "contribute/implementation-design/jans-config-api/#jans-config-api-features", "text": "Jans Config API uses REST endpoints to communicate. Jans Config API endpoint are OAuth 2.0 protected. More details here Jans Config API plugin architecture can be used to add new features. More details here . Config API endpoint can be used to create new user, clients, scopes, etc. This data is stores into the same persistence store as the Jans-Auth server.", "title": "Jans Config API features:"}, {"location": "contribute/implementation-design/jans-config-api/#jans-config-api-flow", "text": "sequenceDiagram title Jans Config API request flow autonumber participant Admin participant Admin UI participant Config API participant Auth Server participant Jans Persistence Admin->>Admin UI: Create Client note over Admin UI: Click on plus sign to Create Client and Save button to create new client Config API->>Auth Server: Introspect Token Auth Server->>Config API: Returns Introspection Response Config API->>Config API: Successful validation of token claim with Introspection Response Config API->>Jans Persistence: Validate and persist client data Config API->>Admin UI: Returns persistence status Admin : Administrator of the application. Will use Admin UI to configure application. Admin UI : Gluu graphical user interface for the administrators to manage configuration and other properties of Jans Auth Server via Jans Config API. Config API : Jans API gateway for configuring Janssen modules like Jans Auth Server, fido2, SCIM, etc. Auth Server : Janssen federated identity with comprehensive implementation of OpenID Connect. Used for introspection of access token in this flow. Jans Persistence : Jans Persistence layer to persist data in backend.", "title": "Jans Config API Flow"}, {"location": "contribute/implementation-design/jans-core/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "jans-core"}, {"location": "contribute/implementation-design/jans-core/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/jans-core/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/jans-core/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "contribute/implementation-design/jans-fido2/", "tags": ["developer", "fido"], "text": "Overview # Janssen's FIDO2 server # FIDO2 as an open standard for authentication is based on public key cryptography. Janssen's FIDO2 server - a component inside the Janssen project enables users of RPs to enroll and authenticate themselves using U2F keys, FIDO2 keys or inbuilt platform authenticator. 1. The FIDO2 server uses REST endpoints to communicate with an RP via an https connection. 2. The FIDO2 server implements the FIDO Metadata Service (MDS3) defined by FIDO Alliance. 3. The FIDO2 server stores user data into the same persistence store as the Jans-Auth server. (PostgreSQL, MYSQL etc.) Components of the FIDO2 ecosystem in Janssen # Diagram reference User : User of an application, the one who possesses the Authenticator and who's role is to pass the Test of User Presence (TUP) (touch device, look, speak etc.). WebAuthn API : A global web standard for password-less FIDO2 authentication, implemented by most browsers (Google Chrome, Mozilla Firefox, Microsoft Edge, Apple Safari, Opera, Microsoft edge). It provides clients access to the underlying capabilities of the Authenticator. WebAuthn offers a very good user experience, there is no need for any additional browser plugin to be installed. WebAuthn API: enables clients to make requests to authenticators with regards to : creation of a new key-pair provide an assertion about a key report capabilities (capability exists but not offered in Janssen's FIDO2 offering) manage a PIN. (capability exists but not offered in Janssen's FIDO2 offering) Authenticator : A device which holds the private key. It prompts the user to perform a certain gesture. It can be a platform authenticator that is built into the client device or a roaming authenticator that is connected to the client device through USB, BLE, or NFC. Relying Party : The RP ( jans-auth or casa ) implements a Javascript Client which makes a registration and authentication request to the WebAuthn API. The Relying Party ID is the DNS domain where the FIDO2 device will be registered and used. CTAP2 : Simple and lightweight hardware protocol that enables Authenticators to talk with Supported browsers. FIDO2 Server Janssen's FIDO server is a standalone server communicates with the RP using an API which can be obtained by querying the following URL : https://<myjans-server>/.well-known/fido2-configuration Response: { \"version\": \"1.1\", \"issuer\": \"https://<myjans-server>\", \"attestation\": { \"base_path\": \"https://<myjans-server>/jans-fido2/restv1/attestation\", \"options_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/attestation/options\", \"result_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/attestation/result\" }, \"assertion\": { \"base_path\": \"https://<myjans-server>/jans-fido2/restv1/assertion\", \"options_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/assertion/options\", \"result_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/assertion/result\" } } The two main functionalities are: 1. Attestation 2. Assertion The authenticator credentials obtained after querying the WebAuthn API is forwarded to the FIDO2 server for attestation or assertion. Interception script : In the Janssen ecosystem, the authentication flow that comprises of the calls to WebAuthn API and the FIDO server is achieved using an interception script, details of it can be found here . Attestation formats supported by Janssen's FIDO server # Packed (FIDO2) : The most used attestation format TPM : Attestation for Windows10 devices Android key attestation : Attestation for android devices. Android SafetyNet : Any Android devices running 7+ FIDO U2F : Legacy U2F authenticators Apple Anonymous : Apple devices do attestations differently. None Backward compatibility with U2F authenticators # The FIDO server offers registration and authentication using legacy U2F authenticators. References # https://www.w3.org/TR/webauthn-2/ http://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html Tools # https://jwt.io/ \u2013 For JWT decoding and debugging https://www.base64decode.org/ \u2013 For Decoding Base64 to UTF8 https://fidoalliance.org/certification/fido-certified-products/ - To browse authenticators listed with FIDO Alliance", "title": "jans-fido2"}, {"location": "contribute/implementation-design/jans-fido2/#overview", "text": "", "title": "Overview"}, {"location": "contribute/implementation-design/jans-fido2/#janssens-fido2-server", "text": "FIDO2 as an open standard for authentication is based on public key cryptography. Janssen's FIDO2 server - a component inside the Janssen project enables users of RPs to enroll and authenticate themselves using U2F keys, FIDO2 keys or inbuilt platform authenticator. 1. The FIDO2 server uses REST endpoints to communicate with an RP via an https connection. 2. The FIDO2 server implements the FIDO Metadata Service (MDS3) defined by FIDO Alliance. 3. The FIDO2 server stores user data into the same persistence store as the Jans-Auth server. (PostgreSQL, MYSQL etc.)", "title": "Janssen's FIDO2 server"}, {"location": "contribute/implementation-design/jans-fido2/#components-of-the-fido2-ecosystem-in-janssen", "text": "Diagram reference User : User of an application, the one who possesses the Authenticator and who's role is to pass the Test of User Presence (TUP) (touch device, look, speak etc.). WebAuthn API : A global web standard for password-less FIDO2 authentication, implemented by most browsers (Google Chrome, Mozilla Firefox, Microsoft Edge, Apple Safari, Opera, Microsoft edge). It provides clients access to the underlying capabilities of the Authenticator. WebAuthn offers a very good user experience, there is no need for any additional browser plugin to be installed. WebAuthn API: enables clients to make requests to authenticators with regards to : creation of a new key-pair provide an assertion about a key report capabilities (capability exists but not offered in Janssen's FIDO2 offering) manage a PIN. (capability exists but not offered in Janssen's FIDO2 offering) Authenticator : A device which holds the private key. It prompts the user to perform a certain gesture. It can be a platform authenticator that is built into the client device or a roaming authenticator that is connected to the client device through USB, BLE, or NFC. Relying Party : The RP ( jans-auth or casa ) implements a Javascript Client which makes a registration and authentication request to the WebAuthn API. The Relying Party ID is the DNS domain where the FIDO2 device will be registered and used. CTAP2 : Simple and lightweight hardware protocol that enables Authenticators to talk with Supported browsers. FIDO2 Server Janssen's FIDO server is a standalone server communicates with the RP using an API which can be obtained by querying the following URL : https://<myjans-server>/.well-known/fido2-configuration Response: { \"version\": \"1.1\", \"issuer\": \"https://<myjans-server>\", \"attestation\": { \"base_path\": \"https://<myjans-server>/jans-fido2/restv1/attestation\", \"options_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/attestation/options\", \"result_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/attestation/result\" }, \"assertion\": { \"base_path\": \"https://<myjans-server>/jans-fido2/restv1/assertion\", \"options_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/assertion/options\", \"result_enpoint\": \"https://<myjans-server>/jans-fido2/restv1/assertion/result\" } } The two main functionalities are: 1. Attestation 2. Assertion The authenticator credentials obtained after querying the WebAuthn API is forwarded to the FIDO2 server for attestation or assertion. Interception script : In the Janssen ecosystem, the authentication flow that comprises of the calls to WebAuthn API and the FIDO server is achieved using an interception script, details of it can be found here .", "title": "Components of the FIDO2 ecosystem in Janssen"}, {"location": "contribute/implementation-design/jans-fido2/#attestation-formats-supported-by-janssens-fido-server", "text": "Packed (FIDO2) : The most used attestation format TPM : Attestation for Windows10 devices Android key attestation : Attestation for android devices. Android SafetyNet : Any Android devices running 7+ FIDO U2F : Legacy U2F authenticators Apple Anonymous : Apple devices do attestations differently. None", "title": "Attestation formats supported by Janssen's FIDO server"}, {"location": "contribute/implementation-design/jans-fido2/#backward-compatibility-with-u2f-authenticators", "text": "The FIDO server offers registration and authentication using legacy U2F authenticators.", "title": "Backward compatibility with U2F authenticators"}, {"location": "contribute/implementation-design/jans-fido2/#references", "text": "https://www.w3.org/TR/webauthn-2/ http://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html", "title": "References"}, {"location": "contribute/implementation-design/jans-fido2/#tools", "text": "https://jwt.io/ \u2013 For JWT decoding and debugging https://www.base64decode.org/ \u2013 For Decoding Base64 to UTF8 https://fidoalliance.org/certification/fido-certified-products/ - To browse authenticators listed with FIDO Alliance", "title": "Tools"}, {"location": "contribute/implementation-design/jans-orm/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "jans-orm"}, {"location": "contribute/implementation-design/jans-orm/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/jans-orm/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/jans-orm/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "contribute/implementation-design/jans-scim/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "jans-scim"}, {"location": "contribute/implementation-design/jans-scim/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "contribute/implementation-design/jans-scim/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "contribute/implementation-design/jans-scim/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "governance/charter/", "tags": ["governance", "charter"], "text": "Technical Charter (the \u201cCharter\u201d) for Janssen Project a Series of LF Projects, LLC # Adopted December 8, 2020 This Charter sets forth the responsibilities and procedures for technical contribution to, and oversight of, the Janssen open source project, which has been established as Janssen Project a Series of LF Projects, LLC (the \u201cProject\u201d). LF Projects, LLC (\u201cLF Projects\u201d) is a Delaware series limited liability company. All contributors (including committers, maintainers, and other technical positions) and other participants in the Project (collectively, \u201cCollaborators\u201d) must comply with the terms of this Charter. Mission and Scope of the Project The mission of the Project is to develop and maintain a cloud native identity and authorization platform that comprehensively implements OAuth, OpenID Connect and the User Managed Access protocol, while maintaining flexibility and horizontal scalability. The scope of the Project includes collaborative development under the Project License (as defined herein) supporting the mission, including documentation, testing, integration and the creation of other artifacts that aid the development, deployment, operation or adoption of the open source project. Technical Steering Committee The Technical Steering Committee (the \u201cTSC\u201d) will be responsible for all technical oversight of the open source Project. The TSC voting members are initially the Project\u2019s Committers. At the inception of the project, the Committers of the Project will be as set forth within the \u201cCONTRIBUTING\u201d file within the Project\u2019s code repository. The TSC may choose an alternative approach for determining the voting members of the TSC, and any such alternative approach will be documented in the CONTRIBUTING file. Any meetings of the Technical Steering Committee are intended to be open to the public, and can be conducted electronically, via teleconference, or in person. TSC projects generally will involve Contributors and Committers. The TSC may adopt or modify roles so long as the roles are documented in the CONTRIBUTING file. Unless otherwise documented: Contributors include anyone in the technical community that contributes code, documentation, or other technical artifacts to the Project; Committers are Contributors who have earned the ability to modify (\u201ccommit\u201d) source code, documentation or other technical artifacts in a project\u2019s repository; and A Contributor may become a Committer by a majority approval of the existing Committers. A Committer may be removed by a majority approval of the other existing Committers. Participation in the Project through becoming a Contributor and Committer is open to anyone so long as they abide by the terms of this Charter. The TSC may (1) establish work flow procedures for the submission, approval, and closure/archiving of projects, (2) set requirements for the promotion of Contributors to Committer status, as applicable, and (3) amend, adjust, refine and/or eliminate the roles of Contributors, and Committers, and create new roles, and publicly document any TSC roles, as it sees fit. The TSC may elect a TSC Chair, who will preside over meetings of the TSC and will serve until their resignation or replacement by the TSC. Responsibilities: The TSC will be responsible for all aspects of oversight relating to the Project, which may include: coordinating the technical direction of the Project; approving project or system proposals (including, but not limited to, incubation, deprecation, and changes to a sub-project\u2019s scope); organizing sub-projects and removing sub-projects; creating sub-committees or working groups to focus on cross-project technical issues and requirements; appointing representatives to work with other open source or open standards communities; establishing community norms, workflows, issuing releases, and security issue reporting policies; approving and implementing policies and processes for contributing (to be published in the CONTRIBUTING file) and coordinating with the series manager of the Project (as provided for in the Series Agreement, the \u201cSeries Manager\u201d) to resolve matters or concerns that may arise as set forth in Section 7 of this Charter; discussions, seeking consensus, and where necessary, voting on technical matters relating to the code base that affect multiple projects; and coordinating any marketing, events, or communications regarding the Project. TSC Voting While the Project aims to operate as a consensus-based community, if any TSC decision requires a vote to move the Project forward, the voting members of the TSC will vote on a one vote per voting member basis. Quorum for TSC meetings requires at least fifty percent of all voting members of the TSC to be present. The TSC may continue to meet if quorum is not met but will be prevented from making any decisions at the meeting. Except as provided in Section 7.iii. and 8.i, decisions by vote at a meeting require a majority vote of those in attendance, provided quorum is met. Decisions made by electronic vote without a meeting require a majority vote of all voting members of the TSC. In the event a vote cannot be resolved by the TSC, any voting member of the TSC may refer the matter to the Series Manager for assistance in reaching a resolution. Compliance with Policies This Charter is subject to the Series Agreement for the Project and the Operating Agreement of LF Projects. Contributors will comply with the policies of LF Projects as may be adopted and amended by LF Projects, including, without limitation the policies listed at https://lfprojects.org/policies/. The TSC may adopt a code of conduct (\u201cCoC\u201d) for the Project, which is subject to approval by the Series Manager. In the event that a Project-specific CoC has not been approved, the LF Projects Code of Conduct listed at https://lfprojects.org/policies will apply for all Collaborators in the Project. When amending or adopting any policy applicable to the Project, LF Projects will publish such policy, as to be amended or adopted, on its web site at least 30 days prior to such policy taking effect; provided, however, that in the case of any amendment of the Trademark Policy or Terms of Use of LF Projects, any such amendment is effective upon publication on LF Project\u2019s web site. All Collaborators must allow open participation from any individual or organization meeting the requirements for contributing under this Charter and any policies adopted for all Collaborators by the TSC, regardless of competitive interests. Put another way, the Project community must not seek to exclude any participant based on any criteria, requirement, or reason other than those that are reasonable and applied on a non-discriminatory basis to all Collaborators in the Project community. The Project will operate in a transparent, open, collaborative, and ethical manner at all times. The output of all Project discussions, proposals, timelines, decisions, and status should be made open and easily visible to all. Any potential violations of this requirement should be reported immediately to the Series Manager. Community Assets LF Projects will hold title to all trade or service marks used by the Project (\u201cProject Trademarks\u201d), whether based on common law or registered rights. Project Trademarks will be transferred and assigned to LF Projects to hold on behalf of the Project. Any use of any Project Trademarks by Collaborators in the Project will be in accordance with the license from LF Projects and inure to the benefit of LF Projects. The Project will, as permitted and in accordance with such license from LF Projects, develop and own all Project GitHub and social media accounts, and domain name registrations created by the Project community. Under no circumstances will LF Projects be expected or required to undertake any action on behalf of the Project that is inconsistent with the tax-exempt status or purpose, as applicable, of LFP, Inc. or LF Projects, LLC. General Rules and Operations. The Project will: engage in the work of the Project in a professional manner consistent with maintaining a cohesive community, while also maintaining the goodwill and esteem of LF Projects, LFP, Inc. and other partner organizations in the open source community; and respect the rights of all trademark owners, including any branding and trademark usage guidelines. Intellectual Property Policy Collaborators acknowledge that the copyright in all new contributions will be retained by the copyright holder as independent works of authorship and that no contributor or copyright holder will be required to assign copyrights to the Project. Except as described in Section 7.iii., all contributions to the Project are subject to the following: All new inbound code contributions to the Project must be made using the Apache License, Version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 (the \u201cProject License\u201d). All new inbound code contributions must also be accompanied by a Developer Certificate of Origin ( http://developercertificate.org ) sign-off in the source code system that is submitted through a TSC-approved contribution process which will bind the authorized contributor and, if not self-employed, their employer to the applicable license; All outbound code will be made available under the Project License. Documentation will be received and made available by the Project under the Creative Commons Attribution 4.0 International License (available at http://creativecommons.org/licenses/by/4.0/ ). The Project may seek to integrate and contribute back to other open source projects (\u201cUpstream Projects\u201d). In such cases, the Project will conform to all license requirements of the Upstream Projects, including dependencies, leveraged by the Project. Upstream Project code contributions not stored within the Project\u2019s main code repository will comply with the contribution process and license terms for the applicable Upstream Project. The TSC may approve the use of an alternative license or licenses for inbound or outbound contributions on an exception basis. To request an exception, please describe the contribution, the alternative open source license(s), and the justification for using an alternative open source license for the Project. License exceptions must be approved by a two-thirds vote of the entire TSC. Contributed files should contain license information, such as SPDX short form identifiers, indicating the open source license or licenses pertaining to the file. Amendments This charter may be amended by a two-thirds vote of the entire TSC and is subject to approval by LF Projects.", "title": "Charter"}, {"location": "governance/charter/#technical-charter-the-charter-for-janssen-project-a-series-of-lf-projects-llc", "text": "Adopted December 8, 2020 This Charter sets forth the responsibilities and procedures for technical contribution to, and oversight of, the Janssen open source project, which has been established as Janssen Project a Series of LF Projects, LLC (the \u201cProject\u201d). LF Projects, LLC (\u201cLF Projects\u201d) is a Delaware series limited liability company. All contributors (including committers, maintainers, and other technical positions) and other participants in the Project (collectively, \u201cCollaborators\u201d) must comply with the terms of this Charter. Mission and Scope of the Project The mission of the Project is to develop and maintain a cloud native identity and authorization platform that comprehensively implements OAuth, OpenID Connect and the User Managed Access protocol, while maintaining flexibility and horizontal scalability. The scope of the Project includes collaborative development under the Project License (as defined herein) supporting the mission, including documentation, testing, integration and the creation of other artifacts that aid the development, deployment, operation or adoption of the open source project. Technical Steering Committee The Technical Steering Committee (the \u201cTSC\u201d) will be responsible for all technical oversight of the open source Project. The TSC voting members are initially the Project\u2019s Committers. At the inception of the project, the Committers of the Project will be as set forth within the \u201cCONTRIBUTING\u201d file within the Project\u2019s code repository. The TSC may choose an alternative approach for determining the voting members of the TSC, and any such alternative approach will be documented in the CONTRIBUTING file. Any meetings of the Technical Steering Committee are intended to be open to the public, and can be conducted electronically, via teleconference, or in person. TSC projects generally will involve Contributors and Committers. The TSC may adopt or modify roles so long as the roles are documented in the CONTRIBUTING file. Unless otherwise documented: Contributors include anyone in the technical community that contributes code, documentation, or other technical artifacts to the Project; Committers are Contributors who have earned the ability to modify (\u201ccommit\u201d) source code, documentation or other technical artifacts in a project\u2019s repository; and A Contributor may become a Committer by a majority approval of the existing Committers. A Committer may be removed by a majority approval of the other existing Committers. Participation in the Project through becoming a Contributor and Committer is open to anyone so long as they abide by the terms of this Charter. The TSC may (1) establish work flow procedures for the submission, approval, and closure/archiving of projects, (2) set requirements for the promotion of Contributors to Committer status, as applicable, and (3) amend, adjust, refine and/or eliminate the roles of Contributors, and Committers, and create new roles, and publicly document any TSC roles, as it sees fit. The TSC may elect a TSC Chair, who will preside over meetings of the TSC and will serve until their resignation or replacement by the TSC. Responsibilities: The TSC will be responsible for all aspects of oversight relating to the Project, which may include: coordinating the technical direction of the Project; approving project or system proposals (including, but not limited to, incubation, deprecation, and changes to a sub-project\u2019s scope); organizing sub-projects and removing sub-projects; creating sub-committees or working groups to focus on cross-project technical issues and requirements; appointing representatives to work with other open source or open standards communities; establishing community norms, workflows, issuing releases, and security issue reporting policies; approving and implementing policies and processes for contributing (to be published in the CONTRIBUTING file) and coordinating with the series manager of the Project (as provided for in the Series Agreement, the \u201cSeries Manager\u201d) to resolve matters or concerns that may arise as set forth in Section 7 of this Charter; discussions, seeking consensus, and where necessary, voting on technical matters relating to the code base that affect multiple projects; and coordinating any marketing, events, or communications regarding the Project. TSC Voting While the Project aims to operate as a consensus-based community, if any TSC decision requires a vote to move the Project forward, the voting members of the TSC will vote on a one vote per voting member basis. Quorum for TSC meetings requires at least fifty percent of all voting members of the TSC to be present. The TSC may continue to meet if quorum is not met but will be prevented from making any decisions at the meeting. Except as provided in Section 7.iii. and 8.i, decisions by vote at a meeting require a majority vote of those in attendance, provided quorum is met. Decisions made by electronic vote without a meeting require a majority vote of all voting members of the TSC. In the event a vote cannot be resolved by the TSC, any voting member of the TSC may refer the matter to the Series Manager for assistance in reaching a resolution. Compliance with Policies This Charter is subject to the Series Agreement for the Project and the Operating Agreement of LF Projects. Contributors will comply with the policies of LF Projects as may be adopted and amended by LF Projects, including, without limitation the policies listed at https://lfprojects.org/policies/. The TSC may adopt a code of conduct (\u201cCoC\u201d) for the Project, which is subject to approval by the Series Manager. In the event that a Project-specific CoC has not been approved, the LF Projects Code of Conduct listed at https://lfprojects.org/policies will apply for all Collaborators in the Project. When amending or adopting any policy applicable to the Project, LF Projects will publish such policy, as to be amended or adopted, on its web site at least 30 days prior to such policy taking effect; provided, however, that in the case of any amendment of the Trademark Policy or Terms of Use of LF Projects, any such amendment is effective upon publication on LF Project\u2019s web site. All Collaborators must allow open participation from any individual or organization meeting the requirements for contributing under this Charter and any policies adopted for all Collaborators by the TSC, regardless of competitive interests. Put another way, the Project community must not seek to exclude any participant based on any criteria, requirement, or reason other than those that are reasonable and applied on a non-discriminatory basis to all Collaborators in the Project community. The Project will operate in a transparent, open, collaborative, and ethical manner at all times. The output of all Project discussions, proposals, timelines, decisions, and status should be made open and easily visible to all. Any potential violations of this requirement should be reported immediately to the Series Manager. Community Assets LF Projects will hold title to all trade or service marks used by the Project (\u201cProject Trademarks\u201d), whether based on common law or registered rights. Project Trademarks will be transferred and assigned to LF Projects to hold on behalf of the Project. Any use of any Project Trademarks by Collaborators in the Project will be in accordance with the license from LF Projects and inure to the benefit of LF Projects. The Project will, as permitted and in accordance with such license from LF Projects, develop and own all Project GitHub and social media accounts, and domain name registrations created by the Project community. Under no circumstances will LF Projects be expected or required to undertake any action on behalf of the Project that is inconsistent with the tax-exempt status or purpose, as applicable, of LFP, Inc. or LF Projects, LLC. General Rules and Operations. The Project will: engage in the work of the Project in a professional manner consistent with maintaining a cohesive community, while also maintaining the goodwill and esteem of LF Projects, LFP, Inc. and other partner organizations in the open source community; and respect the rights of all trademark owners, including any branding and trademark usage guidelines. Intellectual Property Policy Collaborators acknowledge that the copyright in all new contributions will be retained by the copyright holder as independent works of authorship and that no contributor or copyright holder will be required to assign copyrights to the Project. Except as described in Section 7.iii., all contributions to the Project are subject to the following: All new inbound code contributions to the Project must be made using the Apache License, Version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 (the \u201cProject License\u201d). All new inbound code contributions must also be accompanied by a Developer Certificate of Origin ( http://developercertificate.org ) sign-off in the source code system that is submitted through a TSC-approved contribution process which will bind the authorized contributor and, if not self-employed, their employer to the applicable license; All outbound code will be made available under the Project License. Documentation will be received and made available by the Project under the Creative Commons Attribution 4.0 International License (available at http://creativecommons.org/licenses/by/4.0/ ). The Project may seek to integrate and contribute back to other open source projects (\u201cUpstream Projects\u201d). In such cases, the Project will conform to all license requirements of the Upstream Projects, including dependencies, leveraged by the Project. Upstream Project code contributions not stored within the Project\u2019s main code repository will comply with the contribution process and license terms for the applicable Upstream Project. The TSC may approve the use of an alternative license or licenses for inbound or outbound contributions on an exception basis. To request an exception, please describe the contribution, the alternative open source license(s), and the justification for using an alternative open source license for the Project. License exceptions must be approved by a two-thirds vote of the entire TSC. Contributed files should contain license information, such as SPDX short form identifiers, indicating the open source license or licenses pertaining to the file. Amendments This charter may be amended by a two-thirds vote of the entire TSC and is subject to approval by LF Projects.", "title": "Technical Charter (the \u201cCharter\u201d) for Janssen Project a Series of LF Projects, LLC"}, {"location": "governance/copyright-notices/", "tags": ["governance", "copyrights"], "text": "Copyrights # Ownership of Copyrights in Janssen Project Contributions # When source code, documentation and other content is contributed to the Janssen Project, the copyrights in those contributions remain owned by the original copyright holders. The copyrights are not assigned to the Janssen Project. Instead, they are licensed for distribution as part of the project. Whether a project uses a DCO or a CLA, the original copyright holders retain their copyrights. Copyright Notices # The Janssen Project does not require or recommend that every contributor include their copyright notice in contributed files. See below for more details on why not. Instead, we recommend using a more general statement in a form similar to the following: Copyright The Janssen Project Authors. Copyright The Janssen Project Contributors. Copyright Contributors to the Janssen Project. These statements are intended to communicate the following: - the work is copyrighted; - the contributors of the code licensed it, but retain ownership of their copyrights; and - it was licensed for distribution as part of the named project. By using a common format, the project avoids having to deal with names of copyright holders, years or ranges of years, and variations on the (c) symbol. This aims to minimize the burden on developers and maintainers as well as redistributors of the code. What if I want my copyright notice included? # Please note that it is not wrong , and it is acceptable, if a contributor wishes to keep their own copyright notices on their contributions. The above is a recommended format for ease of use, but is not mandated by the Janssen Project. If you are contributing on behalf of your employer, you may wish to discuss with your legal department about whether they will require you to include a copyright notice identifying them as the copyright holder in contributions. What about Third Party Code? # If a file only contains code that originates from a third party source who didn't contribute it themselves, then you would not want to add the notices above. (In a similar vein, you wouldn't add a notice identifying you as the copyright holder either, if you didn't own it.) Just preserve the existing copyright and license notices as they are. If, however, you add copyrightable content to a pre-existing file from another project, then at that point you could add a copyright notice similar to the one above. Don't Change Someone Else's Notice without their Permission # You should not change or remove someone else's copyright notice unless they have expressly permitted you to do so. This includes third parties' notices in pre-existing code. Why not list every copyright holder? # There are several reasons why the Janssen Project doesn't require or recommend trying to list every copyright holder for contributions to every file: Copyright notices are not mandatory in order for the contributor to retain ownership of their copyright. Copyright notices are rarely kept up to date as a file evolves, resulting in inaccurate statements. Trying to keep notices up to date, or to correct notices that have become inaccurate, increases the burden on developers without tangible benefit. Developers and maintainers often do not want to have to worry about e.g. whether a minor contribution (such as a typo fix) means that a new copyright notice should be added. Adding many different copyright notices may increase the burden on downstream distributors, if their license compliance processes involve reproducing notices. The specific individual or legal entity that owns the copyright might not be known to the contributor; it could be you, your employer, or some other entity.", "title": "Copyright-notice"}, {"location": "governance/copyright-notices/#copyrights", "text": "", "title": "Copyrights"}, {"location": "governance/copyright-notices/#ownership-of-copyrights-in-janssen-project-contributions", "text": "When source code, documentation and other content is contributed to the Janssen Project, the copyrights in those contributions remain owned by the original copyright holders. The copyrights are not assigned to the Janssen Project. Instead, they are licensed for distribution as part of the project. Whether a project uses a DCO or a CLA, the original copyright holders retain their copyrights.", "title": "Ownership of Copyrights in Janssen Project Contributions"}, {"location": "governance/copyright-notices/#copyright-notices", "text": "The Janssen Project does not require or recommend that every contributor include their copyright notice in contributed files. See below for more details on why not. Instead, we recommend using a more general statement in a form similar to the following: Copyright The Janssen Project Authors. Copyright The Janssen Project Contributors. Copyright Contributors to the Janssen Project. These statements are intended to communicate the following: - the work is copyrighted; - the contributors of the code licensed it, but retain ownership of their copyrights; and - it was licensed for distribution as part of the named project. By using a common format, the project avoids having to deal with names of copyright holders, years or ranges of years, and variations on the (c) symbol. This aims to minimize the burden on developers and maintainers as well as redistributors of the code.", "title": "Copyright Notices"}, {"location": "governance/copyright-notices/#what-if-i-want-my-copyright-notice-included", "text": "Please note that it is not wrong , and it is acceptable, if a contributor wishes to keep their own copyright notices on their contributions. The above is a recommended format for ease of use, but is not mandated by the Janssen Project. If you are contributing on behalf of your employer, you may wish to discuss with your legal department about whether they will require you to include a copyright notice identifying them as the copyright holder in contributions.", "title": "What if I want my copyright notice included?"}, {"location": "governance/copyright-notices/#what-about-third-party-code", "text": "If a file only contains code that originates from a third party source who didn't contribute it themselves, then you would not want to add the notices above. (In a similar vein, you wouldn't add a notice identifying you as the copyright holder either, if you didn't own it.) Just preserve the existing copyright and license notices as they are. If, however, you add copyrightable content to a pre-existing file from another project, then at that point you could add a copyright notice similar to the one above.", "title": "What about Third Party Code?"}, {"location": "governance/copyright-notices/#dont-change-someone-elses-notice-without-their-permission", "text": "You should not change or remove someone else's copyright notice unless they have expressly permitted you to do so. This includes third parties' notices in pre-existing code.", "title": "Don't Change Someone Else's Notice without their Permission"}, {"location": "governance/copyright-notices/#why-not-list-every-copyright-holder", "text": "There are several reasons why the Janssen Project doesn't require or recommend trying to list every copyright holder for contributions to every file: Copyright notices are not mandatory in order for the contributor to retain ownership of their copyright. Copyright notices are rarely kept up to date as a file evolves, resulting in inaccurate statements. Trying to keep notices up to date, or to correct notices that have become inaccurate, increases the burden on developers without tangible benefit. Developers and maintainers often do not want to have to worry about e.g. whether a minor contribution (such as a typo fix) means that a new copyright notice should be added. Adding many different copyright notices may increase the burden on downstream distributors, if their license compliance processes involve reproducing notices. The specific individual or legal entity that owns the copyright might not be known to the contributor; it could be you, your employer, or some other entity.", "title": "Why not list every copyright holder?"}, {"location": "governance/triage/", "tags": ["governance", "triage"], "text": "Janssen Triage Process and labels # Triage process is used to quickly screen and categorise new issues and PRs. Aim is to determine characteristics of new PRs/issues and take quick actions if possible. Triage process is a contineous process. As new issues/PRs come in, the community initiates discussions, add labels, ask for more details. This process does not wait for triage call or a meeting to be called. Community holds triage calls at a regular cadence. Triage calls are mainly utilised to discuss issue/PR where concensus is not yet reached and to pick up anything which is not yet triaged. It is encouraged to complete triage outside of triage call to improve velocity. Stages in triage process: # Name Description Needs triage When a new issue or PR is created, it is automatically labeled as needs-triage . The label indicates that this issue is missing some of the metadata. Metadata such as the missing owner. Or the owner needs to add metadata labels for effort , priority , kind and component. Once these labels are added, the owner should remove this label and add ready-for-triage label. Ready for triage This label indicates that the issue has enough information and can be triaged. Triaged All issues/PRs with the label ready-for-triage will be reviewed by core members of the community who have permission to add triaged label. Reviewer reviews issue/PR to check if the issue/PR is fully triaged and can be added to backlog without discussion on triage call. At this point, the label triaged is added and the label ready-for-triage is removed. We expect most of the isseus and PRs will be able to follow above path and quickly move out of triage process without waiting for triage call. Issues/PRs which still doesn't have triaged label, or has needs-discussion label, will be discussed during triage call. Labels # Github labels help us annotate issues/PRs with additional data. Janssen community uses labels, as detailed below, to communicate information and help making decisions about issues/PRs. Communication labels # These labels communicate status of current triage process for an issue/PR or indicate where community contribution is required. Most of communication labels would be replaced by other labels as triage process progresses and issue enters active development. For example, help wanted label would be removed once issue gets under active development and a community members takes ownership of the issue. Below is the list of labels which fall under this category: Label Indicates That needs-triage issue/PR needs triaging ready-for-triage that sufficient details has been added to the issue/PR in form of labels and is ready for triage review triaged Issue/PR is fully triaged needs-information Indicates that creator needs to add more information to issue/PR in order to be meaningfully triaged. When adding this label, also comment on the issue about what information is needed needs-discussion Indicates that issue needs discussion during triage meeting. When adding this label, also comment on the issue about what is it that demands discussion on this issue good first issue Indicates to the community that this issue suitable for first time contributor help wanted Indicates to the community that this issue has complexity which is suitable for contribution from any external contributor Metadata labels # These labels enrich issue/PR with metadata that will help during triage process and active development. These labels may not be removed from issue/PR, though value of labels may change as development progresses. For example, effort label may change from effort-3 to effort-8 as we understand issue in more detail. Below is the list of labels in this category: Label Indicates That Details comp-<module> Major Janssen components needing change in order to fix this issue/PR. For example, if this issue/PR would require change in files under fido2 module (under jans/fido2) , then apply comp-jans-fido2 label e.g comp-jans-auth-server , comp-jans-fido2 , area-<concern> Cross-cutting concerns involved in fixing this issue/PR. For example, if changes introduced by this issue/PR will need changes in documentation and need to be mentioned in release notes as well, then apply area-documentation , area-release-notes . area-CI should be applied when changes are required in artifacts relevent to automation, CI build infrastructure or release management process. An example of such artifact would be Github workflow scripts located under .github/workflows Labels available: area-documentation , area-release-notes , area-CI kind-bug Issue/PR is a bug in existing functionality kind-enhancement Issue/PR is an enhancement to an existing functionality kind-feature Issue/PR is new feature request kind-question Issue/PR is a question that can be addressed via pointers to documentation or user education kind-duplicate Issue/PR is a duplicate of existing issue/PR. Original issue should be mentioned in the comments using Duplicate of reply kind-dependencies Fix for Issue/PR pertains to external dependencies effort-1 Relative effort required for completion effort-2 Relative effort required for completion effort-3 Relative effort required for completion effort-5 Relative effort required for completion effort-8 Relative effort required for completion effort-13 Relative effort required for completion effort-21 Relative effort required for completion priority-0 An issue that causes a full outage, breakage, or major function unavailability for everyone, without any known workaround. The issue must be fixed immediately, taking precedence over all other work. Should receive updates at least once per day. priority-1 An issue that significantly impacts a large percentage of users; if there is a workaround it is partial or overly painful. The issue should be resolved before the next release. priority-2 The issue is important to a large percentage of users, with a workaround. Issues that are significantly ugly or painful (especially first-use or install-time issues). Issues with workarounds that would otherwise be P0 or P1. priority-3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent. priority-4 A relatively minor issue that is not relevant to core functions, or relates only to the attractiveness or pleasantness of use of the system. Good to have but not necessary changes/fixes. priority-5 The team acknowledges the request but (due to any number of reasons) does not plan to work on or accept contributions for this request. The issue remains open for discussion. Bot labeling methodology # The following labels are automatically assigned to Issues and PRs in GitHub following the schema provided in this file . Label Method comp-<module> The bot will detect from the title the component between the parentheses. feat(jans-auth-server): detect will result in the label comp-jans-auth-server added to the issue or PR. In a PR these labels are also detected by modified files path area-<concern> The bot will detect from the title the area appropriate. ci: adding something new to our ci will result in the label area-CI added to the issue or PR. In a PR these labels are also detected by modified files path. kind-bug The bot will detect this from the conventional commit written title kind-enhancement The bot will detect this from the conventional commit written title kind-feature The bot will detect this from the conventional commit written title kind-question Issue/PR is a question that can be addressed via pointers to documentation or user education kind-dependencies The bot will detect this from the conventional commit written title", "title": "Triage"}, {"location": "governance/triage/#janssen-triage-process-and-labels", "text": "Triage process is used to quickly screen and categorise new issues and PRs. Aim is to determine characteristics of new PRs/issues and take quick actions if possible. Triage process is a contineous process. As new issues/PRs come in, the community initiates discussions, add labels, ask for more details. This process does not wait for triage call or a meeting to be called. Community holds triage calls at a regular cadence. Triage calls are mainly utilised to discuss issue/PR where concensus is not yet reached and to pick up anything which is not yet triaged. It is encouraged to complete triage outside of triage call to improve velocity.", "title": "Janssen Triage Process and labels"}, {"location": "governance/triage/#stages-in-triage-process", "text": "Name Description Needs triage When a new issue or PR is created, it is automatically labeled as needs-triage . The label indicates that this issue is missing some of the metadata. Metadata such as the missing owner. Or the owner needs to add metadata labels for effort , priority , kind and component. Once these labels are added, the owner should remove this label and add ready-for-triage label. Ready for triage This label indicates that the issue has enough information and can be triaged. Triaged All issues/PRs with the label ready-for-triage will be reviewed by core members of the community who have permission to add triaged label. Reviewer reviews issue/PR to check if the issue/PR is fully triaged and can be added to backlog without discussion on triage call. At this point, the label triaged is added and the label ready-for-triage is removed. We expect most of the isseus and PRs will be able to follow above path and quickly move out of triage process without waiting for triage call. Issues/PRs which still doesn't have triaged label, or has needs-discussion label, will be discussed during triage call.", "title": "Stages in triage process:"}, {"location": "governance/triage/#labels", "text": "Github labels help us annotate issues/PRs with additional data. Janssen community uses labels, as detailed below, to communicate information and help making decisions about issues/PRs.", "title": "Labels"}, {"location": "governance/triage/#communication-labels", "text": "These labels communicate status of current triage process for an issue/PR or indicate where community contribution is required. Most of communication labels would be replaced by other labels as triage process progresses and issue enters active development. For example, help wanted label would be removed once issue gets under active development and a community members takes ownership of the issue. Below is the list of labels which fall under this category: Label Indicates That needs-triage issue/PR needs triaging ready-for-triage that sufficient details has been added to the issue/PR in form of labels and is ready for triage review triaged Issue/PR is fully triaged needs-information Indicates that creator needs to add more information to issue/PR in order to be meaningfully triaged. When adding this label, also comment on the issue about what information is needed needs-discussion Indicates that issue needs discussion during triage meeting. When adding this label, also comment on the issue about what is it that demands discussion on this issue good first issue Indicates to the community that this issue suitable for first time contributor help wanted Indicates to the community that this issue has complexity which is suitable for contribution from any external contributor", "title": "Communication labels"}, {"location": "governance/triage/#metadata-labels", "text": "These labels enrich issue/PR with metadata that will help during triage process and active development. These labels may not be removed from issue/PR, though value of labels may change as development progresses. For example, effort label may change from effort-3 to effort-8 as we understand issue in more detail. Below is the list of labels in this category: Label Indicates That Details comp-<module> Major Janssen components needing change in order to fix this issue/PR. For example, if this issue/PR would require change in files under fido2 module (under jans/fido2) , then apply comp-jans-fido2 label e.g comp-jans-auth-server , comp-jans-fido2 , area-<concern> Cross-cutting concerns involved in fixing this issue/PR. For example, if changes introduced by this issue/PR will need changes in documentation and need to be mentioned in release notes as well, then apply area-documentation , area-release-notes . area-CI should be applied when changes are required in artifacts relevent to automation, CI build infrastructure or release management process. An example of such artifact would be Github workflow scripts located under .github/workflows Labels available: area-documentation , area-release-notes , area-CI kind-bug Issue/PR is a bug in existing functionality kind-enhancement Issue/PR is an enhancement to an existing functionality kind-feature Issue/PR is new feature request kind-question Issue/PR is a question that can be addressed via pointers to documentation or user education kind-duplicate Issue/PR is a duplicate of existing issue/PR. Original issue should be mentioned in the comments using Duplicate of reply kind-dependencies Fix for Issue/PR pertains to external dependencies effort-1 Relative effort required for completion effort-2 Relative effort required for completion effort-3 Relative effort required for completion effort-5 Relative effort required for completion effort-8 Relative effort required for completion effort-13 Relative effort required for completion effort-21 Relative effort required for completion priority-0 An issue that causes a full outage, breakage, or major function unavailability for everyone, without any known workaround. The issue must be fixed immediately, taking precedence over all other work. Should receive updates at least once per day. priority-1 An issue that significantly impacts a large percentage of users; if there is a workaround it is partial or overly painful. The issue should be resolved before the next release. priority-2 The issue is important to a large percentage of users, with a workaround. Issues that are significantly ugly or painful (especially first-use or install-time issues). Issues with workarounds that would otherwise be P0 or P1. priority-3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent. priority-4 A relatively minor issue that is not relevant to core functions, or relates only to the attractiveness or pleasantness of use of the system. Good to have but not necessary changes/fixes. priority-5 The team acknowledges the request but (due to any number of reasons) does not plan to work on or accept contributions for this request. The issue remains open for discussion.", "title": "Metadata labels"}, {"location": "governance/triage/#bot-labeling-methodology", "text": "The following labels are automatically assigned to Issues and PRs in GitHub following the schema provided in this file . Label Method comp-<module> The bot will detect from the title the component between the parentheses. feat(jans-auth-server): detect will result in the label comp-jans-auth-server added to the issue or PR. In a PR these labels are also detected by modified files path area-<concern> The bot will detect from the title the area appropriate. ci: adding something new to our ci will result in the label area-CI added to the issue or PR. In a PR these labels are also detected by modified files path. kind-bug The bot will detect this from the conventional commit written title kind-enhancement The bot will detect this from the conventional commit written title kind-feature The bot will detect this from the conventional commit written title kind-question Issue/PR is a question that can be addressed via pointers to documentation or user education kind-dependencies The bot will detect this from the conventional commit written title", "title": "Bot labeling methodology"}, {"location": "janssen-server/auth-server/config/", "tags": ["administration", "auth-server", "configuration"], "text": "Configuration Overview # In some ways, this whole Auth Server admin guide is about configuration. But you have to start somewhere! This page provides a quick overview before you dive in! Config Server # The Configuration Server is a JSON/REST API that writes to the database, generates the keys, and does much of the other work you need to make your Janssen Project infrastructure solve your digital identity challenges. See the Config API Guide for more information. Tools # API - you can call the configuration endpoints with the API tool of your choice, like curl . With this mechanism, you can use client credential grant to obtain an OAuth token--just make sure it has the required scope to call the method / endpoint. See the Curl Guide for more info. CLI - The CLI, or Command Line Interface, calls the API for you. It uses the device flow to authenticate the person who is behind the config changes. See the Configuration CLI Guide for more info. TUI - The TUI, or Text User Interface, is a menu-based interactive tool that provides a more intuitive experience. When you make changes via the TUI, it also creates a log of the equivalent CLI command, in case you want a shortcut next time around. See the TUI Guide for more info. Client versus Server Configuration # Some behaviors are controlled at the server level. For example, should your Auth Server allow dynamic client registration? Other features you can configure either at the server or client level. For example, do you want user claims in an id_token ? Maybe you always want them (server), or maybe only sometimes (client). See the JSON Configuration/Properties for an overview of the server level configuration options. For client configuration options, see the Client Schema page. Interception Scripts # Janssen is a very flexible platform, that lets you customize many of the flows to meet your exact requirements. The black magic behind this flexibility is interception scripts--these are standard programming interfaces that enable you to add or change the behavior of Jans endpoints. Just to give one example, perhaps you need to add data from an external API into an OAuth access token? In this case, you could use the Update Token interception script. There are around 20 of these scripts. For a full list, see the Scripts Documentation . Customization # You don't want out of the box look and feel provided by Janssen. We know we are UX-challenged, backend developer geeks. Check out the Customization Guide for info about how to add adapt the user facing content to achieve your UX dreams. Operations # Janssen Project software has to run somewhere, right now... either on VM's or in containers. There are specifics instructions about each contained in these docs. Database and Cache # One of the biggest challenges in running the Janssen Platform is persistence. Make sure you understand how Janssen Project stores your data, or in some cases, caches it.", "title": "Auth Server Config"}, {"location": "janssen-server/auth-server/config/#configuration-overview", "text": "In some ways, this whole Auth Server admin guide is about configuration. But you have to start somewhere! This page provides a quick overview before you dive in!", "title": "Configuration Overview"}, {"location": "janssen-server/auth-server/config/#config-server", "text": "The Configuration Server is a JSON/REST API that writes to the database, generates the keys, and does much of the other work you need to make your Janssen Project infrastructure solve your digital identity challenges. See the Config API Guide for more information.", "title": "Config Server"}, {"location": "janssen-server/auth-server/config/#tools", "text": "API - you can call the configuration endpoints with the API tool of your choice, like curl . With this mechanism, you can use client credential grant to obtain an OAuth token--just make sure it has the required scope to call the method / endpoint. See the Curl Guide for more info. CLI - The CLI, or Command Line Interface, calls the API for you. It uses the device flow to authenticate the person who is behind the config changes. See the Configuration CLI Guide for more info. TUI - The TUI, or Text User Interface, is a menu-based interactive tool that provides a more intuitive experience. When you make changes via the TUI, it also creates a log of the equivalent CLI command, in case you want a shortcut next time around. See the TUI Guide for more info.", "title": "Tools"}, {"location": "janssen-server/auth-server/config/#client-versus-server-configuration", "text": "Some behaviors are controlled at the server level. For example, should your Auth Server allow dynamic client registration? Other features you can configure either at the server or client level. For example, do you want user claims in an id_token ? Maybe you always want them (server), or maybe only sometimes (client). See the JSON Configuration/Properties for an overview of the server level configuration options. For client configuration options, see the Client Schema page.", "title": "Client versus Server Configuration"}, {"location": "janssen-server/auth-server/config/#interception-scripts", "text": "Janssen is a very flexible platform, that lets you customize many of the flows to meet your exact requirements. The black magic behind this flexibility is interception scripts--these are standard programming interfaces that enable you to add or change the behavior of Jans endpoints. Just to give one example, perhaps you need to add data from an external API into an OAuth access token? In this case, you could use the Update Token interception script. There are around 20 of these scripts. For a full list, see the Scripts Documentation .", "title": "Interception Scripts"}, {"location": "janssen-server/auth-server/config/#customization", "text": "You don't want out of the box look and feel provided by Janssen. We know we are UX-challenged, backend developer geeks. Check out the Customization Guide for info about how to add adapt the user facing content to achieve your UX dreams.", "title": "Customization"}, {"location": "janssen-server/auth-server/config/#operations", "text": "Janssen Project software has to run somewhere, right now... either on VM's or in containers. There are specifics instructions about each contained in these docs.", "title": "Operations"}, {"location": "janssen-server/auth-server/config/#database-and-cache", "text": "One of the biggest challenges in running the Janssen Platform is persistence. Make sure you understand how Janssen Project stores your data, or in some cases, caches it.", "title": "Database and Cache"}, {"location": "janssen-server/auth-server/client-management/client-authn/", "tags": ["administration", "client", "authentication"], "text": "Client Authentication # Janssen Server supports authentication at the token endpoint for confidential clients. Confidential clients have to specify a preferred method of authentication during the client registration process. Client authentication is defined by OAuth and OpenID Connect client authentication section and in Metadata section property token_endpoint_auth_method Supported Authentication Methods # List of supported authentication methods are listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration The token_endpoint_auth_methods_supported claim in the response specifies the list of all the supported methods. Authentication Methods # Authentication methods can be broadly categorised in two categories: Shared key based Private( or asymmetric) key based While shared key based authentication is simpler to implement, it is less secure than a private key based authentication. This is primarily because when using shared key based authentication, the client secret is transmitted between the client and the authorization server. This makes the authentication vulnerable to theft attacks. There are more reasons to prefer private key over shared secret as listed in this section Characteristics table below shows side-by-side comparison of various supported authentication methods. Method Secret Not Sent in Clear Signed Only client has secret Expiry Token Binding client_secret_basic client_secret_post client_secret_jwt private_key_jwt tls_client_auth self_signed_tls_client_auth client_secret_basic # Default authentication method for Janssen Server. It authenticates clients using method described in client authentication section of OAuth framework. client_secret_post # client_secret_post method authenticates clients using method described in client authentication section of OAuth framework by adding client credentials in request body. client_secret_jwt # Like client_secret_basic and client_secret_post methods, this method is also based on a shared secret that client receives from Janssen Server. But instead of sending secret back to authorization server everytime, the client creates a JWT using an HMAC SHA algorithm where the shared secret is used as the key. This method is more secure than the client_secret_basic and client_secret_post due to following reasons: Secret which is shared once will never be transmitted again JWT can have expiration time, beyond which the same JWT can not be used. This reduces the time window for replay of the same token in case it is compromised. This method is further described in OpenId Connect specification, section 9 . Client Configuration For Using client_secret_jwt # Janssen Server clients should specify the preferred algorithm for use with this method during client configuration. Algorithms supported by Janssen Server are listed in the response of Janssen Server's well-known configuration endpoint . From the response, the claim token_endpoint_auth_signing_alg_values_supported lists the supported algorithms. To specify preferred algorithm for a client, using Janssen Text-based UI(TUI) , navigate via Auth Server -> Get or add clients -> encryption/signing -> TODO: which exact properties. private_key_jwt # private_key_jwt is private key based method where secret is not shared between client and authorization server. Instead, the client generates an JSON Web Token(JWT) which is shared with the Janssen Server. Upon receiving JWT singned by client's private key, the Janssen Server can validate this JWT using public keys supplied by client at the time of registration. The client can supply public keys in form of JSON Web Key Set(JWKS) or provide a URI where the client publishes its JWKS. Providing JWKS URI is preferred method as it enable easy key rotations without client having to update JWKS manualy. Check jwks and jwks_uri elements in OIDC client metadata section for more details. This authentication method is further described in OpenId Connect specification, section 9 . Janssen server implements signing and encryption mechanism following the guidelines in section 10 of OpenId Connect specification. Clients should choose the algorithm to sign and encrypt JWT as per their security requirements. Security Features Of Private Key Authentication # This method of authentication is more secure than the methods relying on shared key due to following features. Secure Storage : Hardware Security Module(HSM) or Trusted Platform Module(TPM) can be used to securely store private key and sign using it at client side. These modules make it impossible to access private key from outside. Smaller footprint : Unlike shared secret, where client secret resides on authorization server as well as client, the private key only exists on client. This reduced footprint reduces potential risks. Limited Time Validity : JWT can be set to expire after a certain duration. Similarly, client certificates can be made to expire. This makes it harder to execute replay attacks using a compromised token or certificate. Implementation Steps # Below are the high-level steps involved in using private_key_jwt authentication method: Create JWK private key Derive JWK public key for the private key. Public key JWK should be provided to Janssen Server at the time of registration Create JWT header and payload as described in section 9 of specification Sign JWT with a signing algorithm Client code that implements above steps should leverage any of the secure and trusted library that implements these functions. A non-exhaustive list of such libraries can be found at jwt.io . Psudocode implementation for Java based client using nimbus-jose-jwt library can be found here Client Configuration For Using private_key_jwt # Janssen Server clients can specify signing and encryption keys using client configuration. Clients can either specify JWKS as value or as reference URI. To specify JWKS values or reference URI, using Janssen Text-based UI(TUI) , navigate via Auth Server -> Get or add clients -> encryption/signing -> set value for Client JWKS URI or Client JWKS . tls_client_auth # During TLS handshake, the client authenticates with Janssen Server using X.509 certificate that is issued by a Certificate Authority(CA). This is mutual TLS based authentication method. Benefit of using mutual TLS based authentication is that the authorization server binds the token with the certificate. This provides enhanced security where it is possible to check that the token belongs to the intended client. This authentication mechanism is defined in mTLS specification for OAuth2 self_signed_tls_client_auth # Client authenticates with Janssen Server using self signed X.509 certificate during TLS handshake. Use of self-signed certificate removes the dependency of public key infrastructure(PKIX). This is mutual TLS based authentication method. Benefit of using mutual TLS based authentication is that the authorization server binds the token with the certificate. This provides enhanced security where it is possible to check that the token belongs to the intended client. This authentication mechanism is defined in mTLS specification for OAuth2 none # The Client does not authenticate itself at the Token Endpoint, either because it uses only the Implicit Flow (and so does not use the Token Endpoint) or because it is a Public Client with no Client Secret or other authentication mechanism. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Client Authentication"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client-authentication", "text": "Janssen Server supports authentication at the token endpoint for confidential clients. Confidential clients have to specify a preferred method of authentication during the client registration process. Client authentication is defined by OAuth and OpenID Connect client authentication section and in Metadata section property token_endpoint_auth_method", "title": "Client Authentication"}, {"location": "janssen-server/auth-server/client-management/client-authn/#supported-authentication-methods", "text": "List of supported authentication methods are listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration The token_endpoint_auth_methods_supported claim in the response specifies the list of all the supported methods.", "title": "Supported Authentication Methods"}, {"location": "janssen-server/auth-server/client-management/client-authn/#authentication-methods", "text": "Authentication methods can be broadly categorised in two categories: Shared key based Private( or asymmetric) key based While shared key based authentication is simpler to implement, it is less secure than a private key based authentication. This is primarily because when using shared key based authentication, the client secret is transmitted between the client and the authorization server. This makes the authentication vulnerable to theft attacks. There are more reasons to prefer private key over shared secret as listed in this section Characteristics table below shows side-by-side comparison of various supported authentication methods. Method Secret Not Sent in Clear Signed Only client has secret Expiry Token Binding client_secret_basic client_secret_post client_secret_jwt private_key_jwt tls_client_auth self_signed_tls_client_auth", "title": "Authentication Methods"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client_secret_basic", "text": "Default authentication method for Janssen Server. It authenticates clients using method described in client authentication section of OAuth framework.", "title": "client_secret_basic"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client_secret_post", "text": "client_secret_post method authenticates clients using method described in client authentication section of OAuth framework by adding client credentials in request body.", "title": "client_secret_post"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client_secret_jwt", "text": "Like client_secret_basic and client_secret_post methods, this method is also based on a shared secret that client receives from Janssen Server. But instead of sending secret back to authorization server everytime, the client creates a JWT using an HMAC SHA algorithm where the shared secret is used as the key. This method is more secure than the client_secret_basic and client_secret_post due to following reasons: Secret which is shared once will never be transmitted again JWT can have expiration time, beyond which the same JWT can not be used. This reduces the time window for replay of the same token in case it is compromised. This method is further described in OpenId Connect specification, section 9 .", "title": "client_secret_jwt"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client-configuration-for-using-client_secret_jwt", "text": "Janssen Server clients should specify the preferred algorithm for use with this method during client configuration. Algorithms supported by Janssen Server are listed in the response of Janssen Server's well-known configuration endpoint . From the response, the claim token_endpoint_auth_signing_alg_values_supported lists the supported algorithms. To specify preferred algorithm for a client, using Janssen Text-based UI(TUI) , navigate via Auth Server -> Get or add clients -> encryption/signing -> TODO: which exact properties.", "title": "Client Configuration For Using client_secret_jwt"}, {"location": "janssen-server/auth-server/client-management/client-authn/#private_key_jwt", "text": "private_key_jwt is private key based method where secret is not shared between client and authorization server. Instead, the client generates an JSON Web Token(JWT) which is shared with the Janssen Server. Upon receiving JWT singned by client's private key, the Janssen Server can validate this JWT using public keys supplied by client at the time of registration. The client can supply public keys in form of JSON Web Key Set(JWKS) or provide a URI where the client publishes its JWKS. Providing JWKS URI is preferred method as it enable easy key rotations without client having to update JWKS manualy. Check jwks and jwks_uri elements in OIDC client metadata section for more details. This authentication method is further described in OpenId Connect specification, section 9 . Janssen server implements signing and encryption mechanism following the guidelines in section 10 of OpenId Connect specification. Clients should choose the algorithm to sign and encrypt JWT as per their security requirements.", "title": "private_key_jwt"}, {"location": "janssen-server/auth-server/client-management/client-authn/#security-features-of-private-key-authentication", "text": "This method of authentication is more secure than the methods relying on shared key due to following features. Secure Storage : Hardware Security Module(HSM) or Trusted Platform Module(TPM) can be used to securely store private key and sign using it at client side. These modules make it impossible to access private key from outside. Smaller footprint : Unlike shared secret, where client secret resides on authorization server as well as client, the private key only exists on client. This reduced footprint reduces potential risks. Limited Time Validity : JWT can be set to expire after a certain duration. Similarly, client certificates can be made to expire. This makes it harder to execute replay attacks using a compromised token or certificate.", "title": "Security Features Of Private Key Authentication"}, {"location": "janssen-server/auth-server/client-management/client-authn/#implementation-steps", "text": "Below are the high-level steps involved in using private_key_jwt authentication method: Create JWK private key Derive JWK public key for the private key. Public key JWK should be provided to Janssen Server at the time of registration Create JWT header and payload as described in section 9 of specification Sign JWT with a signing algorithm Client code that implements above steps should leverage any of the secure and trusted library that implements these functions. A non-exhaustive list of such libraries can be found at jwt.io . Psudocode implementation for Java based client using nimbus-jose-jwt library can be found here", "title": "Implementation Steps"}, {"location": "janssen-server/auth-server/client-management/client-authn/#client-configuration-for-using-private_key_jwt", "text": "Janssen Server clients can specify signing and encryption keys using client configuration. Clients can either specify JWKS as value or as reference URI. To specify JWKS values or reference URI, using Janssen Text-based UI(TUI) , navigate via Auth Server -> Get or add clients -> encryption/signing -> set value for Client JWKS URI or Client JWKS .", "title": "Client Configuration For Using private_key_jwt"}, {"location": "janssen-server/auth-server/client-management/client-authn/#tls_client_auth", "text": "During TLS handshake, the client authenticates with Janssen Server using X.509 certificate that is issued by a Certificate Authority(CA). This is mutual TLS based authentication method. Benefit of using mutual TLS based authentication is that the authorization server binds the token with the certificate. This provides enhanced security where it is possible to check that the token belongs to the intended client. This authentication mechanism is defined in mTLS specification for OAuth2", "title": "tls_client_auth"}, {"location": "janssen-server/auth-server/client-management/client-authn/#self_signed_tls_client_auth", "text": "Client authenticates with Janssen Server using self signed X.509 certificate during TLS handshake. Use of self-signed certificate removes the dependency of public key infrastructure(PKIX). This is mutual TLS based authentication method. Benefit of using mutual TLS based authentication is that the authorization server binds the token with the certificate. This provides enhanced security where it is possible to check that the token belongs to the intended client. This authentication mechanism is defined in mTLS specification for OAuth2", "title": "self_signed_tls_client_auth"}, {"location": "janssen-server/auth-server/client-management/client-authn/#none", "text": "The Client does not authenticate itself at the Token Endpoint, either because it uses only the Implicit Flow (and so does not use the Token Endpoint) or because it is a Public Client with no Client Secret or other authentication mechanism.", "title": "none"}, {"location": "janssen-server/auth-server/client-management/client-authn/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/client-management/client-configuration/", "tags": ["administration", "client", "configuration"], "text": "Client Configuration # This document covers some important configuration elements of client configuration. How these elements are configured for a client has an impact on aspects like client security. Redirect URI # Redirect URI is the most basic and at times the only parameter needed for registering a client. It is defined in OAuth framework and OpenId Connect specification . The client can register a list of URIs as a value for redirect URI parameter. Redirect URI can be any valid URI . Redirect URI should be an absolute URI . For instance, URI should not have wildcard characters. As recommended here Redirect Regex : Janssen Server enables clients to allow redirect URIs that conform to a regular expression(regex) pattern. While validating redirect URIs received in an incoming request, the Janssen Server first looks at the list of statically registered URI as part of Redirect URIs and then checks if any of the redirect URI from the request matches with the regex provided by the client. Great care should be exercised when using regex to ensure that it accurately matches with the intended patterns only. This feature can be turned on or off via feature flag When using client type as web , the redirect URI generally takes the form of <schema>://<host-name>:<port>/<path> . It must use https schema. The exception to schema rule is made when localhost or loopback ip 127.0.0.1 is used as the hostname. Prefer to use the loopback IP instead of localhost as hostname to facilitate local testing as recommended in OAuth 2.0 native app specification section 8.3 Janssen Server supports all methods of redirection used by native apps . Use of Private-Use URI (or custom URL) is supported by allowing redirect URI to take the form of reverse DNS name, for example, com.example.app . URLs for loopback interface redirection are also supported. When the client registers multiple redirect URIs (Janssen Server accepts a list of URIs separated by space), be aware that Janssen Server will use these, one by one for validation purposes and the validation stops at the first match. If there are multiple registered redirect_uris, and the client is using pairwise subject identifiers, the Client MUST also register a sector_identifier_uri . This is required to keep the pairwise subject identifiers consistent across various domains under the same administrative control. Refer to pairwise algorithm section of OpenId Connect specification for more details. Cryptography # Janssen Server allows clients to configure static set of keys using JWKS or specify a URI as JWKS URI where client is exposing its key set. For client who can host keys and expose a URI, it is recommended to use JWKS URI instead of static JWKS key set. Using JWKS URI enables client to rotate its cryptographic keys without having to change the client configuration on Janssen Server. Available Algorithms for Encryption and Signing # The client can select algorithms for cryptographic and encryption during client configuration. Janssen Server supports a list of algorithms as listed in response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claims that list supported algorithms: id_token_encryption_alg_values_supported id_token_signing_alg_values_supported userinfo_encryption_enc_values_supported userinfo_signing_alg_values_supported userinfo_encryption_alg_values_supported access_token_signing_alg_values_supported request_object_signing_alg_values_supported request_object_encryption_alg_values_supported request_object_encryption_alg_values_supported Recommendations # RSA keys with a minimum 2048 bits if using RSA cryptography Elliptic Curve keys with a minimum of 160 bits if using Elliptic Curve cryptography Client secret should have a minimum of 128 bits if using symmetric key cryptography Sign with PS256 (RSASSA-PSS using SHA-256 and MGF1 with SHA-256) or ES256 (ECDSA using P-256 and SHA-256) Grants # Supported Grant Types # Grant defines how a client interacts with the token endpoint to get the tokens. Janssen Server supports grant types defined by OAuth 2.0, OAuth 2.1, and extension grants defined by other RFCs. A complete list of supported grant types can be found in the response of the Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claim grant_types_supported lists all the supported grant types in the response. Configuring Grant Type For Client # Janssen Server will allow requests from a client with grant types that the client is configured to use. Client can be configured to use or not use certain grant types using CLI or TUI tools. Recommendations For Using Grant Types and Flows # Developers should use the grant types based on the ability of the client to protect the client credentials as well as the security profile of the deployment. If the client software is a server-side component that can securely store the client credentials, such a client is called a confidential client. As opposed to that, if the application requesting access token is entirely running on a browser, where it is not possible to store client credentials securely, such a client is called a public client. Along with the grant type to be used, developers also need to choose which flow should be used to get the required tokens. The table below shows grant types and flows that should be used for various use-cases. Client Type Recommended Grant Type Flow Backend App (Example: batch processes) that need to access its own resources client_credentials Client Credentials Server backend of a web-application needs access token authorization_code Authorization Code Web-application that needs user information via id_token on browser and access token on backend authorization_code Hybrid Flow Browser based single page applications or Mobile applications authorization_code Authorization Code with PKCE Browser based single page applications or Mobile applications that only intend to get id_token - Implicit Flow with Form Post Input constrained devices (Example: TV) urn:ietf:params:oauth:grant-type:device_code Device Flow Highly trusted applications where redirect based flows are not feasible to implement password Resource Owner Password Flow Note Certain grant types should not be used together. For example, implicit flow with hybrid flow. Or using authorization code flow with hybrid flow. This allows a downgrade attack from more secure flow to less secure flow. Pre-authorization # If the OAuth authorization prompt should not be displayed to end users, set this field to True. This is useful for SSO to internal clients (not a third party) where there is no need to prompt the person to approve the release of information. Response Types # Client sends response_type request parameter when sending request to authorization endpoint. Using this parameter, the client informs the authorization server of the desired grant. Response type parameter is defined in the OAuth 2.0 framework. Janssen Server supports response types defined by OAuth 2.0, OAuth 2.1.The complete list of supported response types can be found in the response of the Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claim response_types_supported lists all the supported grant types in the response. When registering client using dynamic client registration, if the response_type parameter is not specified, it'll default to code . Response Type Recommendations # Avoid using response type token . This response type is deprecated by OAuth 2.1. Grant types allowed for a client determines which response types are permitted in authorization requests. Make sure appropriate grant types are configured in Janssen Server client configuration. Janssen Server will reject authorization requests containing response types not permitted for respective client. Client expiration # Client expiration is set based on dynamicRegistrationExpirationTime AS configuration property or otherwise if dcrForbidExpirationTimeInRequest is false then it is set with Dynamic Client Registration Request via lifetime parameter which expected value in seconds. Client also can be cleaned up by inactivity period which is set via cleanUpInactiveClientAfterHoursOfInactivity AS configuration property. By default it has 0 value (which means it is off). Client activity time is tracked/recorded each time client is used for authentication or authorization (date is written in jansLastAccessTime client attribute). Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "Configuration"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#client-configuration", "text": "This document covers some important configuration elements of client configuration. How these elements are configured for a client has an impact on aspects like client security.", "title": "Client Configuration"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#redirect-uri", "text": "Redirect URI is the most basic and at times the only parameter needed for registering a client. It is defined in OAuth framework and OpenId Connect specification . The client can register a list of URIs as a value for redirect URI parameter. Redirect URI can be any valid URI . Redirect URI should be an absolute URI . For instance, URI should not have wildcard characters. As recommended here Redirect Regex : Janssen Server enables clients to allow redirect URIs that conform to a regular expression(regex) pattern. While validating redirect URIs received in an incoming request, the Janssen Server first looks at the list of statically registered URI as part of Redirect URIs and then checks if any of the redirect URI from the request matches with the regex provided by the client. Great care should be exercised when using regex to ensure that it accurately matches with the intended patterns only. This feature can be turned on or off via feature flag When using client type as web , the redirect URI generally takes the form of <schema>://<host-name>:<port>/<path> . It must use https schema. The exception to schema rule is made when localhost or loopback ip 127.0.0.1 is used as the hostname. Prefer to use the loopback IP instead of localhost as hostname to facilitate local testing as recommended in OAuth 2.0 native app specification section 8.3 Janssen Server supports all methods of redirection used by native apps . Use of Private-Use URI (or custom URL) is supported by allowing redirect URI to take the form of reverse DNS name, for example, com.example.app . URLs for loopback interface redirection are also supported. When the client registers multiple redirect URIs (Janssen Server accepts a list of URIs separated by space), be aware that Janssen Server will use these, one by one for validation purposes and the validation stops at the first match. If there are multiple registered redirect_uris, and the client is using pairwise subject identifiers, the Client MUST also register a sector_identifier_uri . This is required to keep the pairwise subject identifiers consistent across various domains under the same administrative control. Refer to pairwise algorithm section of OpenId Connect specification for more details.", "title": "Redirect URI"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#cryptography", "text": "Janssen Server allows clients to configure static set of keys using JWKS or specify a URI as JWKS URI where client is exposing its key set. For client who can host keys and expose a URI, it is recommended to use JWKS URI instead of static JWKS key set. Using JWKS URI enables client to rotate its cryptographic keys without having to change the client configuration on Janssen Server.", "title": "Cryptography"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#available-algorithms-for-encryption-and-signing", "text": "The client can select algorithms for cryptographic and encryption during client configuration. Janssen Server supports a list of algorithms as listed in response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claims that list supported algorithms: id_token_encryption_alg_values_supported id_token_signing_alg_values_supported userinfo_encryption_enc_values_supported userinfo_signing_alg_values_supported userinfo_encryption_alg_values_supported access_token_signing_alg_values_supported request_object_signing_alg_values_supported request_object_encryption_alg_values_supported request_object_encryption_alg_values_supported", "title": "Available Algorithms for Encryption and Signing"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#recommendations", "text": "RSA keys with a minimum 2048 bits if using RSA cryptography Elliptic Curve keys with a minimum of 160 bits if using Elliptic Curve cryptography Client secret should have a minimum of 128 bits if using symmetric key cryptography Sign with PS256 (RSASSA-PSS using SHA-256 and MGF1 with SHA-256) or ES256 (ECDSA using P-256 and SHA-256)", "title": "Recommendations"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#grants", "text": "", "title": "Grants"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#supported-grant-types", "text": "Grant defines how a client interacts with the token endpoint to get the tokens. Janssen Server supports grant types defined by OAuth 2.0, OAuth 2.1, and extension grants defined by other RFCs. A complete list of supported grant types can be found in the response of the Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claim grant_types_supported lists all the supported grant types in the response.", "title": "Supported Grant Types"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#configuring-grant-type-for-client", "text": "Janssen Server will allow requests from a client with grant types that the client is configured to use. Client can be configured to use or not use certain grant types using CLI or TUI tools.", "title": "Configuring Grant Type For Client"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#recommendations-for-using-grant-types-and-flows", "text": "Developers should use the grant types based on the ability of the client to protect the client credentials as well as the security profile of the deployment. If the client software is a server-side component that can securely store the client credentials, such a client is called a confidential client. As opposed to that, if the application requesting access token is entirely running on a browser, where it is not possible to store client credentials securely, such a client is called a public client. Along with the grant type to be used, developers also need to choose which flow should be used to get the required tokens. The table below shows grant types and flows that should be used for various use-cases. Client Type Recommended Grant Type Flow Backend App (Example: batch processes) that need to access its own resources client_credentials Client Credentials Server backend of a web-application needs access token authorization_code Authorization Code Web-application that needs user information via id_token on browser and access token on backend authorization_code Hybrid Flow Browser based single page applications or Mobile applications authorization_code Authorization Code with PKCE Browser based single page applications or Mobile applications that only intend to get id_token - Implicit Flow with Form Post Input constrained devices (Example: TV) urn:ietf:params:oauth:grant-type:device_code Device Flow Highly trusted applications where redirect based flows are not feasible to implement password Resource Owner Password Flow Note Certain grant types should not be used together. For example, implicit flow with hybrid flow. Or using authorization code flow with hybrid flow. This allows a downgrade attack from more secure flow to less secure flow.", "title": "Recommendations For Using Grant Types and Flows"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#pre-authorization", "text": "If the OAuth authorization prompt should not be displayed to end users, set this field to True. This is useful for SSO to internal clients (not a third party) where there is no need to prompt the person to approve the release of information.", "title": "Pre-authorization"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#response-types", "text": "Client sends response_type request parameter when sending request to authorization endpoint. Using this parameter, the client informs the authorization server of the desired grant. Response type parameter is defined in the OAuth 2.0 framework. Janssen Server supports response types defined by OAuth 2.0, OAuth 2.1.The complete list of supported response types can be found in the response of the Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration Claim response_types_supported lists all the supported grant types in the response. When registering client using dynamic client registration, if the response_type parameter is not specified, it'll default to code .", "title": "Response Types"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#response-type-recommendations", "text": "Avoid using response type token . This response type is deprecated by OAuth 2.1. Grant types allowed for a client determines which response types are permitted in authorization requests. Make sure appropriate grant types are configured in Janssen Server client configuration. Janssen Server will reject authorization requests containing response types not permitted for respective client.", "title": "Response Type Recommendations"}, {"location": "janssen-server/auth-server/client-management/client-configuration/#client-expiration", "text": "Client expiration is set based on dynamicRegistrationExpirationTime AS configuration property or otherwise if dcrForbidExpirationTimeInRequest is false then it is set with Dynamic Client Registration Request via lifetime parameter which expected value in seconds. Client also can be cleaned up by inactivity period which is set via cleanUpInactiveClientAfterHoursOfInactivity AS configuration property. By default it has 0 value (which means it is off). Client activity time is tracked/recorded each time client is used for authentication or authorization (date is written in jansLastAccessTime client attribute). Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "Client expiration"}, {"location": "janssen-server/auth-server/client-management/client-schema/", "tags": ["administration", "client", "schema"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Client Schema"}, {"location": "janssen-server/auth-server/client-management/client-schema/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/client-management/client-schema/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/client-management/client-schema/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/client-management/client-scripts/", "tags": ["administration", "client", "scripts"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Client Scripts"}, {"location": "janssen-server/auth-server/client-management/client-scripts/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/client-management/client-scripts/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/client-management/client-scripts/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/", "tags": ["administration", "client", "sector-identifier"], "text": "Sector Identifier # Janssen Server supports sector identifier URI and pairwise subject IDs for OpenId Connect relying party. As defined in OpenId Connect core specification , the sector identifiers value is used to derive pairwise subject IDs. Janssen Server also supports Sector Identifier URI as part of client configuration. Sector Identifier URI when used with pairwise subject type, enables a group of websites under the same administrative control to receive the same subject identifiers. Sector Identifier URI also allows clients to change the host component of the redirect URI and still keep the subject identifiers unchanged. Configuring Sector Identifier # Janssen Server runs below mentioned checks on value configured for Sector Identifier URI : URI should have a https schema URI should be accessible to Janssen Server and the response should be a valid JSON array of redirect URIs All redirect URI received in response must exist in the list of the redirect URI provided by the client at the registration time Note If the client can not host an endpoint that will be reachable by Sector Identifier URI , then in order to use the pairwise subject IDs, the client must supply a Redirect URI list where URIs have the same host component. The host component value will be used as the sector identifier. Configuration With Pairwise Subject Type # How sector identifier value is used to derive value for the pairwise subject identifier is detailed in the OIDC core specification . Janssen Server allows clients/RPs to set subject type. The public subject type is the default and the client/RP can choose to use the pairwise type. When using TUI, this can be configured from the client configuration screen below: When the pairwise subject type is selected, the value for Sector Identifier URI can be left blank if all redirect URIs have the same host component. If the list of redirect URIs contains multiple host names, providing a Sector Identifier URI is a must. When Sector Identifier URI is provided, the host component of the URI is used as a sector identifier. Configuration Properties # Janssen Server allows customization concerning sector identifiers using the properties below: sectorIdentifierCacheLifetimeInMinutes shareSubjectIdBetweenClientsWithSameSectorId Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Sector Identifiers"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/#sector-identifier", "text": "Janssen Server supports sector identifier URI and pairwise subject IDs for OpenId Connect relying party. As defined in OpenId Connect core specification , the sector identifiers value is used to derive pairwise subject IDs. Janssen Server also supports Sector Identifier URI as part of client configuration. Sector Identifier URI when used with pairwise subject type, enables a group of websites under the same administrative control to receive the same subject identifiers. Sector Identifier URI also allows clients to change the host component of the redirect URI and still keep the subject identifiers unchanged.", "title": "Sector Identifier"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/#configuring-sector-identifier", "text": "Janssen Server runs below mentioned checks on value configured for Sector Identifier URI : URI should have a https schema URI should be accessible to Janssen Server and the response should be a valid JSON array of redirect URIs All redirect URI received in response must exist in the list of the redirect URI provided by the client at the registration time Note If the client can not host an endpoint that will be reachable by Sector Identifier URI , then in order to use the pairwise subject IDs, the client must supply a Redirect URI list where URIs have the same host component. The host component value will be used as the sector identifier.", "title": "Configuring Sector Identifier"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/#configuration-with-pairwise-subject-type", "text": "How sector identifier value is used to derive value for the pairwise subject identifier is detailed in the OIDC core specification . Janssen Server allows clients/RPs to set subject type. The public subject type is the default and the client/RP can choose to use the pairwise type. When using TUI, this can be configured from the client configuration screen below: When the pairwise subject type is selected, the value for Sector Identifier URI can be left blank if all redirect URIs have the same host component. If the list of redirect URIs contains multiple host names, providing a Sector Identifier URI is a must. When Sector Identifier URI is provided, the host component of the URI is used as a sector identifier.", "title": "Configuration With Pairwise Subject Type"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/#configuration-properties", "text": "Janssen Server allows customization concerning sector identifiers using the properties below: sectorIdentifierCacheLifetimeInMinutes shareSubjectIdBetweenClientsWithSameSectorId", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/client-management/sector-identifiers/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/client-management/software-statements/", "tags": ["administration", "client", "software statements"], "text": "Software Statements # Software Statement is defined by OAuth dynamic client registration RFC 7591 as A digitally signed or MACed JSON Web Token (JWT) that asserts metadata values about the client software. Janssen Server supports usage of software statements during dynamic client registration. Use During Dynamic Client Registration # Janssen Server supports dynamic client registration using software statements. It can be used as software statements or as software statement assertions (SSA) to register client dynamically. Janssen Server also provides SSA endpoint to create and manage SSAs on the server. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Software Statements"}, {"location": "janssen-server/auth-server/client-management/software-statements/#software-statements", "text": "Software Statement is defined by OAuth dynamic client registration RFC 7591 as A digitally signed or MACed JSON Web Token (JWT) that asserts metadata values about the client software. Janssen Server supports usage of software statements during dynamic client registration.", "title": "Software Statements"}, {"location": "janssen-server/auth-server/client-management/software-statements/#use-during-dynamic-client-registration", "text": "Janssen Server supports dynamic client registration using software statements. It can be used as software statements or as software statement assertions (SSA) to register client dynamically. Janssen Server also provides SSA endpoint to create and manage SSAs on the server.", "title": "Use During Dynamic Client Registration"}, {"location": "janssen-server/auth-server/client-management/software-statements/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/crypto/key-generation/", "tags": ["administration", "auth-server", "cryptography", "key generation"], "text": "Key Generation # Generating Cryptographic Keys # The Jans Server is compatible with the Java KeyGenerator to create new cryptographic keys if needed. Backup # Backup jansConfWebKeys attribute data of jansAppConf entity from persistence. Location of this attribute is: o=jans > ou=configuration > ou=jans-auth Backup jans-auth-keys.p12 from /etc/certs/ [N.B] Below if Keystore location is anywhere except /etc/certs/ no need to backup. Key Generate # To get KeyGenerator, run the following command inside the terminal. You can put expiration according to your own policy. For testing purpose we are keeping it 2 days. /opt/jre/bin/java -Dlog4j.defaultInitOverride=true -cp /opt/dist/jans/jans-auth-client-jar-with-dependencies.jar io.jans.as.client.util.KeyGenerator -keystore /etc/certs/jans-auth-keys.p12 -keypasswd <Password> -sig_keys RS256 RS384 -enc_keys RSA1_5 RSA-OAEP -key_ops_type ALL -dnname \"CN=jansAuth CA Certificates\" -expiration 2 > /etc/certs/jans-auth-keys.json Note -key_ops_type ALL parameter which sets purpose of the keys generated by key generator. Possible values are: \"connect\" - connect keys (that is what we already have) \"ssa\" - ssa keys which has expiration set to 50 years (it ignores \"expiration\" parameters) \"all\" - generate both \"connect\" and \"ssa\" keys. Usually should be done during initial setup. Lets see our newly generated crypto keys keytool -list -v -keystore /etc/certs/jans-auth-keys.p12 -storetype pkcs12 -storepass <password> The jans implementation of KeyGenerator accepts the following arguments: Argument Description -dnname DN of certificate issuer -key_length Length of hash key -enc_keys Encryption keys to generate (For example: RSA_OAEP, RSA1_5) -expiration Expiration in days -expiration_hours Expiration in hours -h Show help -key_ops_type Purpose of the key, possible values: connect, ssa, all -keypasswd Key Store password -keystore Key Store file (such as /etc/certs/jans-auth-keys.p12) -sig_keys Signature keys to generate. (For example: RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512) _keyId Key name suffix -test_prop_file Test property file used for test purpose only", "title": "Key Rotation and Generation"}, {"location": "janssen-server/auth-server/crypto/key-generation/#key-generation", "text": "", "title": "Key Generation"}, {"location": "janssen-server/auth-server/crypto/key-generation/#generating-cryptographic-keys", "text": "The Jans Server is compatible with the Java KeyGenerator to create new cryptographic keys if needed.", "title": "Generating Cryptographic Keys"}, {"location": "janssen-server/auth-server/crypto/key-generation/#backup", "text": "Backup jansConfWebKeys attribute data of jansAppConf entity from persistence. Location of this attribute is: o=jans > ou=configuration > ou=jans-auth Backup jans-auth-keys.p12 from /etc/certs/ [N.B] Below if Keystore location is anywhere except /etc/certs/ no need to backup.", "title": "Backup"}, {"location": "janssen-server/auth-server/crypto/key-generation/#key-generate", "text": "To get KeyGenerator, run the following command inside the terminal. You can put expiration according to your own policy. For testing purpose we are keeping it 2 days. /opt/jre/bin/java -Dlog4j.defaultInitOverride=true -cp /opt/dist/jans/jans-auth-client-jar-with-dependencies.jar io.jans.as.client.util.KeyGenerator -keystore /etc/certs/jans-auth-keys.p12 -keypasswd <Password> -sig_keys RS256 RS384 -enc_keys RSA1_5 RSA-OAEP -key_ops_type ALL -dnname \"CN=jansAuth CA Certificates\" -expiration 2 > /etc/certs/jans-auth-keys.json Note -key_ops_type ALL parameter which sets purpose of the keys generated by key generator. Possible values are: \"connect\" - connect keys (that is what we already have) \"ssa\" - ssa keys which has expiration set to 50 years (it ignores \"expiration\" parameters) \"all\" - generate both \"connect\" and \"ssa\" keys. Usually should be done during initial setup. Lets see our newly generated crypto keys keytool -list -v -keystore /etc/certs/jans-auth-keys.p12 -storetype pkcs12 -storepass <password> The jans implementation of KeyGenerator accepts the following arguments: Argument Description -dnname DN of certificate issuer -key_length Length of hash key -enc_keys Encryption keys to generate (For example: RSA_OAEP, RSA1_5) -expiration Expiration in days -expiration_hours Expiration in hours -h Show help -key_ops_type Purpose of the key, possible values: connect, ssa, all -keypasswd Key Store password -keystore Key Store file (such as /etc/certs/jans-auth-keys.p12) -sig_keys Signature keys to generate. (For example: RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512) _keyId Key name suffix -test_prop_file Test property file used for test purpose only", "title": "Key Generate"}, {"location": "janssen-server/auth-server/crypto/key-storage/", "tags": ["administration", "auth-server", "cryptography", "key-storage"], "text": "Overview # A Java KeyStore is a file that contains set of aliases. Every alias can contain private key and public key and certificate (additional property info about owner of they key) or only public key and certificate. KeyStore stores the following type of data: - Private Keys; - Public Keys and Certificates; - Secret Keys. KeyStore are used by follow crypto primitives: - asymetric encryption; - digital signature; - symmetric-key algorithm. Janssen Key Storages # Janssen Key Storages # Janssen KeyStore files contain: - Private Keys; - Public Keys and Certificates. Supported Formats of Key Storages # There is some set of standardized KeyStore formats. Janssen applications use follow KeyStore formats: - JKS : Java KeyStore format (proprietary keystore implementation provided by the SUN provider). KeyStore file extensions: .jks , .keystore , .ks ; - PKCS#12 : Personal Information Exchange Syntax, developed by RSA Security. PKCS #12 defines an archive file format for storing many cryptography objects as a single file. KeyStore file extensions: .pkcs12 , .p12 , .pfx ; - BCFKS : Bouncy Castle FIPS Key Store (BCFKS) format supports storage of certificates and private keys using AES-CCM and PBKDF2 algorithms, providing greater security than the standard JKS and PKCS12 implementations. Support for BCFKS format is implemented, using BCFIPS Crypto Provider (https://www.bouncycastle.org/fips_java_roadmap.html). KeyStore file extensions: .bcfks , bcf , bcfips . Installed KeyStore files # Janssen installs KeyStore files in the directory: /etc/certs . Follow Keystore files are used by Janssen: jans-auth-keys.pkcs12 smtp-keys.pkcs12 . jans-auth-keys.pkcs12 # Here is the example of the file: /etc/certs/jans-auth-keys.pkcs12 (list of entries/aliases). keytool -list -v -storetype PKCS12 -keystore /etc/certs/jans-auth-keys.pkcs12 -storepass gNzpzYj5h8i1 Keystore type: PKCS12 Keystore provider: SUN Your keystore contains 31 entries Alias name: connect_3c83ba3a-7a62-49e7-8478-b6d3e242e549_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a81e8386d6774110b12a292a7185c454359b9b6d67a3f5aef587e9395db04166 Valid from: Thu Aug 17 05:21:05 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 4F:FD:3A:E6:61:D8:8E:0F:61:A4:AA:DE:D7:E4:F4:28:5E:EE:39:20 SHA256: 52:15:67:CE:0B:56:1C:CD:CE:C9:39:4C:11:25:B8:73:13:7F:7F:91:BB:E4:1A:3F:48:8D:B0:DC:01:D0:55:3D Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_45c2ce16-6d5b-47d4-be40-c4da48ba49d3_enc_ecdh-es+a128kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: c6fdff1d75c83e32519a94133f9954de22a2aea4fb20ef669bce2221c08cf21f Valid from: Thu Aug 17 05:21:17 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 02:35:E7:FC:50:47:4A:3A:EA:54:EE:92:CA:75:14:D0:A4:E0:0C:45 SHA256: 19:18:8F:68:68:A2:FE:E2:03:BC:E6:2E:87:24:D4:E9:B0:64:D8:44:7D:32:A1:DE:1C:1B:8E:9A:96:3F:32:5A Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_5365f93a-368d-4643-8708-1f4b31b62d47_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4d561c04da6bbe50ea15720e6c6898d35793e711eabc9eaa02ad7ed9dafa148b Valid from: Thu Aug 17 05:21:14 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: C7:B4:1A:9A:15:59:E6:45:AC:77:C7:1C:E4:7D:F2:01:EC:4B:59:AD SHA256: 75:11:06:F5:74:D7:B4:C4:0A:57:A5:88:AA:91:F9:57:4C:78:BE:D2:68:1F:0E:AF:0B:CA:16:2F:0F:FE:17:EA Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_5b5da374-2ccb-40ca-8544-9338fe7427ff_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 235fc012863b7291c3370978761a2df6a14796cc601b0fec801b84aa7281b116 Valid from: Thu Aug 17 05:21:03 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 17:33:24:FC:C8:F7:0C:10:7B:0A:30:5B:28:6E:30:AC:13:A5:FD:36 SHA256: E5:05:5A:7E:00:93:2E:8B:3E:AE:91:D5:B5:B5:1A:A9:51:37:FE:72:29:02:83:20:F7:6F:BC:BE:D9:FF:23:7E Signature algorithm name: SHA384withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_6218efa5-197e-49f5-919f-769e6d0aaaec_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 304513446352446c48e39017e3044545e0e2a4a71c36899eacfac775606e958d Valid from: Thu Aug 17 05:21:08 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: BE:27:21:18:F4:D4:F6:71:D9:4A:DF:A0:3F:F2:20:76:E1:3E:DD:05 SHA256: 39:FB:09:EC:BD:62:CF:B2:8B:6A:7F:D9:AF:34:64:7C:50:53:E9:E1:14:01:FE:35:B3:B6:03:8D:C6:E3:A3:68 Signature algorithm name: SHA512withECDSA Subject Public Key Algorithm: 521-bit EC (secp521r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_6dbf485d-9d78-49d0-b977-72608ca6b727_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6310f2b2c5fe5e9354d6352140bedf9efe986ed1c44e68d6dda2ccb46038a14c Valid from: Thu Aug 17 05:21:04 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: E1:78:BA:84:C1:9A:9F:6D:FF:32:1B:F4:D9:4E:AE:AE:23:A9:7F:52 SHA256: EF:C9:B8:40:82:E1:16:B2:7B:2C:E9:E4:47:17:5D:C2:AB:D7:AA:16:EE:11:95:19:F7:52:7C:20:E9:3C:82:91 Signature algorithm name: SHA512withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_7325add6-aaa6-4e4c-bfee-968fa7eba793_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ea8c7dfe1d28f4ff9f686f0eccd5b3d06c50d80b4751713cce0052997027c90f Valid from: Thu Aug 17 05:21:10 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 2D:71:05:C2:5C:5A:50:CD:C7:64:42:69:03:8B:BC:66:6F:F7:E3:2A SHA256: C8:DD:E9:2E:49:91:04:25:29:48:6F:CA:01:0B:6F:17:CA:29:01:C5:4D:2B:AF:3F:A3:25:03:16:12:34:5C:48 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_829abf33-03f1-4f35-a42e-bca49f992df4_enc_ecdh-es+a256kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 24c62ce19733ddce99573c073bfa890e29d48fbc4a1b4365748fdc0c420b793a Valid from: Thu Aug 17 05:21:18 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 66:FC:23:8E:08:80:2A:C8:74:08:A5:37:C2:6D:8F:68:AB:23:7E:D3 SHA256: 27:7B:A3:5D:E2:F3:6D:15:52:F8:D0:03:0A:7D:D5:B5:32:B9:4E:93:F1:C3:14:98:CA:98:E9:53:84:45:24:4C Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_87933d28-0523-4bd2-a078-a94e32887b04_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 276ab34dca0e41236756ae0863ebd5e16ea0b209645128f54da0c0dc1c12b64c Valid from: Thu Aug 17 05:21:06 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 53:23:C9:45:4D:D2:29:70:BA:EB:27:EB:83:66:AB:4C:B9:56:9E:83 SHA256: 42:38:33:97:94:ED:58:51:D4:F1:C8:E5:2E:AB:56:05:B0:1D:79:05:33:51:DA:0F:41:E9:E8:59:11:B8:0F:57 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256k1) key (disabled) Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_8d71b86c-5b81-444c-afdf-bb3da4de11e4_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d8344594dfcce15695d56f30178bc2a38bf3d432756bfd15a69242b3348876dd Valid from: Thu Aug 17 05:21:02 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 5D:75:82:47:5F:80:F9:2F:41:48:CF:01:9F:EE:66:0E:71:37:FA:83 SHA256: D1:92:1C:B1:D0:29:B8:23:73:FA:2E:89:11:2D:F1:8F:5E:2E:FE:B0:80:D1:CC:60:1B:B3:46:82:BA:04:9E:4B Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_9574dff8-1f98-421d-91bf-a760a18be2d2_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a92efd444e5ea4ac9cd573aa66746b3b90adf465d20ad1abb25d903619f30d6c Valid from: Thu Aug 17 05:21:11 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 29:CF:94:A6:DF:1E:85:59:A4:C1:62:1F:95:AB:67:31:1B:2D:07:6C SHA256: E5:72:DE:3F:C5:96:63:21:AB:82:B4:64:00:E6:19:9B:2C:B0:6D:7C:C6:8C:3D:5B:21:58:6A:3D:D1:CC:54:0D Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_9f70c848-95b6-48fe-a9e9-79b374848e28_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 46d231ec4e06d52ce1d5a4950f2f91ffc5dd107f5ac7a422225d55fb0004ae26 Valid from: Thu Aug 17 05:21:13 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: A5:82:D0:70:8D:19:A5:5D:DE:4D:CC:52:AE:FB:F4:FF:EF:1A:56:AE SHA256: BB:FA:F0:82:DC:71:84:90:74:C1:33:D9:BC:AE:35:EA:DD:6B:35:95:CE:45:DB:94:E9:9B:E9:39:A4:47:CD:B2 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_a28e886e-090b-42c3-b437-92c91106c0c1_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4f03840af117cdff5a44ae7f12050ead8934d460134a35088ba5cb3782046b9e Valid from: Thu Aug 17 05:21:16 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 24:00:50:A1:B6:FD:F3:EC:19:95:CE:0F:BA:4E:AE:C5:64:57:F7:0C SHA256: BC:02:64:A2:1E:B6:B3:BD:BE:15:8E:E6:8B:CA:1E:00:A0:13:D9:40:72:7E:93:0F:40:DB:58:B5:56:1B:08:54 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_b7920896-d087-4668-9ee5-66fd3cf56694_enc_rsa-oaep-256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 16d9f709786c58f4343b2fce290cafa4130cb706cae25bcc98970742879d6f1d Valid from: Thu Aug 17 05:21:15 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 28:B3:2B:59:0B:BF:DB:F1:05:63:27:C3:9B:CD:35:14:54:A9:A3:16 SHA256: D9:55:37:5E:2E:AE:48:3E:72:DF:39:E2:0B:D8:79:4F:A3:21:33:EF:DA:DF:24:22:8B:42:08:61:E5:7F:F8:9F Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_c50ce977-00c0-4f4a-8594-1a0bc3935f88_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: c1992dccc3c0635dea6f34ac0f03414cc5f2422883dde72e8c07ea3fba66e865 Valid from: Thu Aug 17 05:21:09 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 65:CC:C8:CF:EA:54:C8:2C:27:31:59:34:5E:69:41:CE:09:37:EB:6B SHA256: C0:C8:68:75:BE:C1:CC:9F:4B:19:5E:23:9B:F4:3B:E8:E3:CE:B7:84:35:29:C0:8C:12:63:1E:B4:81:6B:23:99 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_e99b9f12-cbf5-4d5e-9156-12f112d7b4a3_sig_eddsa Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 523b5a9b1edbb4ac08435f1f86c7d810be34535e0bc02b073baeab6d9f35ca75 Valid from: Thu Aug 17 05:21:12 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: EB:D3:5F:54:76:44:D1:01:5F:39:EA:0B:2A:08:FB:30:39:50:E8:CC SHA256: 5F:99:18:AE:47:58:FD:7E:E3:B7:B4:F8:57:4A:5B:68:94:F8:DD:2A:02:DE:F7:58:8B:6A:06:D6:E2:CE:3E:ED Signature algorithm name: 1.3.101.112 Subject Public Key Algorithm: 1.3.101.112 key of unknown size Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_eb5d1996-197c-4913-9b10-201b4f371ff7_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 613554766f456cae0e968ecf8eaedd5fbb0f04c6ff64202c6b51df34cd7b2a20 Valid from: Thu Aug 17 05:21:07 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 50:FF:D2:51:CA:F6:35:31:C8:12:14:13:36:0B:A5:05:F4:08:3F:97 SHA256: 13:13:32:47:2B:5B:E7:20:EC:4B:77:E8:80:78:E0:84:DB:D9:5E:6D:6C:C6:86:5F:B5:6D:18:99:38:02:B0:32 Signature algorithm name: SHA384withECDSA Subject Public Key Algorithm: 384-bit EC (secp384r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_eddc097c-d9bc-4672-a6ec-2740f8ed99c4_enc_ecdh-es+a192kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9755e3a9d7404f86161bdfd47dc0f57021aa598b6f4bde9b3929a1303d66baef Valid from: Thu Aug 17 05:21:18 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 20:1F:EE:29:8F:57:B4:FA:29:E8:3F:D6:DD:60:0C:E7:6C:A6:82:54 SHA256: 6A:69:0F:0F:D0:51:5F:83:29:91:BB:E5:A7:63:48:14:F7:D1:C4:18:EE:4D:F2:28:50:63:18:2D:00:94:C7:F4 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_02674321-5bdc-451e-a8e0-12fbc494ab00_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: b544920f9433a67816ac7e022649057deeecd012b68344683ca92a680496b3dc Valid from: Tue Aug 08 06:57:41 CDT 2023 until: Tue Aug 08 06:57:51 CDT 2073 Certificate fingerprints: SHA1: BC:D6:33:CB:95:28:C1:61:D3:EC:D8:10:79:04:C2:22:B8:AF:93:C3 SHA256: 38:0E:40:94:0F:57:1A:B5:9E:AD:A2:7E:B1:AE:ED:42:4C:60:9F:BE:C3:95:51:2A:8B:39:E8:92:90:1C:57:FD Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_18c82db5-7b1c-4bd4-bbe9-7a4e65045fb4_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 874585304266014b022a0a321c5d4451bb433305b9137a1ddbdff36504e39d45 Valid from: Tue Aug 08 06:57:38 CDT 2023 until: Tue Aug 08 06:57:48 CDT 2073 Certificate fingerprints: SHA1: 56:79:CC:8A:CB:CF:74:40:31:D6:C3:1D:D8:DC:9B:03:EA:2A:80:89 SHA256: 86:12:AF:78:E6:63:68:B7:9E:B7:70:A3:CF:EF:35:35:FF:46:15:18:97:97:A8:1A:17:79:85:F5:99:9E:61:0A Signature algorithm name: SHA384withECDSA Subject Public Key Algorithm: 384-bit EC (secp384r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_45aa4647-b976-44b8-a94d-025ecced0fe9_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4c0fc7cf58866f4beee13c4bf8d12bd084b264f6bedfa484b54034a385d563db Valid from: Tue Aug 08 06:57:45 CDT 2023 until: Tue Aug 08 06:57:55 CDT 2073 Certificate fingerprints: SHA1: 91:48:30:F4:F6:E8:5D:AF:09:79:C2:EC:F9:C6:20:B0:85:3C:02:7E SHA256: 9A:D9:B9:3A:74:AF:99:A9:B2:44:40:1F:8D:E2:C5:72:6E:E3:AA:43:52:A0:8A:1E:61:5A:48:29:57:7E:92:60 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_46f71619-57a9-4c3f-bc15-b91872c828cf_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 1187ed8ad9aa4a985c68ba2e0665665a50c970a06e25697360b0c680bda347a3 Valid from: Tue Aug 08 06:57:37 CDT 2023 until: Tue Aug 08 06:57:47 CDT 2073 Certificate fingerprints: SHA1: 9F:F8:EC:FF:83:8A:35:73:B1:AB:89:FF:39:6C:61:C2:76:24:78:37 SHA256: B5:3C:C6:0B:13:D2:C0:E5:3D:E4:7D:66:B4:DA:AA:B1:6E:23:82:07:57:D9:ED:3B:47:28:91:CE:76:EE:62:64 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_51b7ce59-5b1e-4f24-92d0-57edff831f37_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: e2dd7decf9dd456bddfa2b9800ac47a4e38ac420cf416c0255820851a8041daf Valid from: Tue Aug 08 06:57:39 CDT 2023 until: Tue Aug 08 06:57:49 CDT 2073 Certificate fingerprints: SHA1: A0:F0:F1:30:66:6B:35:DB:31:AB:8D:D3:E5:58:F4:31:F9:0B:60:E8 SHA256: 5F:CF:BB:E8:6E:FE:A9:F3:D0:09:8E:A5:2A:C7:A8:3B:42:CF:2C:A9:59:D9:A2:86:9B:B2:E3:A1:81:D9:BF:2F Signature algorithm name: SHA512withECDSA Subject Public Key Algorithm: 521-bit EC (secp521r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_5b5666f0-8c3c-46db-8e10-190263885d01_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 88d0bbd883c815c46882674a9e0cb82d4c27bc18231177a262aab71b28e1878 Valid from: Tue Aug 08 06:57:37 CDT 2023 until: Tue Aug 08 06:57:47 CDT 2073 Certificate fingerprints: SHA1: E7:6A:0E:37:85:BD:F9:E2:FD:B2:4B:96:A9:3A:97:91:EE:30:91:53 SHA256: 41:AB:78:C1:91:19:BA:03:13:B1:D6:62:27:1D:6E:0B:53:FC:91:AF:DF:E0:6A:17:61:E5:28:D7:AF:26:BA:E1 Signature algorithm name: SHA512withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_64a3d3e3-503c-4574-a544-ea63bab7f637_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 58380f109ee41ec443e0e1655e4009f7c782b4e48203464651b92508e37e8cb1 Valid from: Tue Aug 08 06:57:46 CDT 2023 until: Tue Aug 08 06:57:56 CDT 2073 Certificate fingerprints: SHA1: DF:F5:B0:63:1B:B4:A1:81:28:FF:FB:0E:97:78:49:B1:0F:A7:9F:CA SHA256: 4E:72:58:BB:D6:8E:D1:D1:C8:33:32:2F:58:FA:66:8A:26:1E:10:4F:C3:7F:DD:33:6E:39:38:1F:11:A6:EF:7F Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_9b146bc3-5987-414c-9ed6-7ba735b0ab10_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d62267e39615f334538d64353a48539673b6c8331f3dbb5bdae6b6897541a631 Valid from: Tue Aug 08 06:57:36 CDT 2023 until: Tue Aug 08 06:57:46 CDT 2073 Certificate fingerprints: SHA1: 15:16:97:87:F1:EF:56:12:9E:FB:24:A5:8E:EA:CF:B5:14:9F:81:24 SHA256: 61:C4:F6:D9:8A:54:A9:31:D6:4D:09:B0:D9:0B:36:01:4F:97:53:B8:0D:09:83:01:E3:1B:67:F6:66:F9:05:0B Signature algorithm name: SHA384withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b037a3dc-b4a9-46a6-8b45-66df01da4f0a_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 8decb6c87779103a3915f71963b3c6d6208c7530a6935215b3f7ef6a2832effb Valid from: Tue Aug 08 06:57:39 CDT 2023 until: Tue Aug 08 06:57:49 CDT 2073 Certificate fingerprints: SHA1: 74:9C:1C:D1:D0:15:92:A4:35:38:C7:12:FC:89:D8:19:29:B7:77:EE SHA256: AF:39:10:89:1E:0B:08:2F:AF:C1:D4:F9:13:73:1D:72:C9:6B:27:EF:8A:F0:66:D6:89:BA:27:CB:1A:90:16:EA Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b0b8feac-e048-407c-afc8-44008b4e88cb_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9a20c156e837e5f7d974e6ec9c3da25f30170e775f789c4836d3a00d919fe5e5 Valid from: Tue Aug 08 06:57:36 CDT 2023 until: Tue Aug 08 06:57:46 CDT 2073 Certificate fingerprints: SHA1: 3F:8D:06:04:A6:9F:ED:C1:39:FC:86:40:C4:8C:19:6D:C2:E3:A9:5E SHA256: 3A:1D:39:FC:3C:BD:17:A9:19:A8:45:BB:FD:FE:2A:3A:24:BD:CF:A6:0A:07:17:21:BF:D8:75:84:5E:10:50:16 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b68c6303-e35e-44f0-b300-e9347e3e3305_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9bd61db1532aef6c9efa870ccf8cd39caf227037d82c9c0404ba3c95bff46322 Valid from: Tue Aug 08 06:57:40 CDT 2023 until: Tue Aug 08 06:57:50 CDT 2073 Certificate fingerprints: SHA1: 34:29:CF:02:EF:D0:C9:CF:A3:6C:79:A8:B9:36:D8:6F:CB:6F:4D:02 SHA256: 8B:F9:35:9E:86:1E:0A:1C:BC:2E:7C:BB:C9:50:FD:F3:84:51:F6:E8:92:C6:03:2A:0C:EB:74:0C:7D:93:8C:28 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_cef00de1-5a40-444a-94b4-35d7a290efad_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 845d78edfaf1912519bddcffffa6aaae9253dd1a087c781132686472763314e2 Valid from: Tue Aug 08 06:57:44 CDT 2023 until: Tue Aug 08 06:57:54 CDT 2073 Certificate fingerprints: SHA1: A4:EC:F5:F6:80:A1:51:FE:DD:65:AC:7E:2E:78:C9:0B:FB:82:33:DC SHA256: C9:62:C8:12:CB:C6:6B:96:C6:D4:E4:9B:1D:0A:8A:E8:47:0E:C6:EA:70:E2:CE:DE:06:C8:77:4D:84:3E:32:33 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_cef05e47-6622-43e7-b61d-1209f0dcdf99_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ee31a06bda23b8f5a042295d851018c3502a7a8bcd22e2367226c9b5014699a8 Valid from: Tue Aug 08 06:57:38 CDT 2023 until: Tue Aug 08 06:57:48 CDT 2073 Certificate fingerprints: SHA1: 22:EC:A2:90:AA:1C:73:0C:23:B2:AA:F8:B2:CD:35:C2:A4:10:0E:0E SHA256: F2:B4:3B:93:BA:BF:08:E0:58:30:78:03:8F:C0:60:6A:68:E7:68:7D:00:ED:50:B2:9A:8B:21:C3:9F:71:4A:8A Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256k1) key (disabled) Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* All keys are saved in aliases. Every alias has follow format: KeyOpsType + GUID + Use + Algorithm . Where: - KeyOpsType: values Connect | SSA - Use: sig (signature) | enc (encryption) - Algorithm: if Use == sig follow algorithm values are used: RS256 RS384 RS512 ES256 ES256K ES384 ES512 PS256 PS384 PS512 EdDSA if Use == enc follow algorithm values are used: RSA1_5 RSA-OAEP RSA-OAEP-256 ECDH-ES ECDH-ES+A128KW ECDH-ES+A192KW ECDH-ES+A256KW . This Key Store is used for keys/certificates keeping, which are used by the OpenID provider ( jans-auth-server ). smtp-keys.pkcs12 # Here is the example of the file: /etc/certs/smtp-keys.pkcs12 (list of entries/aliases). keytool -list -v -storetype PKCS12 -keystore /etc/certs/smtp-keys.pkcs12 -storepass 6VkIGu0DhnrD Keystore type: PKCS12 Keystore provider: SUN Your keystore contains 1 entry Alias name: smtp_sig_ec256 Creation date: Aug 8, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=SMTP CA Certificate Issuer: CN=SMTP CA Certificate Serial number: 690675c1 Valid from: Tue Aug 08 06:57:12 CDT 2023 until: Fri Aug 05 06:57:12 CDT 2033 Certificate fingerprints: SHA1: 69:77:F6:3E:44:0C:3A:BE:0D:58:02:71:21:72:39:12:54:DB:D7:88 SHA256: E5:E6:CB:BE:76:62:06:2F:A0:C9:49:0F:DD:0D:B1:D1:5B:D6:A2:2C:11:E1:0B:FE:84:67:B0:9D:EB:9B:3A:ED Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: 94 D2 A8 BC 8C D7 6F E0 EC BF 2D 92 3A 8D E1 CE ......o...-.:... 0010: 3D 71 CB B0 =q.. ] ] ******************************************* ******************************************* This Key Store stores one alias ( smtp_sig_ec256 ) and it is used for keeping of key/certificate, which is used by email sending functionality - signing of emails. Alias smtp_sig_ec256 contains self-signed certificate. User/Admin can update this KeyStore, adding key/certificate signed by trusted certificate authority (CA) (X-509 PKI). BCFKS KeyStore # Janssen also supports BCFKS format of KeyStore. As a rule this format is used on RHEL/DISA-STIG OS. Access to this type of KeyStore is provided by BCFIPS crypto provider. Modules of cryptoprovider can be found (after installing on RHEL/DISA-STIG OS) here: /var/gluu/dist/app/bc-fips-1.0.2.3.jar /var/gluu/dist/app/bcpkix-fips-1.0.6.jar . Here is example of the BCFKS KeyStore /etc/certs/jans-auth-keys.bcfks (list of entries/aliases): keytool -list -v -keystore /etc/certs/jans-auth-keys.bcfks -storetype BCFKS -providerpath /var/gluu/dist/app/bc-fips-1.0.2.3.jar:/var/gluu/dist/app/bcpkix-fips-1.0.6.jar -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -storepass CqE4ApXQxz5y Keystore type: BCFKS Keystore provider: BCFIPS Your keystore contains 30 entries Alias name: connect_01906c9d-fed6-48f1-94b8-85446a692f23_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 3b795840da219a3a7736d0ac0ebc2d632e925dc4b472a02e4b930eb1d5ca278b Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 40:B5:54:85:6B:3B:B1:A9:93:22:6D:91:AA:37:AD:92:A9:B0:5A:A9 SHA256: 06:23:28:01:89:6A:96:EA:A6:3E:EA:27:1D:7C:7A:8A:C7:C9:6D:3F:D0:BF:00:69:35:27:CA:CB:54:75:C6:F1 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_03a3687a-9c3c-4026-abfc-cafef6a76f92_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: df266f1918ae93954aaad44cdceab2ac89be1c20ad16245f1567d751db5d6d1a Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 12:12:0B:15:47:A4:C9:AB:44:4A:00:5E:B3:3A:8E:EE:56:70:6F:A7 SHA256: 11:F8:12:47:17:E6:D1:D4:80:1F:66:72:22:2C:49:93:72:DE:EF:5E:58:40:74:5B:AE:66:C4:96:F5:9C:86:13 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_1b960e55-7b8c-4eeb-9379-b933b8a28fb6_enc_ecdh-es+a128kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ad0cb98a5844cfe6a56c944d269aa3ce6379dc8fea2b0752514753935ae3d821 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 28:8F:83:99:24:8E:97:54:5A:B7:41:BB:28:C5:5E:BE:67:38:AF:F4 SHA256: E5:DE:D0:4A:17:5B:F8:5D:32:E4:8B:E2:E6:24:D6:22:50:D6:2E:E1:D4:ED:AB:9A:AB:74:B8:24:8C:16:97:14 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_4260d824-790d-440e-b2e0-a1a4ab813169_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 28f4866a894a33bb70dcb33138631be67a3b3b2c2b02c31a24913fde2d6d905d Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: CD:2C:FC:D2:81:A7:26:EA:C1:63:66:C4:AF:43:20:F3:E0:10:B7:41 SHA256: F5:3F:81:C5:B4:CD:8B:7D:B1:E4:83:54:DE:B9:88:F5:1B:3E:DA:CD:A5:93:86:D5:21:E5:3B:3D:42:5C:56:E3 Signature algorithm name: SHA512WITHECDSA Subject Public Key Algorithm: 521-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_464cc164-24ec-43c2-9f13-bca1c7faab11_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d4786313f02f3444beabbac0ed6c307db4af29e3f044edd047e976efe48c2337 Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 8A:37:4D:12:F9:24:93:DF:1B:59:90:26:3B:1A:95:5A:F8:46:1E:CB SHA256: B4:28:C6:BC:3D:AA:7C:52:5C:E4:22:FC:E7:E0:94:BF:22:66:91:0F:D6:CF:37:6E:C5:54:ED:0C:30:A8:24:CF Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_53cfa5f1-c227-4843-94d0-e5369cd822b0_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 321e23c27b9ec8a65e7e8fe0e64f68aa7390d713bebfa78b17f8962bb28c1d4f Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 6F:D2:4A:FC:48:1F:F3:B7:CC:13:4B:41:3A:BC:19:C4:85:A9:E9:7C SHA256: 43:80:83:D8:84:75:87:5A:24:D6:6B:AC:EC:0D:45:2E:8F:4A:FC:B4:47:D4:D7:49:E8:06:12:2F:98:7C:91:8F Signature algorithm name: SHA384WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_63e8e482-18ef-410e-bf27-0543a37ac166_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 5fe30fe9ce2b55b6738ec74e0b711c5aa3052ae200fdb9c39bb1392420087d7c Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 1C:27:A5:78:64:EA:01:13:C8:62:D4:4C:93:7A:95:F5:CC:C0:55:BA SHA256: F6:CB:47:52:9D:10:B6:31:FB:C2:1F:CC:30:DD:91:DD:2D:85:C0:44:BB:AB:CA:05:9D:47:05:00:7E:35:73:8B Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_64e35c92-c4f2-4104-81ef-7a366f2dbc38_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6742d9b42e180b7f4a1f58121dddb02896ff1638e8254bd74415a90e47718e91 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 75:AB:EA:2C:D7:C8:87:86:7C:FE:0D:23:33:24:CE:FD:75:3E:E5:E0 SHA256: EA:7D:7F:F1:51:00:5F:D8:80:A5:AF:67:F4:E1:84:A2:E5:D0:0A:8F:A3:98:81:29:36:9B:14:DA:59:02:76:AA Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_71a098e5-0fe0-4946-85f8-adf0d6759413_enc_ecdh-es+a256kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 285d3bcd2569a9a0db6091c184e47bf855edf758251749b739267b7f6f9821d3 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: D6:D7:0C:33:6E:A8:A4:54:2A:1F:2D:59:7D:2C:26:0A:EB:B8:AE:41 SHA256: EC:82:5E:A3:66:99:FB:3E:64:B7:47:27:AA:0D:13:C6:64:E1:42:41:B4:8E:F7:B9:23:20:AA:15:1E:F3:22:F7 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_82a7b334-4756-4201-a432-1b181badf695_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: cce1b501329cff10503a96587042b4f37cc994ac3f98c615bab4c9680a53d769 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 37:1C:A3:F4:A3:04:E4:DC:AA:F3:21:AD:BD:B0:5F:D8:0A:95:7B:29 SHA256: D7:CA:AE:57:A3:43:1E:94:93:ED:C8:34:72:29:DD:CE:02:BD:E5:69:6D:34:D3:7D:26:AE:78:19:4C:E9:BF:CE Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_a3d528cf-fd43-4015-92be-1e644310bbf0_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: de13b1e646dd2456c3512de303b2fb272108bcdb40c180717077820c07e32f65 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: EF:5E:62:AA:89:31:70:83:35:40:CB:9E:30:23:32:21:12:77:DC:83 SHA256: 88:1A:A2:85:DB:27:46:04:EE:E5:DC:8A:5E:A7:77:CC:36:C5:A6:1A:E7:A1:85:44:2E:E4:A0:91:8A:FD:A4:6F Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_ab2f67de-14fb-4312-89fa-56b2cd70f616_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d36755d2a472837ab9fe1dad688b5a1881bff6073d5a494af0275226f236146c Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 8B:FD:A9:75:7C:33:1E:9D:03:47:58:2E:31:D6:49:30:E6:65:6B:A7 SHA256: 5C:E2:28:7B:B0:66:17:A8:14:82:49:14:16:E8:40:B3:B6:C1:5F:90:77:25:A3:C4:A5:25:E6:77:CB:B9:92:91 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_ae7adf42-8f9b-4fe0-bbf1-e9e1016904f5_enc_rsa-oaep-256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 324a9b70a8410e9a02eb596e536cda516f91b250befb22699a909d0b2505e03 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 66:CF:B6:EB:27:10:CC:45:E4:CF:8A:66:71:05:97:22:BA:47:6B:33 SHA256: EF:16:46:1F:C5:0B:41:0B:B4:06:A7:9D:7F:EB:81:76:5F:35:B3:E4:09:67:95:D2:2A:10:D3:2F:59:DA:5D:73 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_b52de13d-33fe-446f-b4fa-6b4ce816c18e_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4d4b22cacdd15cd7bbf339c18ef14fba4ba7b0f13ad37f9452e00404488a880c Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 47:03:76:16:4B:D9:5C:83:AC:C7:40:10:F3:46:72:86:15:21:6C:CD SHA256: A3:3A:22:75:E2:E5:5B:69:31:FB:E8:59:E0:90:20:60:BC:47:30:9C:5C:5A:B6:97:92:37:71:CD:91:BF:93:78 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_c82cc876-6e92-408c-b519-76d153aad42d_enc_ecdh-es+a192kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 586b7dd9cecd3ef8c58b1bac766caec5d4c2ac8097c1cc4a22a20905ce5f9229 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: E6:3E:62:82:3C:6F:FE:CF:85:FD:6D:82:A9:7D:68:03:38:F0:AB:63 SHA256: 0D:D0:1B:50:02:0B:41:C1:35:CD:A9:7A:E5:10:AA:88:F2:AD:F7:8E:88:C2:3F:68:A9:33:E6:1B:EB:28:71:30 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_d1001a39-29a1-45e4-ae0d-2eee86a83ada_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ba44ac71c5a340aec0d8e0078b059c36a2819915774e8403e1b589a330570833 Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 49:59:6A:9D:D6:E6:98:05:18:BD:25:1A:C5:C0:2B:A6:C3:3E:36:52 SHA256: DA:57:65:45:A2:16:76:E0:B7:20:DA:82:BF:77:AF:B9:58:D5:E7:D3:2F:1B:D3:BC:48:51:E2:D1:C2:41:A9:FA Signature algorithm name: SHA512WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_f32a5790-4e43-4629-95bd-37b35d7c2e39_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9f0340f5c5cafc1816d2a31c20846fb24d400b3b5194a629ac5baf6db6d15e60 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 5A:37:CA:6A:27:AB:9F:FC:6B:C3:D3:C6:B4:47:F3:10:F4:C9:F3:B3 SHA256: 11:A4:9C:ED:C0:05:B9:27:89:2B:17:52:11:AA:34:B4:E7:81:08:13:44:7D:93:3A:DE:CA:23:A4:22:F7:05:9F Signature algorithm name: SHA384WITHECDSA Subject Public Key Algorithm: 384-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_0639ba94-902c-4ab6-923a-58137554f667_enc_ecdh-es Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6fac3869f3fc7297470eee65fc4315328edaf475798d5bbc469de652f3088ca3 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: 76:B5:F0:B9:1C:88:54:95:5B:11:2A:6A:AE:2E:C3:02:59:1B:07:2C SHA256: 7B:26:2E:36:4B:27:AA:C0:5B:FE:2C:2E:73:B1:75:64:2D:3E:0B:D2:C4:8D:F6:63:12:E8:2E:4C:46:EB:35:4C Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_0d94f183-878c-445d-9917-28357b15c4ee_sig_rs256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6d76a82ed166e13ecc2fb0742ebc72f619af0b738baf69438d2aba4262cfdbc4 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 14:8E:19:D8:8D:FD:68:14:40:72:35:1F:93:2A:7D:83:81:7E:6C:D8 SHA256: CB:69:E0:7C:55:2C:39:56:F8:17:ED:72:96:47:DB:8C:90:1A:1E:2A:E8:33:CA:79:96:DD:44:9F:F7:63:A2:D4 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_1a5ea0d5-0c70-43d2-ab23-e324620b413b_sig_ps512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 42bd6fbc27749cd6598c54aa0928e93057dc6c6c083c9f73d4e2046c4bac02d0 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: D3:D1:31:59:33:D1:A6:86:8F:A5:F8:7F:D6:15:44:53:15:99:6D:DC SHA256: 88:95:8C:89:F3:E7:28:E8:3D:9F:47:39:E2:F8:F5:FC:FA:63:71:B3:81:F0:9C:98:7E:A4:0A:FD:7E:7E:E9:AD Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_20d8cce9-0994-4fca-9cfa-f5fbe22eb940_sig_es256k Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a192c3ca749b78a153cb3134c50fddcdd5dd401dd399b831199ba383eddf355b Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 4E:94:55:21:15:53:1E:3E:3B:6E:85:B9:BF:A7:4B:46:2A:FB:09:4F SHA256: BA:AB:58:DF:29:7C:5A:D5:31:2F:B9:8B:CE:E9:3F:0B:5B:E5:01:94:CC:A8:9B:41:8B:45:9B:30:D2:63:D6:24 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_33b1591d-1b79-490f-a980-573486ec620b_sig_es384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ba8a0e96843f1a5181a96d2fc1bdae8b6954bb70b2b5c1fad4895438f4079dd0 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: B8:97:F4:EA:85:14:41:24:8C:DC:E0:8F:66:18:FD:31:7E:0B:5D:D5 SHA256: F3:9E:1F:25:E2:03:3C:7B:69:15:12:01:E2:94:EF:1E:95:43:43:A2:CB:8E:88:88:8A:3D:53:5E:82:E9:0E:9C Signature algorithm name: SHA384WITHECDSA Subject Public Key Algorithm: 384-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_34943497-d9fb-43ca-8ee1-1437e1dcf78e_sig_ps384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: b45de18f13366f309b100be313770edc6e80942771b08d656e699f7e081e5a69 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: C4:2D:DB:4D:06:7F:27:89:9A:C0:84:DB:08:BF:0C:75:3B:5B:74:22 SHA256: 77:07:D2:90:7C:AD:7A:F1:D8:EE:C1:84:54:B6:E5:41:7B:BB:C7:8F:64:96:D4:D3:ED:FD:32:F3:6C:10:11:62 Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_475830af-d019-4e04-9fb9-e68f0491284a_sig_es512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 69e6093118ce51ec5f21477e2946dd023f3c5b70bbde2922b26139b653eddd62 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 30:9D:95:9C:AE:60:F9:3F:D8:7A:AD:89:9D:AC:5D:7F:05:52:F9:50 SHA256: CA:90:7B:75:3C:99:CE:F2:42:DE:55:38:83:CB:C2:EA:F8:E7:0D:2B:00:5F:57:CF:75:D5:33:C4:5E:32:7E:A7 Signature algorithm name: SHA512WITHECDSA Subject Public Key Algorithm: 521-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_59bb3fe7-bf2a-4244-85a7-dd18785bcac6_enc_rsa-oaep Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 7f3e4adf1e08994ba83a1a59584c6f402e584baaecf1735ff9e0add33d65a423 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: FC:D7:45:92:F4:60:73:C6:7C:19:DA:AB:EC:54:FF:B4:62:C6:AC:CB SHA256: 66:05:C9:4C:3D:CA:EC:9F:29:06:57:00:A8:90:09:24:17:41:71:DC:1F:8E:7F:E7:5B:39:D8:A1:8B:A3:5A:F2 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_5e0f07d5-1e91-4bd3-bf56-6caa8a137ea6_enc_rsa1_5 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 3449c41d6f7c1b5b7f33c7411a81f41883f6f1fccb64d4e2bc22c130d771a26a Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: 1F:55:2E:62:3D:7E:FE:92:20:13:0D:FC:33:F8:82:B1:B7:BF:9E:7A SHA256: C9:6E:48:AF:F7:8B:04:30:FB:4B:30:47:A2:83:1E:4C:AF:9E:04:E6:07:8A:B1:AE:3B:CD:92:AE:CB:97:D2:EB Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_7d9cec29-697e-4e3e-9991-eba03394b69c_sig_ps256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 15e7eed8194a80919e9bd699212efca7e50ec9aa3834c6a8e32a7eeb9d9e1da9 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: A5:BE:24:97:EB:F5:0F:18:05:56:02:BF:66:24:98:24:59:82:5A:E6 SHA256: 16:EF:DD:45:17:3B:D7:66:36:14:7E:96:03:1F:51:02:6C:86:1E:19:E7:43:C7:DF:E9:A9:D0:86:9C:A6:7C:B8 Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_96ea824f-f915-4da8-8f76-3b4bf8bdf552_sig_rs384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4c79afa5d03e2aaab17c90519d59dec517de004f4c9b62960ebf10276b699105 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: E8:F3:5D:16:D0:2C:47:98:D4:F6:98:A1:5F:46:A0:DB:BD:F8:72:30 SHA256: 15:42:A4:30:FE:DB:D8:C4:61:11:A6:8D:10:51:02:64:70:C7:EA:BF:F3:C8:F3:42:03:D9:F8:00:19:F9:7C:28 Signature algorithm name: SHA384WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_b7ee7e46-0a6b-4040-b6b3-a78e9dedc116_sig_rs512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 82f95026558b89f3ca8c1129d3b79c74ce2ff70bb849991a8305afea974ebe1c Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: D8:45:78:27:94:39:93:57:DF:67:56:3B:06:5C:0C:2A:20:93:F6:0F SHA256: 6D:55:8E:F3:5F:6A:EA:6D:37:71:A9:57:1D:32:98:92:04:5E:8B:4A:C4:FC:E1:ED:B1:7A:D4:11:BF:38:02:80 Signature algorithm name: SHA512WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_b9d65217-ff51-4eab-914f-aeb40eb30bc2_sig_es256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 632a5f6e2bf5c5dbabf7376718c35b3101fe8a8065a6bf54db3dde5a1825dbf4 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 7D:51:C1:44:45:EF:6B:71:3D:EF:BC:20:E0:AE:59:4C:3D:16:10:23 SHA256: CC:1C:60:5E:E4:6A:B4:C4:7F:3F:2D:1B:2F:12:B4:79:27:94:3D:1D:D5:FA:C4:11:0E:53:76:DA:52:34:B0:62 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* .", "title": "Key Storage"}, {"location": "janssen-server/auth-server/crypto/key-storage/#overview", "text": "A Java KeyStore is a file that contains set of aliases. Every alias can contain private key and public key and certificate (additional property info about owner of they key) or only public key and certificate. KeyStore stores the following type of data: - Private Keys; - Public Keys and Certificates; - Secret Keys. KeyStore are used by follow crypto primitives: - asymetric encryption; - digital signature; - symmetric-key algorithm.", "title": "Overview"}, {"location": "janssen-server/auth-server/crypto/key-storage/#janssen-key-storages", "text": "", "title": "Janssen Key Storages"}, {"location": "janssen-server/auth-server/crypto/key-storage/#janssen-key-storages_1", "text": "Janssen KeyStore files contain: - Private Keys; - Public Keys and Certificates.", "title": "Janssen Key Storages"}, {"location": "janssen-server/auth-server/crypto/key-storage/#supported-formats-of-key-storages", "text": "There is some set of standardized KeyStore formats. Janssen applications use follow KeyStore formats: - JKS : Java KeyStore format (proprietary keystore implementation provided by the SUN provider). KeyStore file extensions: .jks , .keystore , .ks ; - PKCS#12 : Personal Information Exchange Syntax, developed by RSA Security. PKCS #12 defines an archive file format for storing many cryptography objects as a single file. KeyStore file extensions: .pkcs12 , .p12 , .pfx ; - BCFKS : Bouncy Castle FIPS Key Store (BCFKS) format supports storage of certificates and private keys using AES-CCM and PBKDF2 algorithms, providing greater security than the standard JKS and PKCS12 implementations. Support for BCFKS format is implemented, using BCFIPS Crypto Provider (https://www.bouncycastle.org/fips_java_roadmap.html). KeyStore file extensions: .bcfks , bcf , bcfips .", "title": "Supported Formats of Key Storages"}, {"location": "janssen-server/auth-server/crypto/key-storage/#installed-keystore-files", "text": "Janssen installs KeyStore files in the directory: /etc/certs . Follow Keystore files are used by Janssen: jans-auth-keys.pkcs12 smtp-keys.pkcs12 .", "title": "Installed KeyStore files"}, {"location": "janssen-server/auth-server/crypto/key-storage/#jans-auth-keyspkcs12", "text": "Here is the example of the file: /etc/certs/jans-auth-keys.pkcs12 (list of entries/aliases). keytool -list -v -storetype PKCS12 -keystore /etc/certs/jans-auth-keys.pkcs12 -storepass gNzpzYj5h8i1 Keystore type: PKCS12 Keystore provider: SUN Your keystore contains 31 entries Alias name: connect_3c83ba3a-7a62-49e7-8478-b6d3e242e549_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a81e8386d6774110b12a292a7185c454359b9b6d67a3f5aef587e9395db04166 Valid from: Thu Aug 17 05:21:05 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 4F:FD:3A:E6:61:D8:8E:0F:61:A4:AA:DE:D7:E4:F4:28:5E:EE:39:20 SHA256: 52:15:67:CE:0B:56:1C:CD:CE:C9:39:4C:11:25:B8:73:13:7F:7F:91:BB:E4:1A:3F:48:8D:B0:DC:01:D0:55:3D Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_45c2ce16-6d5b-47d4-be40-c4da48ba49d3_enc_ecdh-es+a128kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: c6fdff1d75c83e32519a94133f9954de22a2aea4fb20ef669bce2221c08cf21f Valid from: Thu Aug 17 05:21:17 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 02:35:E7:FC:50:47:4A:3A:EA:54:EE:92:CA:75:14:D0:A4:E0:0C:45 SHA256: 19:18:8F:68:68:A2:FE:E2:03:BC:E6:2E:87:24:D4:E9:B0:64:D8:44:7D:32:A1:DE:1C:1B:8E:9A:96:3F:32:5A Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_5365f93a-368d-4643-8708-1f4b31b62d47_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4d561c04da6bbe50ea15720e6c6898d35793e711eabc9eaa02ad7ed9dafa148b Valid from: Thu Aug 17 05:21:14 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: C7:B4:1A:9A:15:59:E6:45:AC:77:C7:1C:E4:7D:F2:01:EC:4B:59:AD SHA256: 75:11:06:F5:74:D7:B4:C4:0A:57:A5:88:AA:91:F9:57:4C:78:BE:D2:68:1F:0E:AF:0B:CA:16:2F:0F:FE:17:EA Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_5b5da374-2ccb-40ca-8544-9338fe7427ff_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 235fc012863b7291c3370978761a2df6a14796cc601b0fec801b84aa7281b116 Valid from: Thu Aug 17 05:21:03 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 17:33:24:FC:C8:F7:0C:10:7B:0A:30:5B:28:6E:30:AC:13:A5:FD:36 SHA256: E5:05:5A:7E:00:93:2E:8B:3E:AE:91:D5:B5:B5:1A:A9:51:37:FE:72:29:02:83:20:F7:6F:BC:BE:D9:FF:23:7E Signature algorithm name: SHA384withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_6218efa5-197e-49f5-919f-769e6d0aaaec_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 304513446352446c48e39017e3044545e0e2a4a71c36899eacfac775606e958d Valid from: Thu Aug 17 05:21:08 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: BE:27:21:18:F4:D4:F6:71:D9:4A:DF:A0:3F:F2:20:76:E1:3E:DD:05 SHA256: 39:FB:09:EC:BD:62:CF:B2:8B:6A:7F:D9:AF:34:64:7C:50:53:E9:E1:14:01:FE:35:B3:B6:03:8D:C6:E3:A3:68 Signature algorithm name: SHA512withECDSA Subject Public Key Algorithm: 521-bit EC (secp521r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_6dbf485d-9d78-49d0-b977-72608ca6b727_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6310f2b2c5fe5e9354d6352140bedf9efe986ed1c44e68d6dda2ccb46038a14c Valid from: Thu Aug 17 05:21:04 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: E1:78:BA:84:C1:9A:9F:6D:FF:32:1B:F4:D9:4E:AE:AE:23:A9:7F:52 SHA256: EF:C9:B8:40:82:E1:16:B2:7B:2C:E9:E4:47:17:5D:C2:AB:D7:AA:16:EE:11:95:19:F7:52:7C:20:E9:3C:82:91 Signature algorithm name: SHA512withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_7325add6-aaa6-4e4c-bfee-968fa7eba793_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ea8c7dfe1d28f4ff9f686f0eccd5b3d06c50d80b4751713cce0052997027c90f Valid from: Thu Aug 17 05:21:10 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 2D:71:05:C2:5C:5A:50:CD:C7:64:42:69:03:8B:BC:66:6F:F7:E3:2A SHA256: C8:DD:E9:2E:49:91:04:25:29:48:6F:CA:01:0B:6F:17:CA:29:01:C5:4D:2B:AF:3F:A3:25:03:16:12:34:5C:48 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_829abf33-03f1-4f35-a42e-bca49f992df4_enc_ecdh-es+a256kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 24c62ce19733ddce99573c073bfa890e29d48fbc4a1b4365748fdc0c420b793a Valid from: Thu Aug 17 05:21:18 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 66:FC:23:8E:08:80:2A:C8:74:08:A5:37:C2:6D:8F:68:AB:23:7E:D3 SHA256: 27:7B:A3:5D:E2:F3:6D:15:52:F8:D0:03:0A:7D:D5:B5:32:B9:4E:93:F1:C3:14:98:CA:98:E9:53:84:45:24:4C Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_87933d28-0523-4bd2-a078-a94e32887b04_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 276ab34dca0e41236756ae0863ebd5e16ea0b209645128f54da0c0dc1c12b64c Valid from: Thu Aug 17 05:21:06 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 53:23:C9:45:4D:D2:29:70:BA:EB:27:EB:83:66:AB:4C:B9:56:9E:83 SHA256: 42:38:33:97:94:ED:58:51:D4:F1:C8:E5:2E:AB:56:05:B0:1D:79:05:33:51:DA:0F:41:E9:E8:59:11:B8:0F:57 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256k1) key (disabled) Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_8d71b86c-5b81-444c-afdf-bb3da4de11e4_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d8344594dfcce15695d56f30178bc2a38bf3d432756bfd15a69242b3348876dd Valid from: Thu Aug 17 05:21:02 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 5D:75:82:47:5F:80:F9:2F:41:48:CF:01:9F:EE:66:0E:71:37:FA:83 SHA256: D1:92:1C:B1:D0:29:B8:23:73:FA:2E:89:11:2D:F1:8F:5E:2E:FE:B0:80:D1:CC:60:1B:B3:46:82:BA:04:9E:4B Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_9574dff8-1f98-421d-91bf-a760a18be2d2_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a92efd444e5ea4ac9cd573aa66746b3b90adf465d20ad1abb25d903619f30d6c Valid from: Thu Aug 17 05:21:11 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 29:CF:94:A6:DF:1E:85:59:A4:C1:62:1F:95:AB:67:31:1B:2D:07:6C SHA256: E5:72:DE:3F:C5:96:63:21:AB:82:B4:64:00:E6:19:9B:2C:B0:6D:7C:C6:8C:3D:5B:21:58:6A:3D:D1:CC:54:0D Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_9f70c848-95b6-48fe-a9e9-79b374848e28_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 46d231ec4e06d52ce1d5a4950f2f91ffc5dd107f5ac7a422225d55fb0004ae26 Valid from: Thu Aug 17 05:21:13 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: A5:82:D0:70:8D:19:A5:5D:DE:4D:CC:52:AE:FB:F4:FF:EF:1A:56:AE SHA256: BB:FA:F0:82:DC:71:84:90:74:C1:33:D9:BC:AE:35:EA:DD:6B:35:95:CE:45:DB:94:E9:9B:E9:39:A4:47:CD:B2 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_a28e886e-090b-42c3-b437-92c91106c0c1_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4f03840af117cdff5a44ae7f12050ead8934d460134a35088ba5cb3782046b9e Valid from: Thu Aug 17 05:21:16 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 24:00:50:A1:B6:FD:F3:EC:19:95:CE:0F:BA:4E:AE:C5:64:57:F7:0C SHA256: BC:02:64:A2:1E:B6:B3:BD:BE:15:8E:E6:8B:CA:1E:00:A0:13:D9:40:72:7E:93:0F:40:DB:58:B5:56:1B:08:54 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_b7920896-d087-4668-9ee5-66fd3cf56694_enc_rsa-oaep-256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 16d9f709786c58f4343b2fce290cafa4130cb706cae25bcc98970742879d6f1d Valid from: Thu Aug 17 05:21:15 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 28:B3:2B:59:0B:BF:DB:F1:05:63:27:C3:9B:CD:35:14:54:A9:A3:16 SHA256: D9:55:37:5E:2E:AE:48:3E:72:DF:39:E2:0B:D8:79:4F:A3:21:33:EF:DA:DF:24:22:8B:42:08:61:E5:7F:F8:9F Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_c50ce977-00c0-4f4a-8594-1a0bc3935f88_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: c1992dccc3c0635dea6f34ac0f03414cc5f2422883dde72e8c07ea3fba66e865 Valid from: Thu Aug 17 05:21:09 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 65:CC:C8:CF:EA:54:C8:2C:27:31:59:34:5E:69:41:CE:09:37:EB:6B SHA256: C0:C8:68:75:BE:C1:CC:9F:4B:19:5E:23:9B:F4:3B:E8:E3:CE:B7:84:35:29:C0:8C:12:63:1E:B4:81:6B:23:99 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_e99b9f12-cbf5-4d5e-9156-12f112d7b4a3_sig_eddsa Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 523b5a9b1edbb4ac08435f1f86c7d810be34535e0bc02b073baeab6d9f35ca75 Valid from: Thu Aug 17 05:21:12 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: EB:D3:5F:54:76:44:D1:01:5F:39:EA:0B:2A:08:FB:30:39:50:E8:CC SHA256: 5F:99:18:AE:47:58:FD:7E:E3:B7:B4:F8:57:4A:5B:68:94:F8:DD:2A:02:DE:F7:58:8B:6A:06:D6:E2:CE:3E:ED Signature algorithm name: 1.3.101.112 Subject Public Key Algorithm: 1.3.101.112 key of unknown size Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_eb5d1996-197c-4913-9b10-201b4f371ff7_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 613554766f456cae0e968ecf8eaedd5fbb0f04c6ff64202c6b51df34cd7b2a20 Valid from: Thu Aug 17 05:21:07 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 50:FF:D2:51:CA:F6:35:31:C8:12:14:13:36:0B:A5:05:F4:08:3F:97 SHA256: 13:13:32:47:2B:5B:E7:20:EC:4B:77:E8:80:78:E0:84:DB:D9:5E:6D:6C:C6:86:5F:B5:6D:18:99:38:02:B0:32 Signature algorithm name: SHA384withECDSA Subject Public Key Algorithm: 384-bit EC (secp384r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: connect_eddc097c-d9bc-4672-a6ec-2740f8ed99c4_enc_ecdh-es+a192kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9755e3a9d7404f86161bdfd47dc0f57021aa598b6f4bde9b3929a1303d66baef Valid from: Thu Aug 17 05:21:18 CDT 2023 until: Sat Aug 19 06:21:10 CDT 2023 Certificate fingerprints: SHA1: 20:1F:EE:29:8F:57:B4:FA:29:E8:3F:D6:DD:60:0C:E7:6C:A6:82:54 SHA256: 6A:69:0F:0F:D0:51:5F:83:29:91:BB:E5:A7:63:48:14:F7:D1:C4:18:EE:4D:F2:28:50:63:18:2D:00:94:C7:F4 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_02674321-5bdc-451e-a8e0-12fbc494ab00_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: b544920f9433a67816ac7e022649057deeecd012b68344683ca92a680496b3dc Valid from: Tue Aug 08 06:57:41 CDT 2023 until: Tue Aug 08 06:57:51 CDT 2073 Certificate fingerprints: SHA1: BC:D6:33:CB:95:28:C1:61:D3:EC:D8:10:79:04:C2:22:B8:AF:93:C3 SHA256: 38:0E:40:94:0F:57:1A:B5:9E:AD:A2:7E:B1:AE:ED:42:4C:60:9F:BE:C3:95:51:2A:8B:39:E8:92:90:1C:57:FD Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_18c82db5-7b1c-4bd4-bbe9-7a4e65045fb4_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 874585304266014b022a0a321c5d4451bb433305b9137a1ddbdff36504e39d45 Valid from: Tue Aug 08 06:57:38 CDT 2023 until: Tue Aug 08 06:57:48 CDT 2073 Certificate fingerprints: SHA1: 56:79:CC:8A:CB:CF:74:40:31:D6:C3:1D:D8:DC:9B:03:EA:2A:80:89 SHA256: 86:12:AF:78:E6:63:68:B7:9E:B7:70:A3:CF:EF:35:35:FF:46:15:18:97:97:A8:1A:17:79:85:F5:99:9E:61:0A Signature algorithm name: SHA384withECDSA Subject Public Key Algorithm: 384-bit EC (secp384r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_45aa4647-b976-44b8-a94d-025ecced0fe9_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4c0fc7cf58866f4beee13c4bf8d12bd084b264f6bedfa484b54034a385d563db Valid from: Tue Aug 08 06:57:45 CDT 2023 until: Tue Aug 08 06:57:55 CDT 2073 Certificate fingerprints: SHA1: 91:48:30:F4:F6:E8:5D:AF:09:79:C2:EC:F9:C6:20:B0:85:3C:02:7E SHA256: 9A:D9:B9:3A:74:AF:99:A9:B2:44:40:1F:8D:E2:C5:72:6E:E3:AA:43:52:A0:8A:1E:61:5A:48:29:57:7E:92:60 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_46f71619-57a9-4c3f-bc15-b91872c828cf_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 1187ed8ad9aa4a985c68ba2e0665665a50c970a06e25697360b0c680bda347a3 Valid from: Tue Aug 08 06:57:37 CDT 2023 until: Tue Aug 08 06:57:47 CDT 2073 Certificate fingerprints: SHA1: 9F:F8:EC:FF:83:8A:35:73:B1:AB:89:FF:39:6C:61:C2:76:24:78:37 SHA256: B5:3C:C6:0B:13:D2:C0:E5:3D:E4:7D:66:B4:DA:AA:B1:6E:23:82:07:57:D9:ED:3B:47:28:91:CE:76:EE:62:64 Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_51b7ce59-5b1e-4f24-92d0-57edff831f37_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: e2dd7decf9dd456bddfa2b9800ac47a4e38ac420cf416c0255820851a8041daf Valid from: Tue Aug 08 06:57:39 CDT 2023 until: Tue Aug 08 06:57:49 CDT 2073 Certificate fingerprints: SHA1: A0:F0:F1:30:66:6B:35:DB:31:AB:8D:D3:E5:58:F4:31:F9:0B:60:E8 SHA256: 5F:CF:BB:E8:6E:FE:A9:F3:D0:09:8E:A5:2A:C7:A8:3B:42:CF:2C:A9:59:D9:A2:86:9B:B2:E3:A1:81:D9:BF:2F Signature algorithm name: SHA512withECDSA Subject Public Key Algorithm: 521-bit EC (secp521r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_5b5666f0-8c3c-46db-8e10-190263885d01_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 88d0bbd883c815c46882674a9e0cb82d4c27bc18231177a262aab71b28e1878 Valid from: Tue Aug 08 06:57:37 CDT 2023 until: Tue Aug 08 06:57:47 CDT 2073 Certificate fingerprints: SHA1: E7:6A:0E:37:85:BD:F9:E2:FD:B2:4B:96:A9:3A:97:91:EE:30:91:53 SHA256: 41:AB:78:C1:91:19:BA:03:13:B1:D6:62:27:1D:6E:0B:53:FC:91:AF:DF:E0:6A:17:61:E5:28:D7:AF:26:BA:E1 Signature algorithm name: SHA512withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_64a3d3e3-503c-4574-a544-ea63bab7f637_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 58380f109ee41ec443e0e1655e4009f7c782b4e48203464651b92508e37e8cb1 Valid from: Tue Aug 08 06:57:46 CDT 2023 until: Tue Aug 08 06:57:56 CDT 2073 Certificate fingerprints: SHA1: DF:F5:B0:63:1B:B4:A1:81:28:FF:FB:0E:97:78:49:B1:0F:A7:9F:CA SHA256: 4E:72:58:BB:D6:8E:D1:D1:C8:33:32:2F:58:FA:66:8A:26:1E:10:4F:C3:7F:DD:33:6E:39:38:1F:11:A6:EF:7F Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_9b146bc3-5987-414c-9ed6-7ba735b0ab10_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d62267e39615f334538d64353a48539673b6c8331f3dbb5bdae6b6897541a631 Valid from: Tue Aug 08 06:57:36 CDT 2023 until: Tue Aug 08 06:57:46 CDT 2073 Certificate fingerprints: SHA1: 15:16:97:87:F1:EF:56:12:9E:FB:24:A5:8E:EA:CF:B5:14:9F:81:24 SHA256: 61:C4:F6:D9:8A:54:A9:31:D6:4D:09:B0:D9:0B:36:01:4F:97:53:B8:0D:09:83:01:E3:1B:67:F6:66:F9:05:0B Signature algorithm name: SHA384withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b037a3dc-b4a9-46a6-8b45-66df01da4f0a_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 8decb6c87779103a3915f71963b3c6d6208c7530a6935215b3f7ef6a2832effb Valid from: Tue Aug 08 06:57:39 CDT 2023 until: Tue Aug 08 06:57:49 CDT 2073 Certificate fingerprints: SHA1: 74:9C:1C:D1:D0:15:92:A4:35:38:C7:12:FC:89:D8:19:29:B7:77:EE SHA256: AF:39:10:89:1E:0B:08:2F:AF:C1:D4:F9:13:73:1D:72:C9:6B:27:EF:8A:F0:66:D6:89:BA:27:CB:1A:90:16:EA Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b0b8feac-e048-407c-afc8-44008b4e88cb_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9a20c156e837e5f7d974e6ec9c3da25f30170e775f789c4836d3a00d919fe5e5 Valid from: Tue Aug 08 06:57:36 CDT 2023 until: Tue Aug 08 06:57:46 CDT 2073 Certificate fingerprints: SHA1: 3F:8D:06:04:A6:9F:ED:C1:39:FC:86:40:C4:8C:19:6D:C2:E3:A9:5E SHA256: 3A:1D:39:FC:3C:BD:17:A9:19:A8:45:BB:FD:FE:2A:3A:24:BD:CF:A6:0A:07:17:21:BF:D8:75:84:5E:10:50:16 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_b68c6303-e35e-44f0-b300-e9347e3e3305_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9bd61db1532aef6c9efa870ccf8cd39caf227037d82c9c0404ba3c95bff46322 Valid from: Tue Aug 08 06:57:40 CDT 2023 until: Tue Aug 08 06:57:50 CDT 2073 Certificate fingerprints: SHA1: 34:29:CF:02:EF:D0:C9:CF:A3:6C:79:A8:B9:36:D8:6F:CB:6F:4D:02 SHA256: 8B:F9:35:9E:86:1E:0A:1C:BC:2E:7C:BB:C9:50:FD:F3:84:51:F6:E8:92:C6:03:2A:0C:EB:74:0C:7D:93:8C:28 Signature algorithm name: RSASSA-PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_cef00de1-5a40-444a-94b4-35d7a290efad_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 845d78edfaf1912519bddcffffa6aaae9253dd1a087c781132686472763314e2 Valid from: Tue Aug 08 06:57:44 CDT 2023 until: Tue Aug 08 06:57:54 CDT 2073 Certificate fingerprints: SHA1: A4:EC:F5:F6:80:A1:51:FE:DD:65:AC:7E:2E:78:C9:0B:FB:82:33:DC SHA256: C9:62:C8:12:CB:C6:6B:96:C6:D4:E4:9B:1D:0A:8A:E8:47:0E:C6:EA:70:E2:CE:DE:06:C8:77:4D:84:3E:32:33 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* Alias name: ssa_cef05e47-6622-43e7-b61d-1209f0dcdf99_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ee31a06bda23b8f5a042295d851018c3502a7a8bcd22e2367226c9b5014699a8 Valid from: Tue Aug 08 06:57:38 CDT 2023 until: Tue Aug 08 06:57:48 CDT 2073 Certificate fingerprints: SHA1: 22:EC:A2:90:AA:1C:73:0C:23:B2:AA:F8:B2:CD:35:C2:A4:10:0E:0E SHA256: F2:B4:3B:93:BA:BF:08:E0:58:30:78:03:8F:C0:60:6A:68:E7:68:7D:00:ED:50:B2:9A:8B:21:C3:9F:71:4A:8A Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256k1) key (disabled) Version: 3 Extensions: #1: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth anyExtendedKeyUsage ] ******************************************* ******************************************* All keys are saved in aliases. Every alias has follow format: KeyOpsType + GUID + Use + Algorithm . Where: - KeyOpsType: values Connect | SSA - Use: sig (signature) | enc (encryption) - Algorithm: if Use == sig follow algorithm values are used: RS256 RS384 RS512 ES256 ES256K ES384 ES512 PS256 PS384 PS512 EdDSA if Use == enc follow algorithm values are used: RSA1_5 RSA-OAEP RSA-OAEP-256 ECDH-ES ECDH-ES+A128KW ECDH-ES+A192KW ECDH-ES+A256KW . This Key Store is used for keys/certificates keeping, which are used by the OpenID provider ( jans-auth-server ).", "title": "jans-auth-keys.pkcs12"}, {"location": "janssen-server/auth-server/crypto/key-storage/#smtp-keyspkcs12", "text": "Here is the example of the file: /etc/certs/smtp-keys.pkcs12 (list of entries/aliases). keytool -list -v -storetype PKCS12 -keystore /etc/certs/smtp-keys.pkcs12 -storepass 6VkIGu0DhnrD Keystore type: PKCS12 Keystore provider: SUN Your keystore contains 1 entry Alias name: smtp_sig_ec256 Creation date: Aug 8, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=SMTP CA Certificate Issuer: CN=SMTP CA Certificate Serial number: 690675c1 Valid from: Tue Aug 08 06:57:12 CDT 2023 until: Fri Aug 05 06:57:12 CDT 2033 Certificate fingerprints: SHA1: 69:77:F6:3E:44:0C:3A:BE:0D:58:02:71:21:72:39:12:54:DB:D7:88 SHA256: E5:E6:CB:BE:76:62:06:2F:A0:C9:49:0F:DD:0D:B1:D1:5B:D6:A2:2C:11:E1:0B:FE:84:67:B0:9D:EB:9B:3A:ED Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 256-bit EC (secp256r1) key Version: 3 Extensions: #1: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: 94 D2 A8 BC 8C D7 6F E0 EC BF 2D 92 3A 8D E1 CE ......o...-.:... 0010: 3D 71 CB B0 =q.. ] ] ******************************************* ******************************************* This Key Store stores one alias ( smtp_sig_ec256 ) and it is used for keeping of key/certificate, which is used by email sending functionality - signing of emails. Alias smtp_sig_ec256 contains self-signed certificate. User/Admin can update this KeyStore, adding key/certificate signed by trusted certificate authority (CA) (X-509 PKI).", "title": "smtp-keys.pkcs12"}, {"location": "janssen-server/auth-server/crypto/key-storage/#bcfks-keystore", "text": "Janssen also supports BCFKS format of KeyStore. As a rule this format is used on RHEL/DISA-STIG OS. Access to this type of KeyStore is provided by BCFIPS crypto provider. Modules of cryptoprovider can be found (after installing on RHEL/DISA-STIG OS) here: /var/gluu/dist/app/bc-fips-1.0.2.3.jar /var/gluu/dist/app/bcpkix-fips-1.0.6.jar . Here is example of the BCFKS KeyStore /etc/certs/jans-auth-keys.bcfks (list of entries/aliases): keytool -list -v -keystore /etc/certs/jans-auth-keys.bcfks -storetype BCFKS -providerpath /var/gluu/dist/app/bc-fips-1.0.2.3.jar:/var/gluu/dist/app/bcpkix-fips-1.0.6.jar -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -storepass CqE4ApXQxz5y Keystore type: BCFKS Keystore provider: BCFIPS Your keystore contains 30 entries Alias name: connect_01906c9d-fed6-48f1-94b8-85446a692f23_enc_rsa1_5 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 3b795840da219a3a7736d0ac0ebc2d632e925dc4b472a02e4b930eb1d5ca278b Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 40:B5:54:85:6B:3B:B1:A9:93:22:6D:91:AA:37:AD:92:A9:B0:5A:A9 SHA256: 06:23:28:01:89:6A:96:EA:A6:3E:EA:27:1D:7C:7A:8A:C7:C9:6D:3F:D0:BF:00:69:35:27:CA:CB:54:75:C6:F1 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_03a3687a-9c3c-4026-abfc-cafef6a76f92_enc_rsa-oaep Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: df266f1918ae93954aaad44cdceab2ac89be1c20ad16245f1567d751db5d6d1a Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 12:12:0B:15:47:A4:C9:AB:44:4A:00:5E:B3:3A:8E:EE:56:70:6F:A7 SHA256: 11:F8:12:47:17:E6:D1:D4:80:1F:66:72:22:2C:49:93:72:DE:EF:5E:58:40:74:5B:AE:66:C4:96:F5:9C:86:13 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_1b960e55-7b8c-4eeb-9379-b933b8a28fb6_enc_ecdh-es+a128kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ad0cb98a5844cfe6a56c944d269aa3ce6379dc8fea2b0752514753935ae3d821 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 28:8F:83:99:24:8E:97:54:5A:B7:41:BB:28:C5:5E:BE:67:38:AF:F4 SHA256: E5:DE:D0:4A:17:5B:F8:5D:32:E4:8B:E2:E6:24:D6:22:50:D6:2E:E1:D4:ED:AB:9A:AB:74:B8:24:8C:16:97:14 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_4260d824-790d-440e-b2e0-a1a4ab813169_sig_es512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 28f4866a894a33bb70dcb33138631be67a3b3b2c2b02c31a24913fde2d6d905d Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: CD:2C:FC:D2:81:A7:26:EA:C1:63:66:C4:AF:43:20:F3:E0:10:B7:41 SHA256: F5:3F:81:C5:B4:CD:8B:7D:B1:E4:83:54:DE:B9:88:F5:1B:3E:DA:CD:A5:93:86:D5:21:E5:3B:3D:42:5C:56:E3 Signature algorithm name: SHA512WITHECDSA Subject Public Key Algorithm: 521-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_464cc164-24ec-43c2-9f13-bca1c7faab11_sig_es256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d4786313f02f3444beabbac0ed6c307db4af29e3f044edd047e976efe48c2337 Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 8A:37:4D:12:F9:24:93:DF:1B:59:90:26:3B:1A:95:5A:F8:46:1E:CB SHA256: B4:28:C6:BC:3D:AA:7C:52:5C:E4:22:FC:E7:E0:94:BF:22:66:91:0F:D6:CF:37:6E:C5:54:ED:0C:30:A8:24:CF Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_53cfa5f1-c227-4843-94d0-e5369cd822b0_sig_rs384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 321e23c27b9ec8a65e7e8fe0e64f68aa7390d713bebfa78b17f8962bb28c1d4f Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 6F:D2:4A:FC:48:1F:F3:B7:CC:13:4B:41:3A:BC:19:C4:85:A9:E9:7C SHA256: 43:80:83:D8:84:75:87:5A:24:D6:6B:AC:EC:0D:45:2E:8F:4A:FC:B4:47:D4:D7:49:E8:06:12:2F:98:7C:91:8F Signature algorithm name: SHA384WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_63e8e482-18ef-410e-bf27-0543a37ac166_sig_ps512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 5fe30fe9ce2b55b6738ec74e0b711c5aa3052ae200fdb9c39bb1392420087d7c Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 1C:27:A5:78:64:EA:01:13:C8:62:D4:4C:93:7A:95:F5:CC:C0:55:BA SHA256: F6:CB:47:52:9D:10:B6:31:FB:C2:1F:CC:30:DD:91:DD:2D:85:C0:44:BB:AB:CA:05:9D:47:05:00:7E:35:73:8B Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_64e35c92-c4f2-4104-81ef-7a366f2dbc38_sig_ps384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6742d9b42e180b7f4a1f58121dddb02896ff1638e8254bd74415a90e47718e91 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 75:AB:EA:2C:D7:C8:87:86:7C:FE:0D:23:33:24:CE:FD:75:3E:E5:E0 SHA256: EA:7D:7F:F1:51:00:5F:D8:80:A5:AF:67:F4:E1:84:A2:E5:D0:0A:8F:A3:98:81:29:36:9B:14:DA:59:02:76:AA Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_71a098e5-0fe0-4946-85f8-adf0d6759413_enc_ecdh-es+a256kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 285d3bcd2569a9a0db6091c184e47bf855edf758251749b739267b7f6f9821d3 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: D6:D7:0C:33:6E:A8:A4:54:2A:1F:2D:59:7D:2C:26:0A:EB:B8:AE:41 SHA256: EC:82:5E:A3:66:99:FB:3E:64:B7:47:27:AA:0D:13:C6:64:E1:42:41:B4:8E:F7:B9:23:20:AA:15:1E:F3:22:F7 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_82a7b334-4756-4201-a432-1b181badf695_sig_ps256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: cce1b501329cff10503a96587042b4f37cc994ac3f98c615bab4c9680a53d769 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 37:1C:A3:F4:A3:04:E4:DC:AA:F3:21:AD:BD:B0:5F:D8:0A:95:7B:29 SHA256: D7:CA:AE:57:A3:43:1E:94:93:ED:C8:34:72:29:DD:CE:02:BD:E5:69:6D:34:D3:7D:26:AE:78:19:4C:E9:BF:CE Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_a3d528cf-fd43-4015-92be-1e644310bbf0_enc_ecdh-es Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: de13b1e646dd2456c3512de303b2fb272108bcdb40c180717077820c07e32f65 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: EF:5E:62:AA:89:31:70:83:35:40:CB:9E:30:23:32:21:12:77:DC:83 SHA256: 88:1A:A2:85:DB:27:46:04:EE:E5:DC:8A:5E:A7:77:CC:36:C5:A6:1A:E7:A1:85:44:2E:E4:A0:91:8A:FD:A4:6F Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_ab2f67de-14fb-4312-89fa-56b2cd70f616_sig_es256k Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: d36755d2a472837ab9fe1dad688b5a1881bff6073d5a494af0275226f236146c Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 8B:FD:A9:75:7C:33:1E:9D:03:47:58:2E:31:D6:49:30:E6:65:6B:A7 SHA256: 5C:E2:28:7B:B0:66:17:A8:14:82:49:14:16:E8:40:B3:B6:C1:5F:90:77:25:A3:C4:A5:25:E6:77:CB:B9:92:91 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_ae7adf42-8f9b-4fe0-bbf1-e9e1016904f5_enc_rsa-oaep-256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 324a9b70a8410e9a02eb596e536cda516f91b250befb22699a909d0b2505e03 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 66:CF:B6:EB:27:10:CC:45:E4:CF:8A:66:71:05:97:22:BA:47:6B:33 SHA256: EF:16:46:1F:C5:0B:41:0B:B4:06:A7:9D:7F:EB:81:76:5F:35:B3:E4:09:67:95:D2:2A:10:D3:2F:59:DA:5D:73 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_b52de13d-33fe-446f-b4fa-6b4ce816c18e_sig_rs256 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4d4b22cacdd15cd7bbf339c18ef14fba4ba7b0f13ad37f9452e00404488a880c Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 47:03:76:16:4B:D9:5C:83:AC:C7:40:10:F3:46:72:86:15:21:6C:CD SHA256: A3:3A:22:75:E2:E5:5B:69:31:FB:E8:59:E0:90:20:60:BC:47:30:9C:5C:5A:B6:97:92:37:71:CD:91:BF:93:78 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_c82cc876-6e92-408c-b519-76d153aad42d_enc_ecdh-es+a192kw Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 586b7dd9cecd3ef8c58b1bac766caec5d4c2ac8097c1cc4a22a20905ce5f9229 Valid from: Thu Aug 17 04:58:52 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: E6:3E:62:82:3C:6F:FE:CF:85:FD:6D:82:A9:7D:68:03:38:F0:AB:63 SHA256: 0D:D0:1B:50:02:0B:41:C1:35:CD:A9:7A:E5:10:AA:88:F2:AD:F7:8E:88:C2:3F:68:A9:33:E6:1B:EB:28:71:30 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: connect_d1001a39-29a1-45e4-ae0d-2eee86a83ada_sig_rs512 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ba44ac71c5a340aec0d8e0078b059c36a2819915774e8403e1b589a330570833 Valid from: Thu Aug 17 04:58:50 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 49:59:6A:9D:D6:E6:98:05:18:BD:25:1A:C5:C0:2B:A6:C3:3E:36:52 SHA256: DA:57:65:45:A2:16:76:E0:B7:20:DA:82:BF:77:AF:B9:58:D5:E7:D3:2F:1B:D3:BC:48:51:E2:D1:C2:41:A9:FA Signature algorithm name: SHA512WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: connect_f32a5790-4e43-4629-95bd-37b35d7c2e39_sig_es384 Creation date: Aug 17, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 9f0340f5c5cafc1816d2a31c20846fb24d400b3b5194a629ac5baf6db6d15e60 Valid from: Thu Aug 17 04:58:51 CDT 2023 until: Sat Aug 19 05:58:59 CDT 2023 Certificate fingerprints: SHA1: 5A:37:CA:6A:27:AB:9F:FC:6B:C3:D3:C6:B4:47:F3:10:F4:C9:F3:B3 SHA256: 11:A4:9C:ED:C0:05:B9:27:89:2B:17:52:11:AA:34:B4:E7:81:08:13:44:7D:93:3A:DE:CA:23:A4:22:F7:05:9F Signature algorithm name: SHA384WITHECDSA Subject Public Key Algorithm: 384-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_0639ba94-902c-4ab6-923a-58137554f667_enc_ecdh-es Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6fac3869f3fc7297470eee65fc4315328edaf475798d5bbc469de652f3088ca3 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: 76:B5:F0:B9:1C:88:54:95:5B:11:2A:6A:AE:2E:C3:02:59:1B:07:2C SHA256: 7B:26:2E:36:4B:27:AA:C0:5B:FE:2C:2E:73:B1:75:64:2D:3E:0B:D2:C4:8D:F6:63:12:E8:2E:4C:46:EB:35:4C Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_0d94f183-878c-445d-9917-28357b15c4ee_sig_rs256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 6d76a82ed166e13ecc2fb0742ebc72f619af0b738baf69438d2aba4262cfdbc4 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 14:8E:19:D8:8D:FD:68:14:40:72:35:1F:93:2A:7D:83:81:7E:6C:D8 SHA256: CB:69:E0:7C:55:2C:39:56:F8:17:ED:72:96:47:DB:8C:90:1A:1E:2A:E8:33:CA:79:96:DD:44:9F:F7:63:A2:D4 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_1a5ea0d5-0c70-43d2-ab23-e324620b413b_sig_ps512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 42bd6fbc27749cd6598c54aa0928e93057dc6c6c083c9f73d4e2046c4bac02d0 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: D3:D1:31:59:33:D1:A6:86:8F:A5:F8:7F:D6:15:44:53:15:99:6D:DC SHA256: 88:95:8C:89:F3:E7:28:E8:3D:9F:47:39:E2:F8:F5:FC:FA:63:71:B3:81:F0:9C:98:7E:A4:0A:FD:7E:7E:E9:AD Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_20d8cce9-0994-4fca-9cfa-f5fbe22eb940_sig_es256k Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: a192c3ca749b78a153cb3134c50fddcdd5dd401dd399b831199ba383eddf355b Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 4E:94:55:21:15:53:1E:3E:3B:6E:85:B9:BF:A7:4B:46:2A:FB:09:4F SHA256: BA:AB:58:DF:29:7C:5A:D5:31:2F:B9:8B:CE:E9:3F:0B:5B:E5:01:94:CC:A8:9B:41:8B:45:9B:30:D2:63:D6:24 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_33b1591d-1b79-490f-a980-573486ec620b_sig_es384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: ba8a0e96843f1a5181a96d2fc1bdae8b6954bb70b2b5c1fad4895438f4079dd0 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: B8:97:F4:EA:85:14:41:24:8C:DC:E0:8F:66:18:FD:31:7E:0B:5D:D5 SHA256: F3:9E:1F:25:E2:03:3C:7B:69:15:12:01:E2:94:EF:1E:95:43:43:A2:CB:8E:88:88:8A:3D:53:5E:82:E9:0E:9C Signature algorithm name: SHA384WITHECDSA Subject Public Key Algorithm: 384-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_34943497-d9fb-43ca-8ee1-1437e1dcf78e_sig_ps384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: b45de18f13366f309b100be313770edc6e80942771b08d656e699f7e081e5a69 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: C4:2D:DB:4D:06:7F:27:89:9A:C0:84:DB:08:BF:0C:75:3B:5B:74:22 SHA256: 77:07:D2:90:7C:AD:7A:F1:D8:EE:C1:84:54:B6:E5:41:7B:BB:C7:8F:64:96:D4:D3:ED:FD:32:F3:6C:10:11:62 Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_475830af-d019-4e04-9fb9-e68f0491284a_sig_es512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 69e6093118ce51ec5f21477e2946dd023f3c5b70bbde2922b26139b653eddd62 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 30:9D:95:9C:AE:60:F9:3F:D8:7A:AD:89:9D:AC:5D:7F:05:52:F9:50 SHA256: CA:90:7B:75:3C:99:CE:F2:42:DE:55:38:83:CB:C2:EA:F8:E7:0D:2B:00:5F:57:CF:75:D5:33:C4:5E:32:7E:A7 Signature algorithm name: SHA512WITHECDSA Subject Public Key Algorithm: 521-bit EC key Version: 3 ******************************************* ******************************************* Alias name: ssa_59bb3fe7-bf2a-4244-85a7-dd18785bcac6_enc_rsa-oaep Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 7f3e4adf1e08994ba83a1a59584c6f402e584baaecf1735ff9e0add33d65a423 Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: FC:D7:45:92:F4:60:73:C6:7C:19:DA:AB:EC:54:FF:B4:62:C6:AC:CB SHA256: 66:05:C9:4C:3D:CA:EC:9F:29:06:57:00:A8:90:09:24:17:41:71:DC:1F:8E:7F:E7:5B:39:D8:A1:8B:A3:5A:F2 Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_5e0f07d5-1e91-4bd3-bf56-6caa8a137ea6_enc_rsa1_5 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 3449c41d6f7c1b5b7f33c7411a81f41883f6f1fccb64d4e2bc22c130d771a26a Valid from: Thu Aug 10 18:20:51 CDT 2023 until: Thu Aug 10 18:21:01 CDT 2073 Certificate fingerprints: SHA1: 1F:55:2E:62:3D:7E:FE:92:20:13:0D:FC:33:F8:82:B1:B7:BF:9E:7A SHA256: C9:6E:48:AF:F7:8B:04:30:FB:4B:30:47:A2:83:1E:4C:AF:9E:04:E6:07:8A:B1:AE:3B:CD:92:AE:CB:97:D2:EB Signature algorithm name: SHA256WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_7d9cec29-697e-4e3e-9991-eba03394b69c_sig_ps256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 15e7eed8194a80919e9bd699212efca7e50ec9aa3834c6a8e32a7eeb9d9e1da9 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: A5:BE:24:97:EB:F5:0F:18:05:56:02:BF:66:24:98:24:59:82:5A:E6 SHA256: 16:EF:DD:45:17:3B:D7:66:36:14:7E:96:03:1F:51:02:6C:86:1E:19:E7:43:C7:DF:E9:A9:D0:86:9C:A6:7C:B8 Signature algorithm name: PSS Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_96ea824f-f915-4da8-8f76-3b4bf8bdf552_sig_rs384 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 4c79afa5d03e2aaab17c90519d59dec517de004f4c9b62960ebf10276b699105 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: E8:F3:5D:16:D0:2C:47:98:D4:F6:98:A1:5F:46:A0:DB:BD:F8:72:30 SHA256: 15:42:A4:30:FE:DB:D8:C4:61:11:A6:8D:10:51:02:64:70:C7:EA:BF:F3:C8:F3:42:03:D9:F8:00:19:F9:7C:28 Signature algorithm name: SHA384WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_b7ee7e46-0a6b-4040-b6b3-a78e9dedc116_sig_rs512 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 82f95026558b89f3ca8c1129d3b79c74ce2ff70bb849991a8305afea974ebe1c Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: D8:45:78:27:94:39:93:57:DF:67:56:3B:06:5C:0C:2A:20:93:F6:0F SHA256: 6D:55:8E:F3:5F:6A:EA:6D:37:71:A9:57:1D:32:98:92:04:5E:8B:4A:C4:FC:E1:ED:B1:7A:D4:11:BF:38:02:80 Signature algorithm name: SHA512WITHRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 ******************************************* ******************************************* Alias name: ssa_b9d65217-ff51-4eab-914f-aeb40eb30bc2_sig_es256 Creation date: Aug 10, 2023 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Jans Auth CA Certificates Issuer: CN=Jans Auth CA Certificates Serial number: 632a5f6e2bf5c5dbabf7376718c35b3101fe8a8065a6bf54db3dde5a1825dbf4 Valid from: Thu Aug 10 18:20:50 CDT 2023 until: Thu Aug 10 18:21:00 CDT 2073 Certificate fingerprints: SHA1: 7D:51:C1:44:45:EF:6B:71:3D:EF:BC:20:E0:AE:59:4C:3D:16:10:23 SHA256: CC:1C:60:5E:E4:6A:B4:C4:7F:3F:2D:1B:2F:12:B4:79:27:94:3D:1D:D5:FA:C4:11:0E:53:76:DA:52:34:B0:62 Signature algorithm name: SHA256WITHECDSA Subject Public Key Algorithm: 256-bit EC key Version: 3 ******************************************* ******************************************* .", "title": "BCFKS KeyStore"}, {"location": "janssen-server/auth-server/crypto/keys/", "tags": ["administration", "auth-server", "cryptography", "keys"], "text": "Overview # Janssen uses keys for signing and encryption, primarily concerning JSON documents. Janssen supports several signing and encryption algorithms in salted and unsalted, to fit a variety of business needs. If other algorithms are necessary, Janssen supports them via interception scripts. Keys # A key is a piece of information, usually a string of numbers or letters that are stored in a file, which, when processed through a cryptographic algorithm, can encode or decode cryptographic data. In Janssen we use keys for creating token like id_token , access_token . access_token : Access tokens are what the OAuth client uses to make requests to an API. The access token is meant to be read and validated by the API. id_token : An ID token is an artifact that proves that the user has been authenticated. It was introduced by OpenID Connect (OIDC) , an open standard for authentication used by Janssen. It contains information about what happened when a user authenticated, and is intended to be read by the OAuth client. The ID token may also contain information about the user such as their name or email address, although that is not a requirement of an ID token. Jans server JSON objects of public key # Gets list of JSON Web Key (JWK) used by server. JWK is a JSON data structure that represents a set of public keys as a JSON object. Browse below endpoint to know more about public keys used by server. https://<your_server>/jans-auth/restv1/jwks Let's see some example of JWT public keys used in janssen. When jwk is expired, it is archived and can be access by following url: https://<your_server>/jans-auth/restv1/jwks/archived/{kid} More info about archived jwks can be found here Example-1 # The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for \"sig\" (Signature) on data. The \"alg\" (Algorithm) intended with this key is \"RS256\". { \"name\" : \"Connect RS256 Sign Key\" \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\", ... } Example-2 # The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for \"sig\" (Signature) on data. The \"alg\" (Algorithm) intended with this key is \"RS384\". { \"name\" : \"Connect RS384 Sign Key\", \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-384\", ... } Example-3 # The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"RS512\". { \"name\" : \"Connect RS512 Sign Key\", \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-512\", ... } Example-4 # The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256\". { \"name\" : \"Connect ES256 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-256 (secp256r1) and SHA-256\", ... } Example-5 # The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256K\". { \"name\" : \"Connect ES256 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-256 (secp256r1) and SHA-256\", ... } Example-6 # The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256K\". { \"name\" : \"Connect ES384 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-384 (secp384r1) and SHA-384\", ... } Example-7 # The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES512\". { \"name\" : \"Connect ES512 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-521 (secp521r1) and SHA-512\", ... } Example-8 # The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS256\". { \"name\" : \"Connect PS256 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-256 and MGF1 with SHA-256\", ... } Example-9 # The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS384\". { \"name\" : \"Connect PS384 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-384 and MGF1 with SHA-384\", ... } Example-10 # The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS512\". { \"name\" : \"Connect PS512 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-512 and MGF1 with SHA-512\", ... } Example-11 # The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for \"enc\" (encryption) on data. The \"alg\" (Algorithm) intended with this key is \"RSA1_5\". ``commandLine { \"name\" : \"Connect RSA1_5 Encryption Key\", \"descr\" : \"Encryption Key: RSAES-PKCS1-v1_5\", ... } ### Example-12 The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for \"enc\" (encryption) on data. The \"alg\" (Algorithm) intended with this key is \"RSA-OAEP\". ```commandLine { \"name\" : \"Connect RSA-OAEP Encryption Key\", \"descr\" : \"Encryption Key: RSAES OAEP using default parameters\", ... } Crypto Supported # Depending on the transport through which the messages are sent, the integrity of the message might not be guaranteed and the originator of the message might not be authenticated. To mitigate these risks, ID Token, UserInfo Response, Request Object, and Client Authentication JWT values can utilize JSON Web Signature (JWS) [JWS] to sign their contents. To achieve message confidentiality, these values can also use JSON Web Encryption (JWE) [JWE] to encrypt their contents. Signing algorithms # Signing or Signature algorithm is a cryptographic mechanism used to verify the authenticity and integrity of digital data. We may consider it as a digital version of the ordinary handwritten signatures, but with higher levels of complexity and security. Let's see some signing key algorithms Name Kty Use Alg RS256 Sign Key RSA sig RS256 RS384 Sign Key RSA sig RS384 RS512 Sign Key RSA sig RS512 ES256 Sign Key EC sig ES256 ES256 Sign Key EC sig ES256K ES384 Sign Key EC sig ES384 ES512 Sign Key EC sig ES384 PS256 Sign Key RSA sig PS256 PS384 sign Key RSA sig PS384 PS512 sign Key RSA sig PS512 Encryption algorithms # In cryptography, encryption is the process of encoding information. This process converts the original representation of the information, known as plaintext, into an alternative form known as ciphertext. Ideally, only authorized parties can decipher a ciphertext back to plaintext and access the original information. Let's see some encryption keys. Name Kty Use Alg RSA1_5 Encryption key RSA enc RSA1_5 RSA-OAEP Encryption Key RSA enc RSA-OAEP ECDH-ES Encryption Key CE enc ECDH-ES RSA Key Formats # PKCS#8 encrypted private key \"EncryptedPrivateKeyInfo\" (default for private keys) PKCS#1 \"RSAPublicKey\" (default for public keys) PKCS#8 unencrypted \"PrivateKeyInfo\" PKCS#1 unencrypted \"RSAPrivateKey\" (OpenSSL private key file format) X.509 \"SubjectPublicKeyInfo\" (OpenSSL public key file format) The above key values can be passed as (a) a binary DER-encoded ASN.1 file, (b) a text file in PEM format, (c) a string containing the key in PEM format . Also supported are RSA private and public keys represented in XML format to XKMS 2.0 [XKMS] and JSON Web Key (JWK) format [JWK] . For more details, see Key Storage Format . To know more about RSA keyformat browse here Janssen Keystore Formats # In Janssen we use keystore formats PKCS12 . Which is Encrypted private key formats. In Janssen currently using an extension of p12 . We also have pkcs12 , pfx . We can store private keys, secret keys and certificates on this type. You can find jans-auth-keys.p12 in /etc/certs/ To see the private key you can use bellow command keytool -list -v -keystore /etc/certs/jans-auth-keys.p12 -storetype pkcs12 -storepass <password>", "title": "Keys"}, {"location": "janssen-server/auth-server/crypto/keys/#overview", "text": "Janssen uses keys for signing and encryption, primarily concerning JSON documents. Janssen supports several signing and encryption algorithms in salted and unsalted, to fit a variety of business needs. If other algorithms are necessary, Janssen supports them via interception scripts.", "title": "Overview"}, {"location": "janssen-server/auth-server/crypto/keys/#keys", "text": "A key is a piece of information, usually a string of numbers or letters that are stored in a file, which, when processed through a cryptographic algorithm, can encode or decode cryptographic data. In Janssen we use keys for creating token like id_token , access_token . access_token : Access tokens are what the OAuth client uses to make requests to an API. The access token is meant to be read and validated by the API. id_token : An ID token is an artifact that proves that the user has been authenticated. It was introduced by OpenID Connect (OIDC) , an open standard for authentication used by Janssen. It contains information about what happened when a user authenticated, and is intended to be read by the OAuth client. The ID token may also contain information about the user such as their name or email address, although that is not a requirement of an ID token.", "title": "Keys"}, {"location": "janssen-server/auth-server/crypto/keys/#jans-server-json-objects-of-public-key", "text": "Gets list of JSON Web Key (JWK) used by server. JWK is a JSON data structure that represents a set of public keys as a JSON object. Browse below endpoint to know more about public keys used by server. https://<your_server>/jans-auth/restv1/jwks Let's see some example of JWT public keys used in janssen. When jwk is expired, it is archived and can be access by following url: https://<your_server>/jans-auth/restv1/jwks/archived/{kid} More info about archived jwks can be found here", "title": "Jans server JSON objects of public key"}, {"location": "janssen-server/auth-server/crypto/keys/#example-1", "text": "The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for \"sig\" (Signature) on data. The \"alg\" (Algorithm) intended with this key is \"RS256\". { \"name\" : \"Connect RS256 Sign Key\" \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\", ... }", "title": "Example-1"}, {"location": "janssen-server/auth-server/crypto/keys/#example-2", "text": "The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for \"sig\" (Signature) on data. The \"alg\" (Algorithm) intended with this key is \"RS384\". { \"name\" : \"Connect RS384 Sign Key\", \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-384\", ... }", "title": "Example-2"}, {"location": "janssen-server/auth-server/crypto/keys/#example-3", "text": "The \"kty\" (Key Type) of this key is RSA. This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"RS512\". { \"name\" : \"Connect RS512 Sign Key\", \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-512\", ... }", "title": "Example-3"}, {"location": "janssen-server/auth-server/crypto/keys/#example-4", "text": "The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256\". { \"name\" : \"Connect ES256 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-256 (secp256r1) and SHA-256\", ... }", "title": "Example-4"}, {"location": "janssen-server/auth-server/crypto/keys/#example-5", "text": "The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256K\". { \"name\" : \"Connect ES256 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-256 (secp256r1) and SHA-256\", ... }", "title": "Example-5"}, {"location": "janssen-server/auth-server/crypto/keys/#example-6", "text": "The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES256K\". { \"name\" : \"Connect ES384 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-384 (secp384r1) and SHA-384\", ... }", "title": "Example-6"}, {"location": "janssen-server/auth-server/crypto/keys/#example-7", "text": "The \"kty\" (Key Type) of this key is \"EC\" (Ellliptic Curve). This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"ES512\". { \"name\" : \"Connect ES512 Sign Key\", \"descr\" : \"Signature Key: ECDSA using P-521 (secp521r1) and SHA-512\", ... }", "title": "Example-7"}, {"location": "janssen-server/auth-server/crypto/keys/#example-8", "text": "The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS256\". { \"name\" : \"Connect PS256 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-256 and MGF1 with SHA-256\", ... }", "title": "Example-8"}, {"location": "janssen-server/auth-server/crypto/keys/#example-9", "text": "The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS384\". { \"name\" : \"Connect PS384 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-384 and MGF1 with SHA-384\", ... }", "title": "Example-9"}, {"location": "janssen-server/auth-server/crypto/keys/#example-10", "text": "The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for signature (\"sig\") on data. The \"alg\" (Algorithm) intended with this key is \"PS512\". { \"name\" : \"Connect PS512 Sign Key\", \"descr\" : \"Signature Key: RSASSA-PSS using SHA-512 and MGF1 with SHA-512\", ... }", "title": "Example-10"}, {"location": "janssen-server/auth-server/crypto/keys/#example-11", "text": "The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for \"enc\" (encryption) on data. The \"alg\" (Algorithm) intended with this key is \"RSA1_5\". ``commandLine { \"name\" : \"Connect RSA1_5 Encryption Key\", \"descr\" : \"Encryption Key: RSAES-PKCS1-v1_5\", ... } ### Example-12 The \"kty\" (Key Type) of this key is \"RSA\". This key is \"use\" (Public Key Use) for \"enc\" (encryption) on data. The \"alg\" (Algorithm) intended with this key is \"RSA-OAEP\". ```commandLine { \"name\" : \"Connect RSA-OAEP Encryption Key\", \"descr\" : \"Encryption Key: RSAES OAEP using default parameters\", ... }", "title": "Example-11"}, {"location": "janssen-server/auth-server/crypto/keys/#crypto-supported", "text": "Depending on the transport through which the messages are sent, the integrity of the message might not be guaranteed and the originator of the message might not be authenticated. To mitigate these risks, ID Token, UserInfo Response, Request Object, and Client Authentication JWT values can utilize JSON Web Signature (JWS) [JWS] to sign their contents. To achieve message confidentiality, these values can also use JSON Web Encryption (JWE) [JWE] to encrypt their contents.", "title": "Crypto Supported"}, {"location": "janssen-server/auth-server/crypto/keys/#signing-algorithms", "text": "Signing or Signature algorithm is a cryptographic mechanism used to verify the authenticity and integrity of digital data. We may consider it as a digital version of the ordinary handwritten signatures, but with higher levels of complexity and security. Let's see some signing key algorithms Name Kty Use Alg RS256 Sign Key RSA sig RS256 RS384 Sign Key RSA sig RS384 RS512 Sign Key RSA sig RS512 ES256 Sign Key EC sig ES256 ES256 Sign Key EC sig ES256K ES384 Sign Key EC sig ES384 ES512 Sign Key EC sig ES384 PS256 Sign Key RSA sig PS256 PS384 sign Key RSA sig PS384 PS512 sign Key RSA sig PS512", "title": "Signing algorithms"}, {"location": "janssen-server/auth-server/crypto/keys/#encryption-algorithms", "text": "In cryptography, encryption is the process of encoding information. This process converts the original representation of the information, known as plaintext, into an alternative form known as ciphertext. Ideally, only authorized parties can decipher a ciphertext back to plaintext and access the original information. Let's see some encryption keys. Name Kty Use Alg RSA1_5 Encryption key RSA enc RSA1_5 RSA-OAEP Encryption Key RSA enc RSA-OAEP ECDH-ES Encryption Key CE enc ECDH-ES", "title": "Encryption algorithms"}, {"location": "janssen-server/auth-server/crypto/keys/#rsa-key-formats", "text": "PKCS#8 encrypted private key \"EncryptedPrivateKeyInfo\" (default for private keys) PKCS#1 \"RSAPublicKey\" (default for public keys) PKCS#8 unencrypted \"PrivateKeyInfo\" PKCS#1 unencrypted \"RSAPrivateKey\" (OpenSSL private key file format) X.509 \"SubjectPublicKeyInfo\" (OpenSSL public key file format) The above key values can be passed as (a) a binary DER-encoded ASN.1 file, (b) a text file in PEM format, (c) a string containing the key in PEM format . Also supported are RSA private and public keys represented in XML format to XKMS 2.0 [XKMS] and JSON Web Key (JWK) format [JWK] . For more details, see Key Storage Format . To know more about RSA keyformat browse here", "title": "RSA Key Formats"}, {"location": "janssen-server/auth-server/crypto/keys/#janssen-keystore-formats", "text": "In Janssen we use keystore formats PKCS12 . Which is Encrypted private key formats. In Janssen currently using an extension of p12 . We also have pkcs12 , pfx . We can store private keys, secret keys and certificates on this type. You can find jans-auth-keys.p12 in /etc/certs/ To see the private key you can use bellow command keytool -list -v -keystore /etc/certs/jans-auth-keys.p12 -storetype pkcs12 -storepass <password>", "title": "Janssen Keystore Formats"}, {"location": "janssen-server/auth-server/endpoints/access-evaluation/", "tags": ["administration", "auth-server", "access-evaluation", "endpoint"], "text": "Overview # The Jans-Auth server implements OpenID AuthZEN Authorization API 1.0 \u2013 draft 01 . The AuthZEN Authorization API 1.0 specification defines a standardized interface for communication between Policy Enforcement Points (PEPs) and Policy Decision Points (PDPs) to facilitate consistent authorization decisions across diverse systems. It introduces an Access Evaluation API that allows PEPs to query PDPs about specific access requests, enhancing interoperability and scalability in authorization processes. The specification is transport-agnostic, with an initial focus on HTTPS bindings, and emphasizes secure, fine-grained, and dynamic authorization mechanisms. The Access Evaluation Endpoint in the AuthZEN specification serves as a mechanism for Policy Enforcement Points (PEPs) to request access decisions from a Policy Decision Point (PDP) for specific resources and actions. Upon receiving a request, the endpoint evaluates the subject, resource, and action against defined policies to determine if access should be granted, denied, or if additional information is needed. The endpoint's responses are typically concise, aiming to provide a rapid decision that PEPs can enforce in real-time. The goal is to provide a scalable, secure interface for dynamic and fine-grained access control across applications. URL to access access evaluation endpoint on Janssen Server is listed in both: - the response of Janssen Server's well-known configuration endpoint given below. - the response of Janssen Server's /.well-known/authzen-configuration endpoint. OpenID Discovery https://janssen.server.host/jans-auth/.well-known/openid-configuration AuthZEN Discovery https://janssen.server.host/jans-auth/.well-known/authzen-configuration /.well-known/authzen-configuration allows to publish data specific to AuthZEN only. Response of AuthZEN discovery endpoint can be changed via AccessEvaluationDiscoveryType custom script. Snippet of AccessEvaluationDiscoveryType @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { scriptLogger . info ( \"write to script logger\" ); JSONObject response = ( JSONObject ) responseAsJsonObject ; response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); return true ; } access_evaluation_v1_endpoint claim in the response specifies the URL for access evaluation endpoint. By default, access evaluation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/access/v1/evaluation In order to call Access Evaluation Endpoint client must have access_evaluation scope. If scope is not present AS rejects call with 401 (unauthorized) http status code. Authorization header must contain valid access_token with access_evaluation scope granted to it. Otherwise it's possible to use Basic token with encoded client credentials if set accessEvaluationAllowBasicClientAuthorization AS configuration property to true . Bearer token : Authorization: Bearer <access_token> Basic authorization : Authorization: Basic <encoded client credentials> More information about request and response of the Access Evaluation Endpoint can be found in the OpenAPI specification of jans-auth-server module . Sample request POST /jans-auth/restv1/access/v1/evaluation HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Authorization: Basic M2NjOTdhYWItMDE0Zi00ZWM5LWI4M2EtNTE3MTRlODE3MDMwOmFlYmMwZWFhLWY5N2YtNDU5NS04ZWExLWFlNmU1NDFmNDZjNg== { \"subject\": { \"id\": \"alice@acmecorp.com\", \"type\": \"super_admin\", \"properties\": null }, \"resource\": { \"id\": \"123\", \"type\": \"account\", \"properties\": null }, \"action\": { \"name\": \"can_read\", \"properties\": { \"method\": \"GET\" } }, \"context\": { \"properties\": null } } Sample successful response with authorization_code . HTTP/1.1 200 Content-Type: application/json { \"decision\":true, \"context\": { \"id\":\"9e04dd22-e980-4e54-bc04-d64a0c2e1afe\", \"reason_admin\":{\"reason\":\"super_admin\"}, \"reason_user\":null } } Sample error response HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"invalid_token\" } Configuration Properties # Access Evaluation Endpoint AS configuration: accessEvaluationScriptName - Access evaluation custom script name. If not set AS falls back to first valid script found in database. accessEvaluationAllowBasicClientAuthorization - Allow basic client authorization for access evaluation endpoint. Custom script # AS provides AccessEvaluationType custom script which must be used to control Access Evaluation Endpoint behaviour. Use accessEvaluationScriptName configuration property to specify custom script. If not set AS falls back to first valid script found in database. Main evaluate method returns response which grants or denies access. Please see following snippet below: @Override public AccessEvaluationResponse evaluate ( AccessEvaluationRequest request , Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. access http request via context.getHttpRequest() // 2. access all access evaluation specific data directly with 'request', e.g. request.getSubject() // 3. perform custom validation if needed validateResource ( request . getResource ()); // typically some internal validation must be performed here // request data alone must not be trusted, it's just sample to demo script with endpoint if ( \"super_admin\" . equalsIgnoreCase ( request . getSubject (). getType ())) { final ObjectNode reasonAdmin = objectMapper . createObjectNode (); reasonAdmin . put ( \"reason\" , \"super_admin\" ); final AccessEvaluationResponseContext responseContext = new AccessEvaluationResponseContext (); responseContext . setId ( UUID . randomUUID (). toString ()); responseContext . setReasonAdmin ( reasonAdmin ); return new AccessEvaluationResponse ( true , responseContext ); } return AccessEvaluationResponse . FALSE ; } More details in Access Evaluation Custom Script Page . Full sample script can be found here Full successful Access Evaluation Flow sample # ####################################################### TEST: OpenID Connect Discovery ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/webfinger HTTP/1.1?resource=acct%3Aadmin%40happy-example.gluu.info&rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer HTTP/1.1 Host: happy-example.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 207 Content-Type: application/jrd+json;charset=iso-8859-1 Date: Fri, 08 Nov 2024 17:15:19 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=f8a91ca8-3ebb-48fb-852e-31e40b398b6d; Secure; HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"subject\": \"acct:admin@happy-example.gluu.info\", \"links\": [{ \"rel\": \"http://openid.net/specs/connect/1.0/issuer\", \"href\": \"https://happy-example.gluu.info\" }] } OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: happy-example.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 7715 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:19 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=474307e2-ed02-404e-bf35-a2bc60bf3421; Secure; HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/par\", \"introspection_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"introspection_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"status_list_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/status_list\", \"issuer\" : \"https://happy-example.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"introspection_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"fragment\", \"query.jwt\", \"query\", \"fragment.jwt\", \"jwt\", \"form_post.jwt\", \"form_post\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code token\", \"code\", \"code id_token\", \"code token id_token\", \"token id_token\", \"token\", \"id_token\" ], \"tx_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:device_code\", \"refresh_token\", \"implicit\", \"password\", \"authorization_code\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:token-exchange\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"prompt_values_supported\" : [ \"none\", \"login\", \"consent\", \"select_account\", \"create\" ], \"userinfo_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/userinfo\", \"access_evaluation_v1_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/access/v1/evaluation\", \"authorization_challenge_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/authorization_challenge\", \"op_tos_uri\" : \"https://happy-example.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"global_token_revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/global-token-revocation\", \"introspection_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"tx_token_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"session_revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://happy-example.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"role\", \"access_evaluation\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"clientinfo\", \"user_name\", \"profile\", \"uma_protection\", \"revoke_any_token\", \"global_token_revocation\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"device_sso\", \"https://jans.io/scim/users.read\", \"phone\", \"mobile_phone\", \"offline_access\", \"authorization_challenge\", \"https://jans.io/oauth/lock/audit.write\", \"email\", \"https://jans.io/oauth/lock/audit.readonly\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"archived_jwks_uri\" : \"https://happy-example.gluu.info/jans-auth/restv1/jwks/archived\", \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"tx_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://happy-example.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: accessEvaluation_whenSubjectTypeIsAcceptedByScript_shouldGrantAccess ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"access_evaluation openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://happy-example.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"access_evaluation test\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1664 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:20 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=d7035723-e472-4cac-84c5-ef19f14fcc09; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://happy-example.gluu.info/jans-auth/restv1/register?client_id=3cc97aab-014f-4ec9-b83a-51714e817030\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"bcf42a29-d534-4ed4-a4aa-eceb4e50f472\", \"client_id\": \"3cc97aab-014f-4ec9-b83a-51714e817030\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid access_evaluation\", \"client_secret\": \"aebc0eaa-f97f-4595-8ea1-ae6e541f46c6\", \"client_id_issued_at\": 1731086120, \"backchannel_logout_session_required\": false, \"client_name\": \"access_evaluation test\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"refresh_token\", \"authorization_code\" ], \"subject_type\": \"public\", \"authorization_details_types\": [], \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://happy-example.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 0, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/access/v1/evaluation HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Authorization: Basic M2NjOTdhYWItMDE0Zi00ZWM5LWI4M2EtNTE3MTRlODE3MDMwOmFlYmMwZWFhLWY5N2YtNDU5NS04ZWExLWFlNmU1NDFmNDZjNg== {\"subject\":{\"id\":\"alice@acmecorp.com\",\"type\":\"super_admin\",\"properties\":null},\"resource\":{\"id\":\"123\",\"type\":\"account\",\"properties\":null},\"action\":{\"name\":\"can_read\",\"properties\":{\"method\":\"GET\"}},\"context\":{\"properties\":null}} ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 132 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:21 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=d4f99d9f-5b94-4863-a020-73f6fb62c5e8; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"decision\":true,\"context\":{\"id\":\"9e04dd22-e980-4e54-bc04-d64a0c2e1afe\",\"reason_admin\":{\"reason\":\"super_admin\"},\"reason_user\":null}}", "title": "Access Evaluation"}, {"location": "janssen-server/auth-server/endpoints/access-evaluation/#overview", "text": "The Jans-Auth server implements OpenID AuthZEN Authorization API 1.0 \u2013 draft 01 . The AuthZEN Authorization API 1.0 specification defines a standardized interface for communication between Policy Enforcement Points (PEPs) and Policy Decision Points (PDPs) to facilitate consistent authorization decisions across diverse systems. It introduces an Access Evaluation API that allows PEPs to query PDPs about specific access requests, enhancing interoperability and scalability in authorization processes. The specification is transport-agnostic, with an initial focus on HTTPS bindings, and emphasizes secure, fine-grained, and dynamic authorization mechanisms. The Access Evaluation Endpoint in the AuthZEN specification serves as a mechanism for Policy Enforcement Points (PEPs) to request access decisions from a Policy Decision Point (PDP) for specific resources and actions. Upon receiving a request, the endpoint evaluates the subject, resource, and action against defined policies to determine if access should be granted, denied, or if additional information is needed. The endpoint's responses are typically concise, aiming to provide a rapid decision that PEPs can enforce in real-time. The goal is to provide a scalable, secure interface for dynamic and fine-grained access control across applications. URL to access access evaluation endpoint on Janssen Server is listed in both: - the response of Janssen Server's well-known configuration endpoint given below. - the response of Janssen Server's /.well-known/authzen-configuration endpoint. OpenID Discovery https://janssen.server.host/jans-auth/.well-known/openid-configuration AuthZEN Discovery https://janssen.server.host/jans-auth/.well-known/authzen-configuration /.well-known/authzen-configuration allows to publish data specific to AuthZEN only. Response of AuthZEN discovery endpoint can be changed via AccessEvaluationDiscoveryType custom script. Snippet of AccessEvaluationDiscoveryType @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { scriptLogger . info ( \"write to script logger\" ); JSONObject response = ( JSONObject ) responseAsJsonObject ; response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); return true ; } access_evaluation_v1_endpoint claim in the response specifies the URL for access evaluation endpoint. By default, access evaluation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/access/v1/evaluation In order to call Access Evaluation Endpoint client must have access_evaluation scope. If scope is not present AS rejects call with 401 (unauthorized) http status code. Authorization header must contain valid access_token with access_evaluation scope granted to it. Otherwise it's possible to use Basic token with encoded client credentials if set accessEvaluationAllowBasicClientAuthorization AS configuration property to true . Bearer token : Authorization: Bearer <access_token> Basic authorization : Authorization: Basic <encoded client credentials> More information about request and response of the Access Evaluation Endpoint can be found in the OpenAPI specification of jans-auth-server module . Sample request POST /jans-auth/restv1/access/v1/evaluation HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Authorization: Basic M2NjOTdhYWItMDE0Zi00ZWM5LWI4M2EtNTE3MTRlODE3MDMwOmFlYmMwZWFhLWY5N2YtNDU5NS04ZWExLWFlNmU1NDFmNDZjNg== { \"subject\": { \"id\": \"alice@acmecorp.com\", \"type\": \"super_admin\", \"properties\": null }, \"resource\": { \"id\": \"123\", \"type\": \"account\", \"properties\": null }, \"action\": { \"name\": \"can_read\", \"properties\": { \"method\": \"GET\" } }, \"context\": { \"properties\": null } } Sample successful response with authorization_code . HTTP/1.1 200 Content-Type: application/json { \"decision\":true, \"context\": { \"id\":\"9e04dd22-e980-4e54-bc04-d64a0c2e1afe\", \"reason_admin\":{\"reason\":\"super_admin\"}, \"reason_user\":null } } Sample error response HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"invalid_token\" }", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/access-evaluation/#configuration-properties", "text": "Access Evaluation Endpoint AS configuration: accessEvaluationScriptName - Access evaluation custom script name. If not set AS falls back to first valid script found in database. accessEvaluationAllowBasicClientAuthorization - Allow basic client authorization for access evaluation endpoint.", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/access-evaluation/#custom-script", "text": "AS provides AccessEvaluationType custom script which must be used to control Access Evaluation Endpoint behaviour. Use accessEvaluationScriptName configuration property to specify custom script. If not set AS falls back to first valid script found in database. Main evaluate method returns response which grants or denies access. Please see following snippet below: @Override public AccessEvaluationResponse evaluate ( AccessEvaluationRequest request , Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. access http request via context.getHttpRequest() // 2. access all access evaluation specific data directly with 'request', e.g. request.getSubject() // 3. perform custom validation if needed validateResource ( request . getResource ()); // typically some internal validation must be performed here // request data alone must not be trusted, it's just sample to demo script with endpoint if ( \"super_admin\" . equalsIgnoreCase ( request . getSubject (). getType ())) { final ObjectNode reasonAdmin = objectMapper . createObjectNode (); reasonAdmin . put ( \"reason\" , \"super_admin\" ); final AccessEvaluationResponseContext responseContext = new AccessEvaluationResponseContext (); responseContext . setId ( UUID . randomUUID (). toString ()); responseContext . setReasonAdmin ( reasonAdmin ); return new AccessEvaluationResponse ( true , responseContext ); } return AccessEvaluationResponse . FALSE ; } More details in Access Evaluation Custom Script Page . Full sample script can be found here", "title": "Custom script"}, {"location": "janssen-server/auth-server/endpoints/access-evaluation/#full-successful-access-evaluation-flow-sample", "text": "####################################################### TEST: OpenID Connect Discovery ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/webfinger HTTP/1.1?resource=acct%3Aadmin%40happy-example.gluu.info&rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer HTTP/1.1 Host: happy-example.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 207 Content-Type: application/jrd+json;charset=iso-8859-1 Date: Fri, 08 Nov 2024 17:15:19 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=f8a91ca8-3ebb-48fb-852e-31e40b398b6d; Secure; HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"subject\": \"acct:admin@happy-example.gluu.info\", \"links\": [{ \"rel\": \"http://openid.net/specs/connect/1.0/issuer\", \"href\": \"https://happy-example.gluu.info\" }] } OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: happy-example.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 7715 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:19 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=474307e2-ed02-404e-bf35-a2bc60bf3421; Secure; HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/par\", \"introspection_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"introspection_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"status_list_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/status_list\", \"issuer\" : \"https://happy-example.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"introspection_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"fragment\", \"query.jwt\", \"query\", \"fragment.jwt\", \"jwt\", \"form_post.jwt\", \"form_post\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code token\", \"code\", \"code id_token\", \"code token id_token\", \"token id_token\", \"token\", \"id_token\" ], \"tx_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:device_code\", \"refresh_token\", \"implicit\", \"password\", \"authorization_code\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:token-exchange\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"prompt_values_supported\" : [ \"none\", \"login\", \"consent\", \"select_account\", \"create\" ], \"userinfo_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/userinfo\", \"access_evaluation_v1_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/access/v1/evaluation\", \"authorization_challenge_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/authorization_challenge\", \"op_tos_uri\" : \"https://happy-example.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"global_token_revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/global-token-revocation\", \"introspection_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"tx_token_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"session_revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://happy-example.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"role\", \"access_evaluation\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"clientinfo\", \"user_name\", \"profile\", \"uma_protection\", \"revoke_any_token\", \"global_token_revocation\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"device_sso\", \"https://jans.io/scim/users.read\", \"phone\", \"mobile_phone\", \"offline_access\", \"authorization_challenge\", \"https://jans.io/oauth/lock/audit.write\", \"email\", \"https://jans.io/oauth/lock/audit.readonly\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"archived_jwks_uri\" : \"https://happy-example.gluu.info/jans-auth/restv1/jwks/archived\", \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"tx_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://happy-example.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://happy-example.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: accessEvaluation_whenSubjectTypeIsAcceptedByScript_shouldGrantAccess ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"access_evaluation openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://happy-example.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"access_evaluation test\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1664 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:20 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=d7035723-e472-4cac-84c5-ef19f14fcc09; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://happy-example.gluu.info/jans-auth/restv1/register?client_id=3cc97aab-014f-4ec9-b83a-51714e817030\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"bcf42a29-d534-4ed4-a4aa-eceb4e50f472\", \"client_id\": \"3cc97aab-014f-4ec9-b83a-51714e817030\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid access_evaluation\", \"client_secret\": \"aebc0eaa-f97f-4595-8ea1-ae6e541f46c6\", \"client_id_issued_at\": 1731086120, \"backchannel_logout_session_required\": false, \"client_name\": \"access_evaluation test\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"refresh_token\", \"authorization_code\" ], \"subject_type\": \"public\", \"authorization_details_types\": [], \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://happy-example.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 0, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/access/v1/evaluation HTTP/1.1 Host: happy-example.gluu.info Content-Type: application/json Authorization: Basic M2NjOTdhYWItMDE0Zi00ZWM5LWI4M2EtNTE3MTRlODE3MDMwOmFlYmMwZWFhLWY5N2YtNDU5NS04ZWExLWFlNmU1NDFmNDZjNg== {\"subject\":{\"id\":\"alice@acmecorp.com\",\"type\":\"super_admin\",\"properties\":null},\"resource\":{\"id\":\"123\",\"type\":\"account\",\"properties\":null},\"action\":{\"name\":\"can_read\",\"properties\":{\"method\":\"GET\"}},\"context\":{\"properties\":null}} ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 132 Content-Type: application/json Date: Fri, 08 Nov 2024 17:15:21 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.52 (Ubuntu) Set-Cookie: X-Correlation-Id=d4f99d9f-5b94-4863-a020-73f6fb62c5e8; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"decision\":true,\"context\":{\"id\":\"9e04dd22-e980-4e54-bc04-d64a0c2e1afe\",\"reason_admin\":{\"reason\":\"super_admin\"},\"reason_user\":null}}", "title": "Full successful Access Evaluation Flow sample"}, {"location": "janssen-server/auth-server/endpoints/archived-jwks-uri/", "tags": ["administration", "auth-server", "jwks", "json-web-key-set", "endpoint"], "text": "Overview # Janssen Server supports /jwks/archived/{kid} metadata endpoint and publishes its Archived JSON Web Keys (JWKs) at this endpoint. This endpoint publishes expired signing keys as well as expired encryption keys used by Janssen Server. RP can use these keys to validate signatures from Janssen Server, and also to perform encryption and decryption if keys are no longer present in /jwks endpoint. Like other metadata endpoints, this is not a secure endpoint. URL to access archived jwks endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration archived_jwks_uri claim in the response specifies the URL for archived jwks endpoint. By default, the archived jwks endpoint looks like below: https://janssen.server.host/jans-auth/restv1/jwks/archived/{kid} This endpoint is always enabled and can not be disabled using feature flags. Configuration Properties # Archived JWKs endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . archivedJwksUri archivedJwkLifetimeInSeconds If archivedJwkLifetimeInSeconds is not set then AS falls back to one year expiration. After archived jwk lifetime is passed, jwk is removed from archive. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Archived JWKS URI"}, {"location": "janssen-server/auth-server/endpoints/archived-jwks-uri/#overview", "text": "Janssen Server supports /jwks/archived/{kid} metadata endpoint and publishes its Archived JSON Web Keys (JWKs) at this endpoint. This endpoint publishes expired signing keys as well as expired encryption keys used by Janssen Server. RP can use these keys to validate signatures from Janssen Server, and also to perform encryption and decryption if keys are no longer present in /jwks endpoint. Like other metadata endpoints, this is not a secure endpoint. URL to access archived jwks endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration archived_jwks_uri claim in the response specifies the URL for archived jwks endpoint. By default, the archived jwks endpoint looks like below: https://janssen.server.host/jans-auth/restv1/jwks/archived/{kid} This endpoint is always enabled and can not be disabled using feature flags.", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/archived-jwks-uri/#configuration-properties", "text": "Archived JWKs endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . archivedJwksUri archivedJwkLifetimeInSeconds If archivedJwkLifetimeInSeconds is not set then AS falls back to one year expiration. After archived jwk lifetime is passed, jwk is removed from archive.", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/archived-jwks-uri/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/", "tags": ["administration", "auth-server", "authorization-challenge", "endpoint"], "text": "Overview # Authorization Challenge Endpoint allows first-party native client obtain authorization code which later can be exchanged on access token. This can provide an entirely browserless OAuth 2.0 experience suited for native applications. This endpoint conforms to OAuth 2.0 for First-Party Applications specifications. URL to access authorization challenge endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration authorization_challenge_endpoint claim in the response specifies the URL for authorization challenge endpoint. By default, authorization challenge endpoint looks like below: https://janssen.server.host/jans-auth/restv1/authorize-challenge In order to call Authorization Challenge Endpoint client must have authorization_challenge scope. If scope is not present AS rejects call with 401 (unauthorized) http status code. Authorization Challenge Endpoint supports Proof Key for Code Exchange (PKCE). More information about request and response of the authorization challenge endpoint can be found in the OpenAPI specification of jans-auth-server module . Sample request POST /authorize HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded login_hint=%2B1-310-123-4567&scope=profile &client_id=bb16c14c73415 Sample successful response with authorization_code . HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store { \"authorization_code\": \"uY29tL2F1dGhlbnRpY\" } Sample error response HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"username_required\" } Configuration Properties # Authorization Challenge Endpoint AS configuration: authorizationChallengeEndpoint - The authorization challenge endpoint URL authorizationChallengeDefaultAcr - Authorization Challenge Endpoint Default ACR if no value is specified in acr_values request parameter. Default value is default_challenge . authorizationChallengeShouldGenerateSession - Boolean value specifying whether to generate session_id (AS object and cookie) during authorization at Authorization Challenge Endpoint. Default value is false . mtlsAuthorizationChallengeEndpoint - URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Authorization Challenge Endpoint. Custom script # AS provides AuthorizationChallengeType custom script which must be used to control Authorization Challenge Endpoint behaviour. If request does not have acr_values specified and script name falls back to default_challenge which is available and enabled during installation. Default script name can be changed via authorizationChallengeDefaultAcr configuration property. Main method return true/false which indicates to server whether to issue authorization_code in response or not. If parameters is not present then error has to be created and false returned. If all is good script has to return true and it's strongly recommended to set user context.getExecutionContext().setUser(user); so AS can keep tracking what exactly user is authenticated. Please see following snippet below: public boolean authorize ( Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. validate all required parameters are present final String username = getParameterOrCreateError ( context , USERNAME_PARAMETER ); if ( StringUtils . isBlank ( username )) { return false ; } final String password = getParameterOrCreateError ( context , PASSWORD_PARAMETER ); if ( StringUtils . isBlank ( password )) { return false ; } scriptLogger . trace ( \"All required parameters are present\" ); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil . bean ( UserService . class ); PersistenceEntryManager entryManager = CdiUtil . bean ( PersistenceEntryManager . class ); final User user = userService . getUser ( username ); if ( user == null ) { scriptLogger . trace ( \"User is not found by username {}\" , username ); createError ( context , \"username_invalid\" ); return false ; } final boolean ok = entryManager . authenticate ( user . getDn (), User . class , password ); if ( ok ) { context . getExecutionContext (). setUser ( user ); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger . trace ( \"User {} is authenticated successfully.\" , username ); return true ; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger . trace ( \"Failed to authenticate user {}. Please check username and password.\" , username ); createError ( context , \"username_or_password_invalid\" ); return false ; } More details in Authorization Challenge Custom Script Page . Full sample script can be found here Auth session # Auth session is optional. AS does not return it by default. It's possible to pass in request use_auth_session=true which makes AS return it in error response. If it is desired to use auth_session and don't pass client_id (or other parameters) in next request, it should be put in attributes of auth_session object. auth_session object lifetime is set by authorizationChallengeSessionLifetimeInSeconds AS configuration property. If authorizationChallengeSessionLifetimeInSeconds is not set then value falls back to 86400 seconds. Example String clientId = context . getHttpRequest (). getParameter ( \"client_id\" ); authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"client_id\" , clientId ); AS automatically validates DPoP if it is set during auth session creation. Thus it's recommended to set jkt of the auth session if DPoP is used. final String dpop = context . getHttpRequest (). getHeader ( DpopService . DPOP ); if ( StringUtils . isNotBlank ( dpop )) { authorizationChallengeSessionObject . getAttributes (). setJkt ( getDpopJkt ( dpop )); } Full sample script can be found here Web session # Authorization challenge script is first-party flow and thus web session is not created by default. However there can be cases when such session has to be created. Please set authorizationChallengeShouldGenerateSession configuration property to true to force session creation. In case it is needed to prepare session with specific data, it is possible to create session in script and set it into context. Example: SessionIdService sessionIdService = CdiUtil . bean ( SessionIdService . class ); Identity identityService = CdiUtil . bean ( Identity . class ); Map < String , String > sessionStore = new HashMap < String , String > (); sessionStore . put ( \"login_id_token\" , login_id_token ); sessionStore . put ( \"login_access_token\" , login_access_token ); sessionStore . put ( \"transaction_status\" , \"PENDING\" ); SessionId sessionId = sessionIdService . generateAuthenticatedSessionId ( context . getHttpRequest (), user . getDn (), sessionStore ); context . getExecutionContext (). setAuthorizationChallengeSessionId ( sessionId ); scriptLogger . trace ( \"Created Authorization challenge session successfully\" ); Multi-step example # Sometimes it's required to send data sequentially. Step by step. Calls to Authorization Challenge Endpoint must have use_auth_session=true parameter to force tracking data between request. Lets consider example when RP first sends username and then in next request OTP . POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded username=alice &scope=photos &client_id=bb16c14c73415 AS accepts username and returns back error with auth_session . HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"otp_required\", \"auth_session\": \"ce6772f5e07bc8361572f\" } In next call RP can send OTP and auth_session (AS matches user from auth_session ) POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded otp=ccnnju667d&auth_session=ce6772f5e07bc8361572f In custom script it's easy to code what data has to be kept in auth_session . private void createError(ExternalScriptContext context, String errorCode) { String deviceSessionPart = prepareDeviceSessionSubJson(context); final String entity = String.format(\"{\\\"error\\\": \\\"%s\\\"%s}\", errorCode, deviceSessionPart); context.createWebApplicationException(401, entity); } private String prepareDeviceSessionSubJson(ExternalScriptContext context) { DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { prepareDeviceSession(context, authorizationChallengeSessionObject); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } else if (context.getAuthzRequest().isUseDeviceSession()) { authorizationChallengeSessionObject = prepareDeviceSession(context, null); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } return \"\"; } private DeviceSession prepareDeviceSession(ExternalScriptContext context, DeviceSession authorizationChallengeSessionObject) { DeviceSessionService deviceSessionService = CdiUtil.bean(DeviceSessionService.class); boolean newSave = authorizationChallengeSessionObject == null; if (newSave) { authorizationChallengeSessionObject = deviceSessionService.newDeviceSession(); } String username = context.getHttpRequest().getParameter(USERNAME_PARAMETER); if (StringUtils.isNotBlank(username)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(USERNAME_PARAMETER, username); } String otp = context.getHttpRequest().getParameter(OTP_PARAMETER); if (StringUtils.isNotBlank(otp)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(OTP_PARAMETER, otp); } String clientId = context.getHttpRequest().getParameter(\"client_id\"); if (StringUtils.isNotBlank(clientId)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"client_id\", clientId); } String acrValues = context.getHttpRequest().getParameter(\"acr_values\"); if (StringUtils.isNotBlank(acrValues)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"acr_values\", acrValues); } if (newSave) { deviceSessionService.persist(authorizationChallengeSessionObject); } else { deviceSessionService.merge(authorizationChallengeSessionObject); } return authorizationChallengeSessionObject; } More details in Authorization Challenge Custom Script Page . Full multi-step sample script can be found here Full successful Authorization Challenge Flow sample # OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 6244 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:04 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=fa097a44-5568-48aa-9390-1880616e5a69; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://yuriyz-fond-skink.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"phone_number_verified\", \"room_number\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"query\", \"jwt\", \"query.jwt\", \"form_post.jwt\", \"form_post\", \"fragment\", \"fragment.jwt\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code\", \"code id_token token\", \"id_token\", \"code id_token\", \"token\", \"id_token token\", \"code token\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:device_code\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"implicit\", \"authorization_code\", \"password\", \"refresh_token\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/userinfo\", \"authorization_challenge_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize-challenge\", \"op_tos_uri\" : \"https://yuriyz-fond-skink.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"key_from_java\" : \"value_from_script_on_java\", \"session_revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"user_name\", \"clientinfo\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"https://jans.io/scim/users.read\", \"device_sso\", \"phone\", \"mobile_phone\", \"offline_access\", \"email\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: authorizationChallengeFlow ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"jans test app\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1633 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:05 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=81dc6c45-7831-4738-b169-b087ee9a6bd6; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register?client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"28a50db3-b6d1-4054-a259-ef7168afa760\", \"client_id\": \"999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid\", \"client_secret\": \"f6364c5c-295d-4e6e-bb40-6ad3a47b2119\", \"client_id_issued_at\": 1691668385, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"jans test app\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"authorization_code\", \"refresh_token\" ], \"subject_type\": \"public\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1691704385, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea&scope=openid+profile+address+email+phone+user_name&state=b4a41b29-51c8-4354-9c8c-fda38b4dbd43&nonce=3a56f8d0-f78e-4b15-857c-3e792801be68&prompt=&ui_locales=&claims_locales=&acr_values=&request_session_id=false&password=secret&username=admin ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-transform, no-store Connection: Keep-Alive Content-Length: 61 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:06 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=3aa95eb7-73e2-40ae-9303-34adf30a1a05; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"authorization_code\":\"9e3dc65b-937a-49c2-bdff-41fbc1a352d0\"} Successfully obtained authorization code 9e3dc65b-937a-49c2-bdff-41fbc1a352d0 at Authorization Challenge Endpoint ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/x-www-form-urlencoded Authorization: Basic OTk5ZTEzYjgtZjRhMi00ZmVkLWFkM2MtNmM4OGJkMmM5MmVhOmY2MzY0YzVjLTI5NWQtNGU2ZS1iYjQwLTZhZDNhNDdiMjExOQ== grant_type=authorization_code&code=9e3dc65b-937a-49c2-bdff-41fbc1a352d0&redirect_uri=https%3A%2F%2Fyuriyz-fond-skink.gluu.info%2Fjans-auth-rp%2Fhome.htm ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1250 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:06 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=3eb3c205-6206-4a70-98fb-75bf81757976; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"access_token\":\"d87aa8d2-fefb-4d16-a775-9b9d27f73bfc\",\"refresh_token\":\"505314a7-05f5-4c9f-8900-ccb0685dea17\",\"id_token\":\"eyJraWQiOiJjb25uZWN0XzI1OGZmMmFiLWE4ODQtNDIxNy1iNmQ4LTJhMGI2NDhmOTcxZF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiUC04RktlejhlNHROTURTbVlGeHV5dyIsInN1YiI6IjI1Nzg0ZDQ5LTg0ZjMtNGIyNi1hZWUyLTEwNDkzMzM5MjMyZCIsImFtciI6W10sImlzcyI6Imh0dHBzOi8veXVyaXl6LWZvbmQtc2tpbmsuZ2x1dS5pbmZvIiwibm9uY2UiOiIzYTU2ZjhkMC1mNzhlLTRiMTUtODU3Yy0zZTc5MjgwMWJlNjgiLCJqYW5zT3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCIsImF1ZCI6Ijk5OWUxM2I4LWY0YTItNGZlZC1hZDNjLTZjODhiZDJjOTJlYSIsInJhbmRvbSI6ImJmYmI5OTBmLWNkYTEtNGM3OC1hNjM4LWFhN2NiMjc5MjU3MiIsImFjciI6ImRlZmF1bHRfY2hhbGxlbmdlIiwiY19oYXNoIjoiTnFoSGFIenZZYjYxeDFackQwUEZVdyIsImF1dGhfdGltZSI6MTY5MTY2ODM4NiwiZXhwIjoxNjkxNjcxOTg2LCJncmFudCI6ImF1dGhvcml6YXRpb25fY29kZSIsImlhdCI6MTY5MTY2ODM4Nn0.QTUmzJaHtbPGjrV4E0MUn_fU1On44B6-_7pT0Dz_cY29s_KajGLfin3G_WsYmZA--ysyRLAmdK_X5C3W-wpkpDJ8906vuZST5547lSJGOZ45_VFv7XnTmBip3zRQOmrlxdU6OQ5Vmj3xMON_NQ-ckEUSNr65xWTAPmOQoncGYp8s-TO7ethyx6UyDTnW8d1YiXWCUYfQDQ8d5wCPHnfoYAsZCs_f0xaBUmaiwvUL3ckiXgMr2yHjWKWQuezlbjJk7ODu2cgoAzs3IWMonaixIJeeJJcOvFB4SPTnbToJe7ISvvsZTEwrLWW_E_LgTUEDqHbeWyeQI8WqDa9EOwMEFw\",\"token_type\":\"Bearer\",\"expires_in\":299} ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/x-www-form-urlencoded Authorization: Basic OTk5ZTEzYjgtZjRhMi00ZmVkLWFkM2MtNmM4OGJkMmM5MmVhOmY2MzY0YzVjLTI5NWQtNGU2ZS1iYjQwLTZhZDNhNDdiMjExOQ== grant_type=refresh_token&refresh_token=505314a7-05f5-4c9f-8900-ccb0685dea17 ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store Connection: Keep-Alive Content-Length: 166 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:08 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=88a6b7a5-3230-4f0f-b859-09df77a5c67a; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"access_token\":\"572f6422-caf9-496a-a6be-4ab39c872816\",\"refresh_token\":\"e93b6576-5297-4d9d-a92b-3276d90a75e4\",\"scope\":\"openid\",\"token_type\":\"Bearer\",\"expires_in\":299} ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /jans-auth/restv1/userinfo HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Authorization: Bearer 572f6422-caf9-496a-a6be-4ab39c872816 ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store, private Connection: Keep-Alive Content-Length: 46 Content-Type: application/json;charset=utf-8 Date: Thu, 10 Aug 2023 11:53:08 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=390c7a63-fe06-48a5-b3bf-2549267ba9b0; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"sub\":\"25784d49-84f3-4b26-aee2-10493339232d\"} Authorization Challenge Flow sample with invalid user # OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 6244 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:01 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=79c5fed3-d69a-4fdf-af88-fce550cd1819; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://yuriyz-fond-skink.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"phone_number_verified\", \"room_number\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"query\", \"jwt\", \"query.jwt\", \"form_post.jwt\", \"form_post\", \"fragment\", \"fragment.jwt\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code\", \"code id_token token\", \"id_token\", \"code id_token\", \"token\", \"id_token token\", \"code token\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:device_code\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"implicit\", \"authorization_code\", \"password\", \"refresh_token\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/userinfo\", \"authorization_challenge_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize-challenge\", \"op_tos_uri\" : \"https://yuriyz-fond-skink.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"key_from_java\" : \"value_from_script_on_java\", \"session_revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"user_name\", \"clientinfo\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"https://jans.io/scim/users.read\", \"device_sso\", \"phone\", \"mobile_phone\", \"offline_access\", \"email\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: authorizationChallengeFlow ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"jans test app\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1633 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:02 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=7045173c-9a96-418a-86ed-47a09749b004; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register?client_id=d93a5129-1546-4b9b-bf8c-ea19e36ea2c8\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"67aa99de-e977-4562-955d-6292f2c95df4\", \"client_id\": \"d93a5129-1546-4b9b-bf8c-ea19e36ea2c8\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid\", \"client_secret\": \"f921c89c-57f0-4a91-baaa-036a4a22737b\", \"client_id_issued_at\": 1691668622, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"jans test app\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"authorization_code\", \"refresh_token\" ], \"subject_type\": \"public\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1691704622, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=d93a5129-1546-4b9b-bf8c-ea19e36ea2c8&scope=openid+profile+address+email+phone+user_name&state=4f925a8d-287a-4cba-a174-04d2e56109df&nonce=84c9b6dd-635c-4ca4-bba1-35c53c51a339&prompt=&ui_locales=&claims_locales=&acr_values=&request_session_id=false&password=secret&username=invalidUser ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 401 Cache-Control: no-transform, no-store Connection: Keep-Alive Content-Length: 29 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:02 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=4c89e007-6c77-43da-a67f-b7ee1ff0e60a; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"error\": \"username_invalid\"}", "title": "Authorization Challenge"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#overview", "text": "Authorization Challenge Endpoint allows first-party native client obtain authorization code which later can be exchanged on access token. This can provide an entirely browserless OAuth 2.0 experience suited for native applications. This endpoint conforms to OAuth 2.0 for First-Party Applications specifications. URL to access authorization challenge endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration authorization_challenge_endpoint claim in the response specifies the URL for authorization challenge endpoint. By default, authorization challenge endpoint looks like below: https://janssen.server.host/jans-auth/restv1/authorize-challenge In order to call Authorization Challenge Endpoint client must have authorization_challenge scope. If scope is not present AS rejects call with 401 (unauthorized) http status code. Authorization Challenge Endpoint supports Proof Key for Code Exchange (PKCE). More information about request and response of the authorization challenge endpoint can be found in the OpenAPI specification of jans-auth-server module . Sample request POST /authorize HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded login_hint=%2B1-310-123-4567&scope=profile &client_id=bb16c14c73415 Sample successful response with authorization_code . HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store { \"authorization_code\": \"uY29tL2F1dGhlbnRpY\" } Sample error response HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"username_required\" }", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#configuration-properties", "text": "Authorization Challenge Endpoint AS configuration: authorizationChallengeEndpoint - The authorization challenge endpoint URL authorizationChallengeDefaultAcr - Authorization Challenge Endpoint Default ACR if no value is specified in acr_values request parameter. Default value is default_challenge . authorizationChallengeShouldGenerateSession - Boolean value specifying whether to generate session_id (AS object and cookie) during authorization at Authorization Challenge Endpoint. Default value is false . mtlsAuthorizationChallengeEndpoint - URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Authorization Challenge Endpoint.", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#custom-script", "text": "AS provides AuthorizationChallengeType custom script which must be used to control Authorization Challenge Endpoint behaviour. If request does not have acr_values specified and script name falls back to default_challenge which is available and enabled during installation. Default script name can be changed via authorizationChallengeDefaultAcr configuration property. Main method return true/false which indicates to server whether to issue authorization_code in response or not. If parameters is not present then error has to be created and false returned. If all is good script has to return true and it's strongly recommended to set user context.getExecutionContext().setUser(user); so AS can keep tracking what exactly user is authenticated. Please see following snippet below: public boolean authorize ( Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. validate all required parameters are present final String username = getParameterOrCreateError ( context , USERNAME_PARAMETER ); if ( StringUtils . isBlank ( username )) { return false ; } final String password = getParameterOrCreateError ( context , PASSWORD_PARAMETER ); if ( StringUtils . isBlank ( password )) { return false ; } scriptLogger . trace ( \"All required parameters are present\" ); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil . bean ( UserService . class ); PersistenceEntryManager entryManager = CdiUtil . bean ( PersistenceEntryManager . class ); final User user = userService . getUser ( username ); if ( user == null ) { scriptLogger . trace ( \"User is not found by username {}\" , username ); createError ( context , \"username_invalid\" ); return false ; } final boolean ok = entryManager . authenticate ( user . getDn (), User . class , password ); if ( ok ) { context . getExecutionContext (). setUser ( user ); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger . trace ( \"User {} is authenticated successfully.\" , username ); return true ; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger . trace ( \"Failed to authenticate user {}. Please check username and password.\" , username ); createError ( context , \"username_or_password_invalid\" ); return false ; } More details in Authorization Challenge Custom Script Page . Full sample script can be found here", "title": "Custom script"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#auth-session", "text": "Auth session is optional. AS does not return it by default. It's possible to pass in request use_auth_session=true which makes AS return it in error response. If it is desired to use auth_session and don't pass client_id (or other parameters) in next request, it should be put in attributes of auth_session object. auth_session object lifetime is set by authorizationChallengeSessionLifetimeInSeconds AS configuration property. If authorizationChallengeSessionLifetimeInSeconds is not set then value falls back to 86400 seconds. Example String clientId = context . getHttpRequest (). getParameter ( \"client_id\" ); authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"client_id\" , clientId ); AS automatically validates DPoP if it is set during auth session creation. Thus it's recommended to set jkt of the auth session if DPoP is used. final String dpop = context . getHttpRequest (). getHeader ( DpopService . DPOP ); if ( StringUtils . isNotBlank ( dpop )) { authorizationChallengeSessionObject . getAttributes (). setJkt ( getDpopJkt ( dpop )); } Full sample script can be found here", "title": "Auth session"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#web-session", "text": "Authorization challenge script is first-party flow and thus web session is not created by default. However there can be cases when such session has to be created. Please set authorizationChallengeShouldGenerateSession configuration property to true to force session creation. In case it is needed to prepare session with specific data, it is possible to create session in script and set it into context. Example: SessionIdService sessionIdService = CdiUtil . bean ( SessionIdService . class ); Identity identityService = CdiUtil . bean ( Identity . class ); Map < String , String > sessionStore = new HashMap < String , String > (); sessionStore . put ( \"login_id_token\" , login_id_token ); sessionStore . put ( \"login_access_token\" , login_access_token ); sessionStore . put ( \"transaction_status\" , \"PENDING\" ); SessionId sessionId = sessionIdService . generateAuthenticatedSessionId ( context . getHttpRequest (), user . getDn (), sessionStore ); context . getExecutionContext (). setAuthorizationChallengeSessionId ( sessionId ); scriptLogger . trace ( \"Created Authorization challenge session successfully\" );", "title": "Web session"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#multi-step-example", "text": "Sometimes it's required to send data sequentially. Step by step. Calls to Authorization Challenge Endpoint must have use_auth_session=true parameter to force tracking data between request. Lets consider example when RP first sends username and then in next request OTP . POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded username=alice &scope=photos &client_id=bb16c14c73415 AS accepts username and returns back error with auth_session . HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { \"error\": \"otp_required\", \"auth_session\": \"ce6772f5e07bc8361572f\" } In next call RP can send OTP and auth_session (AS matches user from auth_session ) POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded otp=ccnnju667d&auth_session=ce6772f5e07bc8361572f In custom script it's easy to code what data has to be kept in auth_session . private void createError(ExternalScriptContext context, String errorCode) { String deviceSessionPart = prepareDeviceSessionSubJson(context); final String entity = String.format(\"{\\\"error\\\": \\\"%s\\\"%s}\", errorCode, deviceSessionPart); context.createWebApplicationException(401, entity); } private String prepareDeviceSessionSubJson(ExternalScriptContext context) { DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { prepareDeviceSession(context, authorizationChallengeSessionObject); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } else if (context.getAuthzRequest().isUseDeviceSession()) { authorizationChallengeSessionObject = prepareDeviceSession(context, null); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } return \"\"; } private DeviceSession prepareDeviceSession(ExternalScriptContext context, DeviceSession authorizationChallengeSessionObject) { DeviceSessionService deviceSessionService = CdiUtil.bean(DeviceSessionService.class); boolean newSave = authorizationChallengeSessionObject == null; if (newSave) { authorizationChallengeSessionObject = deviceSessionService.newDeviceSession(); } String username = context.getHttpRequest().getParameter(USERNAME_PARAMETER); if (StringUtils.isNotBlank(username)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(USERNAME_PARAMETER, username); } String otp = context.getHttpRequest().getParameter(OTP_PARAMETER); if (StringUtils.isNotBlank(otp)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(OTP_PARAMETER, otp); } String clientId = context.getHttpRequest().getParameter(\"client_id\"); if (StringUtils.isNotBlank(clientId)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"client_id\", clientId); } String acrValues = context.getHttpRequest().getParameter(\"acr_values\"); if (StringUtils.isNotBlank(acrValues)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"acr_values\", acrValues); } if (newSave) { deviceSessionService.persist(authorizationChallengeSessionObject); } else { deviceSessionService.merge(authorizationChallengeSessionObject); } return authorizationChallengeSessionObject; } More details in Authorization Challenge Custom Script Page . Full multi-step sample script can be found here", "title": "Multi-step example"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#full-successful-authorization-challenge-flow-sample", "text": "OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 6244 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:04 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=fa097a44-5568-48aa-9390-1880616e5a69; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://yuriyz-fond-skink.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"phone_number_verified\", \"room_number\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"query\", \"jwt\", \"query.jwt\", \"form_post.jwt\", \"form_post\", \"fragment\", \"fragment.jwt\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code\", \"code id_token token\", \"id_token\", \"code id_token\", \"token\", \"id_token token\", \"code token\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:device_code\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"implicit\", \"authorization_code\", \"password\", \"refresh_token\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/userinfo\", \"authorization_challenge_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize-challenge\", \"op_tos_uri\" : \"https://yuriyz-fond-skink.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"key_from_java\" : \"value_from_script_on_java\", \"session_revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"user_name\", \"clientinfo\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"https://jans.io/scim/users.read\", \"device_sso\", \"phone\", \"mobile_phone\", \"offline_access\", \"email\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: authorizationChallengeFlow ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"jans test app\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1633 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:05 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=81dc6c45-7831-4738-b169-b087ee9a6bd6; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register?client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"28a50db3-b6d1-4054-a259-ef7168afa760\", \"client_id\": \"999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid\", \"client_secret\": \"f6364c5c-295d-4e6e-bb40-6ad3a47b2119\", \"client_id_issued_at\": 1691668385, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"jans test app\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"authorization_code\", \"refresh_token\" ], \"subject_type\": \"public\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1691704385, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea&scope=openid+profile+address+email+phone+user_name&state=b4a41b29-51c8-4354-9c8c-fda38b4dbd43&nonce=3a56f8d0-f78e-4b15-857c-3e792801be68&prompt=&ui_locales=&claims_locales=&acr_values=&request_session_id=false&password=secret&username=admin ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-transform, no-store Connection: Keep-Alive Content-Length: 61 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:06 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=3aa95eb7-73e2-40ae-9303-34adf30a1a05; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"authorization_code\":\"9e3dc65b-937a-49c2-bdff-41fbc1a352d0\"} Successfully obtained authorization code 9e3dc65b-937a-49c2-bdff-41fbc1a352d0 at Authorization Challenge Endpoint ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/x-www-form-urlencoded Authorization: Basic OTk5ZTEzYjgtZjRhMi00ZmVkLWFkM2MtNmM4OGJkMmM5MmVhOmY2MzY0YzVjLTI5NWQtNGU2ZS1iYjQwLTZhZDNhNDdiMjExOQ== grant_type=authorization_code&code=9e3dc65b-937a-49c2-bdff-41fbc1a352d0&redirect_uri=https%3A%2F%2Fyuriyz-fond-skink.gluu.info%2Fjans-auth-rp%2Fhome.htm ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1250 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:06 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=3eb3c205-6206-4a70-98fb-75bf81757976; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"access_token\":\"d87aa8d2-fefb-4d16-a775-9b9d27f73bfc\",\"refresh_token\":\"505314a7-05f5-4c9f-8900-ccb0685dea17\",\"id_token\":\"eyJraWQiOiJjb25uZWN0XzI1OGZmMmFiLWE4ODQtNDIxNy1iNmQ4LTJhMGI2NDhmOTcxZF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiUC04RktlejhlNHROTURTbVlGeHV5dyIsInN1YiI6IjI1Nzg0ZDQ5LTg0ZjMtNGIyNi1hZWUyLTEwNDkzMzM5MjMyZCIsImFtciI6W10sImlzcyI6Imh0dHBzOi8veXVyaXl6LWZvbmQtc2tpbmsuZ2x1dS5pbmZvIiwibm9uY2UiOiIzYTU2ZjhkMC1mNzhlLTRiMTUtODU3Yy0zZTc5MjgwMWJlNjgiLCJqYW5zT3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCIsImF1ZCI6Ijk5OWUxM2I4LWY0YTItNGZlZC1hZDNjLTZjODhiZDJjOTJlYSIsInJhbmRvbSI6ImJmYmI5OTBmLWNkYTEtNGM3OC1hNjM4LWFhN2NiMjc5MjU3MiIsImFjciI6ImRlZmF1bHRfY2hhbGxlbmdlIiwiY19oYXNoIjoiTnFoSGFIenZZYjYxeDFackQwUEZVdyIsImF1dGhfdGltZSI6MTY5MTY2ODM4NiwiZXhwIjoxNjkxNjcxOTg2LCJncmFudCI6ImF1dGhvcml6YXRpb25fY29kZSIsImlhdCI6MTY5MTY2ODM4Nn0.QTUmzJaHtbPGjrV4E0MUn_fU1On44B6-_7pT0Dz_cY29s_KajGLfin3G_WsYmZA--ysyRLAmdK_X5C3W-wpkpDJ8906vuZST5547lSJGOZ45_VFv7XnTmBip3zRQOmrlxdU6OQ5Vmj3xMON_NQ-ckEUSNr65xWTAPmOQoncGYp8s-TO7ethyx6UyDTnW8d1YiXWCUYfQDQ8d5wCPHnfoYAsZCs_f0xaBUmaiwvUL3ckiXgMr2yHjWKWQuezlbjJk7ODu2cgoAzs3IWMonaixIJeeJJcOvFB4SPTnbToJe7ISvvsZTEwrLWW_E_LgTUEDqHbeWyeQI8WqDa9EOwMEFw\",\"token_type\":\"Bearer\",\"expires_in\":299} ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/x-www-form-urlencoded Authorization: Basic OTk5ZTEzYjgtZjRhMi00ZmVkLWFkM2MtNmM4OGJkMmM5MmVhOmY2MzY0YzVjLTI5NWQtNGU2ZS1iYjQwLTZhZDNhNDdiMjExOQ== grant_type=refresh_token&refresh_token=505314a7-05f5-4c9f-8900-ccb0685dea17 ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store Connection: Keep-Alive Content-Length: 166 Content-Type: application/json Date: Thu, 10 Aug 2023 11:53:08 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=88a6b7a5-3230-4f0f-b859-09df77a5c67a; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"access_token\":\"572f6422-caf9-496a-a6be-4ab39c872816\",\"refresh_token\":\"e93b6576-5297-4d9d-a92b-3276d90a75e4\",\"scope\":\"openid\",\"token_type\":\"Bearer\",\"expires_in\":299} ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /jans-auth/restv1/userinfo HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Authorization: Bearer 572f6422-caf9-496a-a6be-4ab39c872816 ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Cache-Control: no-store, private Connection: Keep-Alive Content-Length: 46 Content-Type: application/json;charset=utf-8 Date: Thu, 10 Aug 2023 11:53:08 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=390c7a63-fe06-48a5-b3bf-2549267ba9b0; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"sub\":\"25784d49-84f3-4b26-aee2-10493339232d\"}", "title": "Full successful Authorization Challenge Flow sample"}, {"location": "janssen-server/auth-server/endpoints/authorization-challenge/#authorization-challenge-flow-sample-with-invalid-user", "text": "OpenID Connect Configuration ------------------------------------------------------- REQUEST: ------------------------------------------------------- GET /.well-known/openid-configuration HTTP/1.1 HTTP/1.1 Host: yuriyz-fond-skink.gluu.info ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 200 Connection: Keep-Alive Content-Length: 6244 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:01 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=79c5fed3-d69a-4fdf-af88-fce550cd1819; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://yuriyz-fond-skink.gluu.info\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"formatted\", \"user_name\", \"phone_mobile_number\", \"preferred_username\", \"locale\", \"inum\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"phone_number_verified\", \"room_number\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"ssa_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/ssa\", \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"query\", \"jwt\", \"query.jwt\", \"form_post.jwt\", \"form_post\", \"fragment\", \"fragment.jwt\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/token\", \"response_types_supported\" : [ \"code\", \"code id_token token\", \"id_token\", \"code id_token\", \"token\", \"id_token token\", \"code token\" ], \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"client_credentials\", \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"urn:ietf:params:oauth:grant-type:device_code\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"implicit\", \"authorization_code\", \"password\", \"refresh_token\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/userinfo\", \"authorization_challenge_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/authorize-challenge\", \"op_tos_uri\" : \"https://yuriyz-fond-skink.gluu.info/tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"key_from_java\" : \"value_from_script_on_java\", \"session_revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke_session\", \"check_session_iframe\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"address\", \"introspection\", \"https://jans.io/auth/ssa.admin\", \"online_access\", \"openid\", \"user_name\", \"clientinfo\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/users.write\", \"revoke_session\", \"https://jans.io/scim/users.read\", \"device_sso\", \"phone\", \"mobile_phone\", \"offline_access\", \"email\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"device_authorization_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/device_authorization\", \"display_values_supported\" : [ \"page\", \"popup\" ], \"userinfo_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"require_pushed_authorization_requests\" : false, \"claim_types_supported\" : [ \"normal\" ], \"userinfo_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"end_session_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/end_session\", \"revocation_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/revoke\", \"backchannel_authentication_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/bc-authorize\", \"token_endpoint_auth_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"frontchannel_logout_supported\" : true, \"jwks_uri\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/jwks\", \"subject_types_supported\" : [ \"public\", \"pairwise\" ], \"id_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"registration_endpoint\" : \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register\", \"id_token_token_binding_cnf_values_supported\" : [ \"tbh\" ] } ####################################################### TEST: authorizationChallengeFlow ####################################################### ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/register HTTP/1.1 Host: yuriyz-fond-skink.gluu.info Content-Type: application/json Accept: application/json { \"grant_types\" : [ \"authorization_code\", \"refresh_token\" ], \"subject_type\" : \"public\", \"application_type\" : \"web\", \"scope\" : \"openid profile address email phone user_name\", \"minimum_acr_priority_list\" : [ ], \"redirect_uris\" : [ \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\" ], \"client_name\" : \"jans test app\", \"additional_audience\" : [ ], \"response_types\" : [ \"code\", \"id_token\" ] } ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 201 Cache-Control: no-store Connection: Keep-Alive Content-Length: 1633 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:02 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Pragma: no-cache Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=7045173c-9a96-418a-86ed-47a09749b004; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://yuriyz-fond-skink.gluu.info/jans-auth/restv1/register?client_id=d93a5129-1546-4b9b-bf8c-ea19e36ea2c8\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"67aa99de-e977-4562-955d-6292f2c95df4\", \"client_id\": \"d93a5129-1546-4b9b-bf8c-ea19e36ea2c8\", \"token_endpoint_auth_method\": \"client_secret_basic\", \"scope\": \"openid\", \"client_secret\": \"f921c89c-57f0-4a91-baaa-036a4a22737b\", \"client_id_issued_at\": 1691668622, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"jans test app\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"authorization_code\", \"refresh_token\" ], \"subject_type\": \"public\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://client.example.com/cb2\", \"https://client.example.com/cb1\", \"https://client.example.com/cb\", \"https://yuriyz-fond-skink.gluu.info/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1691704622, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"id_token\" ] } ------------------------------------------------------- REQUEST: ------------------------------------------------------- POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=d93a5129-1546-4b9b-bf8c-ea19e36ea2c8&scope=openid+profile+address+email+phone+user_name&state=4f925a8d-287a-4cba-a174-04d2e56109df&nonce=84c9b6dd-635c-4ca4-bba1-35c53c51a339&prompt=&ui_locales=&claims_locales=&acr_values=&request_session_id=false&password=secret&username=invalidUser ------------------------------------------------------- RESPONSE: ------------------------------------------------------- HTTP/1.1 401 Cache-Control: no-transform, no-store Connection: Keep-Alive Content-Length: 29 Content-Type: application/json Date: Thu, 10 Aug 2023 11:57:02 GMT Expires: Thu, 01 Jan 1970 00:00:00 GMT Keep-Alive: timeout=5, max=100 Server: Apache/2.4.41 (Ubuntu) Set-Cookie: X-Correlation-Id=4c89e007-6c77-43da-a67f-b7ee1ff0e60a; Secure; HttpOnly;HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Xss-Protection: 1; mode=block {\"error\": \"username_invalid\"}", "title": "Authorization Challenge Flow sample with invalid user"}, {"location": "janssen-server/auth-server/endpoints/authorization/", "tags": ["administration", "auth-server", "authorization", "endpoint"], "text": "Overview # Janssen Server exposes authorization endpoint compliant with OAuth2 framework . A client uses authorization endpoint to obtain an authorization grant. Based on response type requested by the client, the authorization endpoint issues an authorization code or an access token. Authorization endpoint is a protected endpoint which will require end-user authentication before issuing authorization code or access token. URL to access authorization endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration authorization_endpoint claim in the response specifies the URL for authorization endpoint. By default, authorization endpoint looks like below: https://janssen.server.host/jans-auth/restv1/authorize More information about request and response of the authorization endpoint can be found in the OpenAPI specification of jans-auth-server module . Configuration Properties # Authorization endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . issuer requirePkce fapiCompatibility forceSignedRequestObject authorizationCodeLifetime returnDeviceSecretFromAuthzEndpoint requestUriBlockList requireRequestObjectEncryption staticDecryptionKid requestUriHashVerificationEnabled legacyIdTokenClaims customHeadersWithAuthorizationResponse includeSidInResponse sessionIdRequestParameterEnabled returnDeviceSecretFromAuthzEndpoint requirePar cibaMaxExpirationTimeAllowedSec Required Client Configuration # Clients must be registered with Janssen Server as using code and/or implicit grant types in order to use authorization endpoint. Using Janssen Text-based UI(TUI) , client can be registered for appropriate grant type by navigating to Auth-Server -> Clients -> Add Client Using PKCE # Janssen Server supports PKCE , which recommended and more secure method for using code grant. PKCE can be enabled/disable by setting requirePkce property. Janssen server supports plain as well as s256 code challenge methods. Using PAR # As a separate endpoint, Janssen Server supports PAR (Pushed Authorization Requests) to enable authorization using more complex authorization requests and making it more secure at the same time. Use Janssen Server configuration property requirePar to accept only PAR requests. Using JARM # Authorization endpoint supports JWT Secured Authorization Response Mode, or JARM . Using JARM makes authorization responses more secure and compliant to be used in FAPI deployments. Janssen Server supports all response modes as defined in JARM specification Using Prompt Parameter # prompt request parameter is an ASCII string value that specifies whether the Authorization Server prompts the End-User for re-authentication and consent. Janssen Server supports none , login , consent , create and select_account values for prompt parameter. Multiple values can be specified by separating them with single space. Based on value/s of this request parameter Authorization Server prompts the End-User for re-authentication ( login ), consent or user registration details ( create ). Check Prompt page for more details. none # none value will instruct Janssen Server NOT to display any authentication or consent user interface pages. An error is returned if the End-User is not already authenticated or the Client does not have pre-configured consent for the requested scopes. This can be used as a method to check for existing authentication and/or consent. login # login value will instruct Janssen Server to prompt the End-User for re-authentication. consent # consent value will instruct Janssen Server to prompt the End-User for consent before returning information to the Client. select_account # select_account value will instruct Janssen Server to prompt the End-User to select a user account. This allows a user who has multiple accounts at the Authorization Server to select amongst the multiple accounts that they may have current sessions for. Configuring Authentication Methods # acr_values request parameter is used to specify authentication methods to be used by Janssen Server to authenticate the end user. Multiple acr values can be specified by separating them with a space. In order to use a particular acr value, the client needs to be authorized to use all the acr values in the list. If no the request doesn't specify any acr value then the default acr value configured for respective client is used by Janssen server for end user authentication. Customizing using Interception Scripts # Interception scripts allows flexibility to configure and customize multiple aspects in Janssen Server. For example, see this documentation to learn how person authentication and consent gathering can be customized using interception scripts. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Authorization"}, {"location": "janssen-server/auth-server/endpoints/authorization/#overview", "text": "Janssen Server exposes authorization endpoint compliant with OAuth2 framework . A client uses authorization endpoint to obtain an authorization grant. Based on response type requested by the client, the authorization endpoint issues an authorization code or an access token. Authorization endpoint is a protected endpoint which will require end-user authentication before issuing authorization code or access token. URL to access authorization endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration authorization_endpoint claim in the response specifies the URL for authorization endpoint. By default, authorization endpoint looks like below: https://janssen.server.host/jans-auth/restv1/authorize More information about request and response of the authorization endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/authorization/#configuration-properties", "text": "Authorization endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . issuer requirePkce fapiCompatibility forceSignedRequestObject authorizationCodeLifetime returnDeviceSecretFromAuthzEndpoint requestUriBlockList requireRequestObjectEncryption staticDecryptionKid requestUriHashVerificationEnabled legacyIdTokenClaims customHeadersWithAuthorizationResponse includeSidInResponse sessionIdRequestParameterEnabled returnDeviceSecretFromAuthzEndpoint requirePar cibaMaxExpirationTimeAllowedSec", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/authorization/#required-client-configuration", "text": "Clients must be registered with Janssen Server as using code and/or implicit grant types in order to use authorization endpoint. Using Janssen Text-based UI(TUI) , client can be registered for appropriate grant type by navigating to Auth-Server -> Clients -> Add Client", "title": "Required Client Configuration"}, {"location": "janssen-server/auth-server/endpoints/authorization/#using-pkce", "text": "Janssen Server supports PKCE , which recommended and more secure method for using code grant. PKCE can be enabled/disable by setting requirePkce property. Janssen server supports plain as well as s256 code challenge methods.", "title": "Using PKCE"}, {"location": "janssen-server/auth-server/endpoints/authorization/#using-par", "text": "As a separate endpoint, Janssen Server supports PAR (Pushed Authorization Requests) to enable authorization using more complex authorization requests and making it more secure at the same time. Use Janssen Server configuration property requirePar to accept only PAR requests.", "title": "Using PAR"}, {"location": "janssen-server/auth-server/endpoints/authorization/#using-jarm", "text": "Authorization endpoint supports JWT Secured Authorization Response Mode, or JARM . Using JARM makes authorization responses more secure and compliant to be used in FAPI deployments. Janssen Server supports all response modes as defined in JARM specification", "title": "Using JARM"}, {"location": "janssen-server/auth-server/endpoints/authorization/#using-prompt-parameter", "text": "prompt request parameter is an ASCII string value that specifies whether the Authorization Server prompts the End-User for re-authentication and consent. Janssen Server supports none , login , consent , create and select_account values for prompt parameter. Multiple values can be specified by separating them with single space. Based on value/s of this request parameter Authorization Server prompts the End-User for re-authentication ( login ), consent or user registration details ( create ). Check Prompt page for more details.", "title": "Using Prompt Parameter"}, {"location": "janssen-server/auth-server/endpoints/authorization/#none", "text": "none value will instruct Janssen Server NOT to display any authentication or consent user interface pages. An error is returned if the End-User is not already authenticated or the Client does not have pre-configured consent for the requested scopes. This can be used as a method to check for existing authentication and/or consent.", "title": "none"}, {"location": "janssen-server/auth-server/endpoints/authorization/#login", "text": "login value will instruct Janssen Server to prompt the End-User for re-authentication.", "title": "login"}, {"location": "janssen-server/auth-server/endpoints/authorization/#consent", "text": "consent value will instruct Janssen Server to prompt the End-User for consent before returning information to the Client.", "title": "consent"}, {"location": "janssen-server/auth-server/endpoints/authorization/#select_account", "text": "select_account value will instruct Janssen Server to prompt the End-User to select a user account. This allows a user who has multiple accounts at the Authorization Server to select amongst the multiple accounts that they may have current sessions for.", "title": "select_account"}, {"location": "janssen-server/auth-server/endpoints/authorization/#configuring-authentication-methods", "text": "acr_values request parameter is used to specify authentication methods to be used by Janssen Server to authenticate the end user. Multiple acr values can be specified by separating them with a space. In order to use a particular acr value, the client needs to be authorized to use all the acr values in the list. If no the request doesn't specify any acr value then the default acr value configured for respective client is used by Janssen server for end user authentication.", "title": "Configuring Authentication Methods"}, {"location": "janssen-server/auth-server/endpoints/authorization/#customizing-using-interception-scripts", "text": "Interception scripts allows flexibility to configure and customize multiple aspects in Janssen Server. For example, see this documentation to learn how person authentication and consent gathering can be customized using interception scripts.", "title": "Customizing using Interception Scripts"}, {"location": "janssen-server/auth-server/endpoints/authorization/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/", "tags": ["administration", "auth-server", "endpoint"], "text": "Backchannel authentication scripts # Janssen server enables domains to render the username/pw login form, avoiding the redirect to the IDP-hosted login page. Many SSO solutions offer a proprietary endpoint to accomplish this. However, in Janssen server, this is accomplished with the OAuth/OpenID framework by using a combination of calling the /token endpoint using the OAuth password flow, and then redirecting to browser to the /authorization endpoint, but auto-submitting the form. This article describes how to process login via backchannel and when browser is processing authorization, AS will recognize automatically the authenticated user, write cookies and then establish the session. Design # Source-code for sequence diagram Title password Grant with State Person->Browser: Navigate to website Browser->Website: Website->Browser:Display login page Person->Browser: Enter Username / PW Browser->Website: (creds) Website->IDP: /token?uid=_&pw=&browser_ip=_ IDP->Website: {\"redirect\": \"/authz/state=1F2D41A\", ...} Website->Browser: Browser->IDP: /authz?state=1F2D41A IDP->IDP: check IP address is\\n same as state IDP->Browser: write cookie / send redirect_uri Browser->Website: redirect_uri Solution # In order to process the whole authorization, idea is to use resource owner password credentials grant type in the first stage, over there process the authentication as we do today, but also write in cache a short-lived token to recognize such authenticated user, then return to the client such short-lived token. During authorization, browser should send that token as part of the custom params and in the AS we should verify if that user is already authenticated using the short-lived param in the cache, then AS will write cookies, create the session and return to the client information required for this. Jans App Configurations # Above the jans-auth record of the jansAppConf table, enable a new attribute on the jansConfDyn field Example: \"authorizationRequestCustomAllowedParameters\": [ { \"paramName\": \"bcAuthnToken\", \"returnInResponse\": true } ] Sample CURL 1. Obtain access token curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/jans-auth-server/config/properties.write\" 2. Apply patch curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"authorizationRequestCustomAllowedParameters\", \"value\": [ { \"paramName\": \"bcAuthnToken\", \"returnInResponse\": true } ] } ]' Custom Script Registration # In the table jansCustomScr enable 2 new scripts: 1. Script type resource_owner_password_credentials displayName ropc-backchannel [ropc-backchannel-script.py] See script below. 2. Script type person_autentication displayName backchannel-authentication [backchannel-authentication-script.py] See script below. Client Configuration # Associate script person_authentication on table jansClnt . Modify the jansAttrs field which contains a json and the ropcScripts field and add the dn from the ropc script record in the previous step Example: \"ropcScripts\": [ \"inum={SCRIPT_ID},ou=scripts,o=jans\", ], Flow # BcAuthToken request: # Firstly, the /token service is called to generate the bcAuthnToken (get it from the response header with the key Bc-Authn-Token ) In this request example, the client's basic credential is being used in order to authenticate the client, however you could use your preferred authn mode. Request curl --location --request POST 'https://jans.localhost/jans-auth/restv1/token' \\ --header 'Authorization: Basic MzE3MGNiYzUtMDAxOC00OWVmLThiYTYtMjY4MGI2NjhiZjBjOmFmNzk1ZjI1LWQ1MjktNDVlYi1iMTJlLWNjM2ExNTY5OTU1Ng==' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=password' \\ --data-urlencode 'username=test_user' \\ --data-urlencode 'password=test_user_password' \\ --data-urlencode 'custom1=your custom param 1' \\ --data-urlencode 'custom2=your custom param 2' \\ --data-urlencode 'scope=openid' Response HTTP/1.1 200 OK Date: Wed, 29 Jun 2022 14:03:25 GMT Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Bc-Authn-Token: dacfe4fc-d0ce-4673-9370-e66f652c4b7f Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1109 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive {\"access_token\":\"7a024a59-e132-4c05-9126-f4f36b3d3677\",\"refresh_token\":\"184c2b60-b5c7-4250-9850-97b0f531743c\",\"scope\":\"openid\",\"id_token\":\"eyJraWQiOiJmZGJhY2Q2Yi05YTY0LTQ2MWQtOWJlYy1jOTAyMjc5ZGI2ODZfc2lnX3JzMjU2IiwidHlwIjoiand0IiwiYWxnIjoiUlMyNTYifQ.eyJhdWQiOiIzMTcwY2JjNS0wMDE4LTQ5ZWYtOGJhNi0yNjgwYjY2OGJmMGMiLCJhY3IiOiJzaW1wbGVfcGFzc3dvcmRfYXV0aCIsInN1YiI6Il9Fa3p5aXlRdVBzUm1mYjh3WHlmTTB4U0xDckxwTDJGNnA3RWhEeWRBUHciLCJjb2RlIjoiNDY4MzQ2NjktOGQ1Yy00NmQxLTkwNWEtNmMzNDg3YzZlMDg3IiwiYW1yIjpbXSwiaXNzIjoiaHR0cHM6Ly9qYW5zLmxvY2FsaG9zdCIsImV4cCI6MTY1NjUxNTAwNiwiZ3JhbnQiOiJwYXNzd29yZCIsImlhdCI6MTY1NjUxMTQwNiwic2lkIjoiMTg0ZTllOTktNjFmNi00ZWNhLWE0ZmUtMTMwZmFmZDk1MjE1Iiwib3hPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIn0.hW0vReGYLzC2RyBHztSFbDYoaYHcCYxatX1lpzWqyW5U2S9eNp58mKKmvdZmMc229Sz5VxqfYflpWuI_6aXsLFR_KT9FY3exSRIRtPiD_fUETdhsVuKWavumVnjvwdAM6ytu5ORJx06DCxEgaG1uXmRiE9GoT8F1uqeo4NxURhVNXmMd2fiiUmgm1lt3-kNhlSg6vMDJS1Aq1idm-XhiSVy895BY-JdpLEGJEycPKr1lpsBTcmasbFNBJv6_orKWlvvgFCVxo7XmbH7Xnmqi6UUo30L6sULqmCsTLa6DaWYfGokHz_0xRflw_Ihv9wlVq8gSdOZGoMaVGzDdKlddZw\",\"token_type\":\"Bearer\",\"expires_in\":299} Authorize request: # Once you have gotten the bcAuthnToken from the previous /token call, you must call authorize attaching the bcAuthnToken as a parameter and in the acr_values param send the name of the backchannel-authentication registered in previous steps. This script will generate cookies and session associated with the browser if the BcAuthToken is valid. Example: https://jans.localhost/jans-auth/restv1/authorize?response_type=code&client_id=3170cbc5-0018-49ef-8ba6-2680b668bf0c&scope=openid+profile+address+email&redirect_uri=https://jans.localhost/jans-auth-rp/home.htm&state=2f78eaf1-d73e-49f2-8f50-e5faef80808a&nonce=92c3a631-db54-4ae9-bd53-caf92a4adbcf&prompt=&ui_locales=&claims_locales=&acr_values=backchannel-authentication&request_session_id=false&bcAuthnToken={your bcAuthnToken} This call will redirect to the redirect_uri that you sent as a parameter in the call and will receive a code as well, after that the process is more or less the same than the regular flow. Request /token: # With the code obtained previously, you must call /token again, adding the parameter code Request: curl --location --request POST 'https://jans.localhost/jans-auth/restv1/token' \\ --header 'Authorization: Basic MzlhNjlmYzAtNzNmYy00MWJhLWFiMGYtNDJhNWFmYWI2MjllOmJmMDRlZTM4LTM0MTktNGEzNS05YTI5LTcyODlmY2JkNzc2Zg==' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=authorization_code' \\ --data-urlencode 'code=d449a7b9-10f6-4320-b257-05fee91d3c16' \\ --data-urlencode 'redirect_uri=https://jans.localhost/jans-auth-rp/home.htm' Response: HTTP/1.1 200 OK Date: Wed, 29 Jun 2022 15:20:50 GMT Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1291 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive {\"access_token\":\"896b04a2-fcbe-4466-89b9-184930b8675b\",\"refresh_token\":\"843995ef-cd0e-4b2c-9b91-7c68081325ab\",\"id_token\":\"eyJraWQiOiJmZGJhY2Q2Yi05YTY0LTQ2MWQtOWJlYy1jOTAyMjc5ZGI2ODZfc2lnX3JzMjU2IiwidHlwIjoiand0IiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoiMmx5OXh5emthMmc2T09HcVRPTmhqdyIsInN1YiI6Il9Fa3p5aXlRdVBzUm1mYjh3WHlmTTB4U0xDckxwTDJGNnA3RWhEeWRBUHciLCJjb2RlIjoiMjdiNjM0NTItMTE1My00ZDk5LTlkYzQtYzMyNGRmNjIwYWE0IiwiYW1yIjpbIjEwIl0sImlzcyI6Imh0dHBzOi8vamFucy5sb2NhbGhvc3QiLCJub25jZSI6IjkyYzNhNjMxLWRiNTQtNGFlOS1iZDUzLWNhZjkyYTRhZGJjZiIsInNpZCI6ImQzZDFlOWY2LWE1NTMtNDI2ZC04MWQ1LTE0YTFiZjg0MDJhNCIsIm94T3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCIsImF1ZCI6IjMxNzBjYmM1LTAwMTgtNDllZi04YmE2LTI2ODBiNjY4YmYwYyIsImFjciI6InJvcGMtYmFja2NoYW5uZWwiLCJjX2hhc2giOiJzZVkxTldwNmN6ZGppUEdTWktqQlZRIiwiYXV0aF90aW1lIjoxNjU2NTE2MDM4LCJleHAiOjE2NTY1MTk2NTAsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNjU2NTE2MDUwfQ.giFYGuN-VUNSVMMT4bBkoGsZ-rKlByqe6qv24jzp7pk2eCY4FawiaLHJqH9MzBN7uEauRXYNR2pa_0oGoYnNNg4zbFiSARSKVsajcrPeDUgNs71MjMOYCH5dukXB7X5SEP3Drz5njxuXswI_EjM2Cd0OtJMoHQ0_IP_C3rzwmaQQsgWk81yAXl-eM4zABYV1e9OObGFqPtVjoHmpbFbg-teoRTr_LxYgKPwB1XnRqD4G9No7oV-9q1Bv1ED9AU6zxLWf9aGE2gQIC-jgkr7LZ5pB4zYgU_DwgmpaAuW_AT8ApfnQPqgNy7YouIPWZ8pyoncLjF0SdStVPEoreRx7GA\",\"token_type\":\"Bearer\",\"expires_in\":299} With info, you could do whatever you want using browser session. NOTE: I added some custom params in case you need to validate something else, for instance browser IP. Script templates # These scripts are examples of how it worked, but you could customize them based on your needs, for instance browser validations. Backchannel authentication script # from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper from io.jans.as.server.util import ServerUtil from io.jans.service.cache import CacheProvider from io.jans.as.server.service import SessionIdService from io.jans.as.server.service import CookieService from io.jans.as.server.security import Identity from io.jans.service.cache import CacheProvider import java class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"Backchannel Authentication. Initialization\" print \"Backchannel Authentication. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Backchannel Authentication. Destroy\" print \"Backchannel Authentication. Destroyed successfully\" return True def getAuthenticationMethodClaims(self, requestParameters): return None def getApiVersion(self): return 11 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): print \"Backchannel Authentication. Authenticate\" # Get bcAuthnToken from params bcAuthnToken = ServerUtil.getFirstValue(requestParameters, \"bcAuthnToken\") print \"Backchannel Authentication. Get bcAuthnToken from params: '%s'\" % (bcAuthnToken) if (bcAuthnToken == None): return False # Get sessionDn from cacheProvider cacheProvider = CdiUtil.bean(CacheProvider) sessionCacheDn = cacheProvider.get(bcAuthnToken) print \"Backchannel Authentication. Get sessionCacheDn from cacheProvider: '%s'\" % (sessionCacheDn) if (sessionCacheDn == None): return False # Get sessionId by sessionDn sessionId = CdiUtil.bean(SessionIdService).getSessionByDn(sessionCacheDn) print \"Backchannel Authentication. Get sessionId from sessionIdService: '%s'\" % ('None' if sessionId == None else sessionId.getId()) if (sessionId == None): return False # Write sessionId in cookies CdiUtil.bean(CookieService).createSessionIdCookie(sessionId, False) print \"Backchannel Authentication. Set session in Cookie\" # Set sessionId in Identity identity = CdiUtil.bean(Identity) identity.setSessionId(sessionId) print \"Backchannel Authentication. Set session in Identity\" # Remove bcAuthnToken from cacheProvider cacheProvider.remove(bcAuthnToken) print \"Backchannel Authentication. Removed cacheProvider bcAuthnToken: '%s'\" % bcAuthnToken return True def prepareForStep(self, configurationAttributes, requestParameters, step): if (step == 1): return True else: return False def getExtraParametersForStep(self, configurationAttributes, step): return None def getCountAuthenticationSteps(self, configurationAttributes): return 1 def getPageForStep(self, configurationAttributes, step): return \"postlogin.xhtml\" def getNextStep(self, configurationAttributes, requestParameters, step): return -1 def getLogoutExternalUrl(self, configurationAttributes, requestParameters): return None def logout(self, configurationAttributes, requestParameters): return True ROPC backchannel script # from io.jans.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType from io.jans.as.server.service import AuthenticationService, SessionIdService from io.jans.as.server.security import Identity from io.jans.service.cdi.util import CdiUtil from io.jans.as.model.authorize import AuthorizeRequestParam from io.jans.as.server.model.config import Constants from io.jans.util import StringHelper from java.lang import String from java.util import Date, HashMap from io.jans.service.cache import CacheProvider import uuid class ResourceOwnerPasswordCredentials(ResourceOwnerPasswordCredentialsType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"ROPC Backchannel. Initializing ...\" print \"ROPC Backchannel. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"ROPC Backchannel. Destroying ...\" print \"ROPC Backchannel. Destroyed successfully\" return True def getApiVersion(self): return 11 def authenticate(self, context): print \"ROPC Backchannel. Authenticate\" # Do generic authentication authenticationService = CdiUtil.bean(AuthenticationService) username = context.getHttpRequest().getParameter(\"username\") password = context.getHttpRequest().getParameter(\"password\") # Add credential validation result = authenticationService.authenticate(username, password) if not result: print \"ROPC Backchannel. Authenticate. Could not authenticate user '%s' \" % username return False context.setUser(authenticationService.getAuthenticatedUser()) print \"ROPC Backchannel. Authenticate. User '%s' authenticated successfully\" % username # Get custom parameters from request customParam1Value = context.getHttpRequest().getParameter(\"custom1\") customParam2Value = context.getHttpRequest().getParameter(\"custom2\") customParameters = {} customParameters[\"custom1\"] = customParam1Value customParameters[\"custom2\"] = customParam2Value print \"ROPC Backchannel. Authenticate. User '%s'. Creating authenticated session with custom attributes: '%s'\" % (username, customParameters) session = self.createNewAuthenticatedSession(context, customParameters) # This is needed to allow store in token entry sessionId authenticationService.configureEventUser(session) print \"ROPC Backchannel. Authenticate. User '%s'. Created authenticated session: '%s'\" % (username, customParameters) return True def createNewAuthenticatedSession(self, context, customParameters={}): sessionIdService = CdiUtil.bean(SessionIdService) user = context.getUser() client = CdiUtil.bean(Identity).getSessionClient().getClient() # Add mandatory session parameters sessionAttributes = HashMap() sessionAttributes.put(Constants.AUTHENTICATED_USER, user.getUserId()) sessionAttributes.put(AuthorizeRequestParam.CLIENT_ID, client.getClientId()) # Add custom session parameters for key, value in customParameters.iteritems(): if StringHelper.isNotEmpty(value): sessionAttributes.put(key, value) # Generate authenticated session sessionId = sessionIdService.generateAuthenticatedSessionId(context.getHttpRequest(), user.getDn(), sessionAttributes) print \"ROPC Backchannel. Generated session id. DN: '%s'\" % sessionId.getDn() # Add state uuid in cache manager and response header bcAuthnToken = str(uuid.uuid4()) cacheProvider = CdiUtil.bean(CacheProvider) cacheProvider.put(300, bcAuthnToken, sessionId.getDn()) print \"ROPC Backchannel. Added cacheProvider id: '%s'\" % bcAuthnToken # Add response header Bc-Authn-Token context.getHttpResponse().setHeader(\"Bc-Authn-Token\", bcAuthnToken) print \"ROPC Backchannel. Added header Bc-Authn-Token\" return sessionId", "title": "Backchannel Authentication"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#backchannel-authentication-scripts", "text": "Janssen server enables domains to render the username/pw login form, avoiding the redirect to the IDP-hosted login page. Many SSO solutions offer a proprietary endpoint to accomplish this. However, in Janssen server, this is accomplished with the OAuth/OpenID framework by using a combination of calling the /token endpoint using the OAuth password flow, and then redirecting to browser to the /authorization endpoint, but auto-submitting the form. This article describes how to process login via backchannel and when browser is processing authorization, AS will recognize automatically the authenticated user, write cookies and then establish the session.", "title": "Backchannel authentication scripts"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#design", "text": "Source-code for sequence diagram Title password Grant with State Person->Browser: Navigate to website Browser->Website: Website->Browser:Display login page Person->Browser: Enter Username / PW Browser->Website: (creds) Website->IDP: /token?uid=_&pw=&browser_ip=_ IDP->Website: {\"redirect\": \"/authz/state=1F2D41A\", ...} Website->Browser: Browser->IDP: /authz?state=1F2D41A IDP->IDP: check IP address is\\n same as state IDP->Browser: write cookie / send redirect_uri Browser->Website: redirect_uri", "title": "Design"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#solution", "text": "In order to process the whole authorization, idea is to use resource owner password credentials grant type in the first stage, over there process the authentication as we do today, but also write in cache a short-lived token to recognize such authenticated user, then return to the client such short-lived token. During authorization, browser should send that token as part of the custom params and in the AS we should verify if that user is already authenticated using the short-lived param in the cache, then AS will write cookies, create the session and return to the client information required for this.", "title": "Solution"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#jans-app-configurations", "text": "Above the jans-auth record of the jansAppConf table, enable a new attribute on the jansConfDyn field Example: \"authorizationRequestCustomAllowedParameters\": [ { \"paramName\": \"bcAuthnToken\", \"returnInResponse\": true } ] Sample CURL 1. Obtain access token curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/jans-auth-server/config/properties.write\" 2. Apply patch curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"authorizationRequestCustomAllowedParameters\", \"value\": [ { \"paramName\": \"bcAuthnToken\", \"returnInResponse\": true } ] } ]'", "title": "Jans App Configurations"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#custom-script-registration", "text": "In the table jansCustomScr enable 2 new scripts: 1. Script type resource_owner_password_credentials displayName ropc-backchannel [ropc-backchannel-script.py] See script below. 2. Script type person_autentication displayName backchannel-authentication [backchannel-authentication-script.py] See script below.", "title": "Custom Script Registration"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#client-configuration", "text": "Associate script person_authentication on table jansClnt . Modify the jansAttrs field which contains a json and the ropcScripts field and add the dn from the ropc script record in the previous step Example: \"ropcScripts\": [ \"inum={SCRIPT_ID},ou=scripts,o=jans\", ],", "title": "Client Configuration"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#flow", "text": "", "title": "Flow"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#bcauthtoken-request", "text": "Firstly, the /token service is called to generate the bcAuthnToken (get it from the response header with the key Bc-Authn-Token ) In this request example, the client's basic credential is being used in order to authenticate the client, however you could use your preferred authn mode. Request curl --location --request POST 'https://jans.localhost/jans-auth/restv1/token' \\ --header 'Authorization: Basic MzE3MGNiYzUtMDAxOC00OWVmLThiYTYtMjY4MGI2NjhiZjBjOmFmNzk1ZjI1LWQ1MjktNDVlYi1iMTJlLWNjM2ExNTY5OTU1Ng==' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=password' \\ --data-urlencode 'username=test_user' \\ --data-urlencode 'password=test_user_password' \\ --data-urlencode 'custom1=your custom param 1' \\ --data-urlencode 'custom2=your custom param 2' \\ --data-urlencode 'scope=openid' Response HTTP/1.1 200 OK Date: Wed, 29 Jun 2022 14:03:25 GMT Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Bc-Authn-Token: dacfe4fc-d0ce-4673-9370-e66f652c4b7f Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1109 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive {\"access_token\":\"7a024a59-e132-4c05-9126-f4f36b3d3677\",\"refresh_token\":\"184c2b60-b5c7-4250-9850-97b0f531743c\",\"scope\":\"openid\",\"id_token\":\"eyJraWQiOiJmZGJhY2Q2Yi05YTY0LTQ2MWQtOWJlYy1jOTAyMjc5ZGI2ODZfc2lnX3JzMjU2IiwidHlwIjoiand0IiwiYWxnIjoiUlMyNTYifQ.eyJhdWQiOiIzMTcwY2JjNS0wMDE4LTQ5ZWYtOGJhNi0yNjgwYjY2OGJmMGMiLCJhY3IiOiJzaW1wbGVfcGFzc3dvcmRfYXV0aCIsInN1YiI6Il9Fa3p5aXlRdVBzUm1mYjh3WHlmTTB4U0xDckxwTDJGNnA3RWhEeWRBUHciLCJjb2RlIjoiNDY4MzQ2NjktOGQ1Yy00NmQxLTkwNWEtNmMzNDg3YzZlMDg3IiwiYW1yIjpbXSwiaXNzIjoiaHR0cHM6Ly9qYW5zLmxvY2FsaG9zdCIsImV4cCI6MTY1NjUxNTAwNiwiZ3JhbnQiOiJwYXNzd29yZCIsImlhdCI6MTY1NjUxMTQwNiwic2lkIjoiMTg0ZTllOTktNjFmNi00ZWNhLWE0ZmUtMTMwZmFmZDk1MjE1Iiwib3hPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIn0.hW0vReGYLzC2RyBHztSFbDYoaYHcCYxatX1lpzWqyW5U2S9eNp58mKKmvdZmMc229Sz5VxqfYflpWuI_6aXsLFR_KT9FY3exSRIRtPiD_fUETdhsVuKWavumVnjvwdAM6ytu5ORJx06DCxEgaG1uXmRiE9GoT8F1uqeo4NxURhVNXmMd2fiiUmgm1lt3-kNhlSg6vMDJS1Aq1idm-XhiSVy895BY-JdpLEGJEycPKr1lpsBTcmasbFNBJv6_orKWlvvgFCVxo7XmbH7Xnmqi6UUo30L6sULqmCsTLa6DaWYfGokHz_0xRflw_Ihv9wlVq8gSdOZGoMaVGzDdKlddZw\",\"token_type\":\"Bearer\",\"expires_in\":299}", "title": "BcAuthToken request:"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#authorize-request", "text": "Once you have gotten the bcAuthnToken from the previous /token call, you must call authorize attaching the bcAuthnToken as a parameter and in the acr_values param send the name of the backchannel-authentication registered in previous steps. This script will generate cookies and session associated with the browser if the BcAuthToken is valid. Example: https://jans.localhost/jans-auth/restv1/authorize?response_type=code&client_id=3170cbc5-0018-49ef-8ba6-2680b668bf0c&scope=openid+profile+address+email&redirect_uri=https://jans.localhost/jans-auth-rp/home.htm&state=2f78eaf1-d73e-49f2-8f50-e5faef80808a&nonce=92c3a631-db54-4ae9-bd53-caf92a4adbcf&prompt=&ui_locales=&claims_locales=&acr_values=backchannel-authentication&request_session_id=false&bcAuthnToken={your bcAuthnToken} This call will redirect to the redirect_uri that you sent as a parameter in the call and will receive a code as well, after that the process is more or less the same than the regular flow.", "title": "Authorize request:"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#request-token", "text": "With the code obtained previously, you must call /token again, adding the parameter code Request: curl --location --request POST 'https://jans.localhost/jans-auth/restv1/token' \\ --header 'Authorization: Basic MzlhNjlmYzAtNzNmYy00MWJhLWFiMGYtNDJhNWFmYWI2MjllOmJmMDRlZTM4LTM0MTktNGEzNS05YTI5LTcyODlmY2JkNzc2Zg==' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=authorization_code' \\ --data-urlencode 'code=d449a7b9-10f6-4320-b257-05fee91d3c16' \\ --data-urlencode 'redirect_uri=https://jans.localhost/jans-auth-rp/home.htm' Response: HTTP/1.1 200 OK Date: Wed, 29 Jun 2022 15:20:50 GMT Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1291 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive {\"access_token\":\"896b04a2-fcbe-4466-89b9-184930b8675b\",\"refresh_token\":\"843995ef-cd0e-4b2c-9b91-7c68081325ab\",\"id_token\":\"eyJraWQiOiJmZGJhY2Q2Yi05YTY0LTQ2MWQtOWJlYy1jOTAyMjc5ZGI2ODZfc2lnX3JzMjU2IiwidHlwIjoiand0IiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoiMmx5OXh5emthMmc2T09HcVRPTmhqdyIsInN1YiI6Il9Fa3p5aXlRdVBzUm1mYjh3WHlmTTB4U0xDckxwTDJGNnA3RWhEeWRBUHciLCJjb2RlIjoiMjdiNjM0NTItMTE1My00ZDk5LTlkYzQtYzMyNGRmNjIwYWE0IiwiYW1yIjpbIjEwIl0sImlzcyI6Imh0dHBzOi8vamFucy5sb2NhbGhvc3QiLCJub25jZSI6IjkyYzNhNjMxLWRiNTQtNGFlOS1iZDUzLWNhZjkyYTRhZGJjZiIsInNpZCI6ImQzZDFlOWY2LWE1NTMtNDI2ZC04MWQ1LTE0YTFiZjg0MDJhNCIsIm94T3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCIsImF1ZCI6IjMxNzBjYmM1LTAwMTgtNDllZi04YmE2LTI2ODBiNjY4YmYwYyIsImFjciI6InJvcGMtYmFja2NoYW5uZWwiLCJjX2hhc2giOiJzZVkxTldwNmN6ZGppUEdTWktqQlZRIiwiYXV0aF90aW1lIjoxNjU2NTE2MDM4LCJleHAiOjE2NTY1MTk2NTAsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNjU2NTE2MDUwfQ.giFYGuN-VUNSVMMT4bBkoGsZ-rKlByqe6qv24jzp7pk2eCY4FawiaLHJqH9MzBN7uEauRXYNR2pa_0oGoYnNNg4zbFiSARSKVsajcrPeDUgNs71MjMOYCH5dukXB7X5SEP3Drz5njxuXswI_EjM2Cd0OtJMoHQ0_IP_C3rzwmaQQsgWk81yAXl-eM4zABYV1e9OObGFqPtVjoHmpbFbg-teoRTr_LxYgKPwB1XnRqD4G9No7oV-9q1Bv1ED9AU6zxLWf9aGE2gQIC-jgkr7LZ5pB4zYgU_DwgmpaAuW_AT8ApfnQPqgNy7YouIPWZ8pyoncLjF0SdStVPEoreRx7GA\",\"token_type\":\"Bearer\",\"expires_in\":299} With info, you could do whatever you want using browser session. NOTE: I added some custom params in case you need to validate something else, for instance browser IP.", "title": "Request /token:"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#script-templates", "text": "These scripts are examples of how it worked, but you could customize them based on your needs, for instance browser validations.", "title": "Script templates"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#backchannel-authentication-script", "text": "from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper from io.jans.as.server.util import ServerUtil from io.jans.service.cache import CacheProvider from io.jans.as.server.service import SessionIdService from io.jans.as.server.service import CookieService from io.jans.as.server.security import Identity from io.jans.service.cache import CacheProvider import java class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"Backchannel Authentication. Initialization\" print \"Backchannel Authentication. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Backchannel Authentication. Destroy\" print \"Backchannel Authentication. Destroyed successfully\" return True def getAuthenticationMethodClaims(self, requestParameters): return None def getApiVersion(self): return 11 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): print \"Backchannel Authentication. Authenticate\" # Get bcAuthnToken from params bcAuthnToken = ServerUtil.getFirstValue(requestParameters, \"bcAuthnToken\") print \"Backchannel Authentication. Get bcAuthnToken from params: '%s'\" % (bcAuthnToken) if (bcAuthnToken == None): return False # Get sessionDn from cacheProvider cacheProvider = CdiUtil.bean(CacheProvider) sessionCacheDn = cacheProvider.get(bcAuthnToken) print \"Backchannel Authentication. Get sessionCacheDn from cacheProvider: '%s'\" % (sessionCacheDn) if (sessionCacheDn == None): return False # Get sessionId by sessionDn sessionId = CdiUtil.bean(SessionIdService).getSessionByDn(sessionCacheDn) print \"Backchannel Authentication. Get sessionId from sessionIdService: '%s'\" % ('None' if sessionId == None else sessionId.getId()) if (sessionId == None): return False # Write sessionId in cookies CdiUtil.bean(CookieService).createSessionIdCookie(sessionId, False) print \"Backchannel Authentication. Set session in Cookie\" # Set sessionId in Identity identity = CdiUtil.bean(Identity) identity.setSessionId(sessionId) print \"Backchannel Authentication. Set session in Identity\" # Remove bcAuthnToken from cacheProvider cacheProvider.remove(bcAuthnToken) print \"Backchannel Authentication. Removed cacheProvider bcAuthnToken: '%s'\" % bcAuthnToken return True def prepareForStep(self, configurationAttributes, requestParameters, step): if (step == 1): return True else: return False def getExtraParametersForStep(self, configurationAttributes, step): return None def getCountAuthenticationSteps(self, configurationAttributes): return 1 def getPageForStep(self, configurationAttributes, step): return \"postlogin.xhtml\" def getNextStep(self, configurationAttributes, requestParameters, step): return -1 def getLogoutExternalUrl(self, configurationAttributes, requestParameters): return None def logout(self, configurationAttributes, requestParameters): return True", "title": "Backchannel authentication script"}, {"location": "janssen-server/auth-server/endpoints/backchannel-authentication/#ropc-backchannel-script", "text": "from io.jans.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType from io.jans.as.server.service import AuthenticationService, SessionIdService from io.jans.as.server.security import Identity from io.jans.service.cdi.util import CdiUtil from io.jans.as.model.authorize import AuthorizeRequestParam from io.jans.as.server.model.config import Constants from io.jans.util import StringHelper from java.lang import String from java.util import Date, HashMap from io.jans.service.cache import CacheProvider import uuid class ResourceOwnerPasswordCredentials(ResourceOwnerPasswordCredentialsType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"ROPC Backchannel. Initializing ...\" print \"ROPC Backchannel. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"ROPC Backchannel. Destroying ...\" print \"ROPC Backchannel. Destroyed successfully\" return True def getApiVersion(self): return 11 def authenticate(self, context): print \"ROPC Backchannel. Authenticate\" # Do generic authentication authenticationService = CdiUtil.bean(AuthenticationService) username = context.getHttpRequest().getParameter(\"username\") password = context.getHttpRequest().getParameter(\"password\") # Add credential validation result = authenticationService.authenticate(username, password) if not result: print \"ROPC Backchannel. Authenticate. Could not authenticate user '%s' \" % username return False context.setUser(authenticationService.getAuthenticatedUser()) print \"ROPC Backchannel. Authenticate. User '%s' authenticated successfully\" % username # Get custom parameters from request customParam1Value = context.getHttpRequest().getParameter(\"custom1\") customParam2Value = context.getHttpRequest().getParameter(\"custom2\") customParameters = {} customParameters[\"custom1\"] = customParam1Value customParameters[\"custom2\"] = customParam2Value print \"ROPC Backchannel. Authenticate. User '%s'. Creating authenticated session with custom attributes: '%s'\" % (username, customParameters) session = self.createNewAuthenticatedSession(context, customParameters) # This is needed to allow store in token entry sessionId authenticationService.configureEventUser(session) print \"ROPC Backchannel. Authenticate. User '%s'. Created authenticated session: '%s'\" % (username, customParameters) return True def createNewAuthenticatedSession(self, context, customParameters={}): sessionIdService = CdiUtil.bean(SessionIdService) user = context.getUser() client = CdiUtil.bean(Identity).getSessionClient().getClient() # Add mandatory session parameters sessionAttributes = HashMap() sessionAttributes.put(Constants.AUTHENTICATED_USER, user.getUserId()) sessionAttributes.put(AuthorizeRequestParam.CLIENT_ID, client.getClientId()) # Add custom session parameters for key, value in customParameters.iteritems(): if StringHelper.isNotEmpty(value): sessionAttributes.put(key, value) # Generate authenticated session sessionId = sessionIdService.generateAuthenticatedSessionId(context.getHttpRequest(), user.getDn(), sessionAttributes) print \"ROPC Backchannel. Generated session id. DN: '%s'\" % sessionId.getDn() # Add state uuid in cache manager and response header bcAuthnToken = str(uuid.uuid4()) cacheProvider = CdiUtil.bean(CacheProvider) cacheProvider.put(300, bcAuthnToken, sessionId.getDn()) print \"ROPC Backchannel. Added cacheProvider id: '%s'\" % bcAuthnToken # Add response header Bc-Authn-Token context.getHttpResponse().setHeader(\"Bc-Authn-Token\", bcAuthnToken) print \"ROPC Backchannel. Added header Bc-Authn-Token\" return sessionId", "title": "ROPC backchannel script"}, {"location": "janssen-server/auth-server/endpoints/client-registration/", "tags": ["administration", "auth-server", "endpoint", "DCR", "dynamic client registration"], "text": "Dynamic Client Registration (DCR) # Dynamic client registration refers to the process by which a client submits a registration request to the Authorization server and how that request is served by the Authorization server. It is explained in the following specifications: For OpenID Connect relying parties For OAuth 2.0 client (without OpenID Connect features) Client management (CRUD) operations OpenBanking OpenID Dynamic Client Registration Client Registration endpoint # The URI to dynamically register a client to a Janssen Auth Server can be found by checking the registration_endpoint claim of the OpenID Connect configuration reponse, typically deployed at https://<my.jans.server>/.well-known/openid-configuration Configuring Janssen AS to allow clients to dynamically register # The Janssen Authorization server will serve a DCR request if the following configuration parameters are set: dynamicRegistrationEnabled : true or false dynamicRegistrationExpirationTime : Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire dcrForbidExpirationTimeInRequest : Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration.. Default value is false . Client expiration Client expiration is set based on dynamicRegistrationExpirationTime AS configuration property or otherwise if dcrForbidExpirationTimeInRequest is false then it can be requested in Dynamic Client Registration Request via lifetime parameter which expected value in seconds. Configure the Janssen AS using steps explained in the link Client registration Requests # Client registration request primarily does two things: Communicate client metadata to the authorization server, and optionally authenticate. There are different ways in which the client metadata is communicated to the authorization server using dynamic client registration requests. Using request body Using signed request object (JWT) Using software statement Using request body # A minimal DCR request with only mandatory parameters, looks like the one below. curl -X POST -k -H 'Content-Type: application/json' -i 'https://my.jans.server/jans-auth/restv1/register' \\ --data '{\"redirect_uris\": [\"https://my.jans.client/page\"]}' If the registration is successful, Janssen Server will respond with http response code 201 with JSON body as shown in example below: { \"allow_spontaneous_scopes\" : false , \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://my.jans.server/jans-auth/restv1/register?client_id=85192707-a38c-496c-806c-ef01a6a3ae4a\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"eaee20de-54ce-4217-b960-6b72b55e6cab\" , \"client_id\" : \"85192707-a38c-496c-806c-ef01a6a3ae4a\" , \"token_endpoint_auth_method\" : \"client_secret_basic\" , \"scope\" : \"profile work_phone phone user_name device_sso openid permission uma_protection address email clientinfo org_name offline_access https://jans.io/auth/ssa.portal test https://jans.io/auth/ssa.admin https://jans.io/auth/ssa.developer\" , \"client_secret\" : \"4148f812-92d6-4245-80e0-243524b3b6a4\" , \"client_id_issued_at\" : 1678700818 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"client_name\" : \"my.jans.client\" , \"par_lifetime\" : 600 , \"lifetime\" : 3600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : false , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" ], \"subject_type\" : \"pairwise\" , \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris\" : [ \"https://my.jans.client/page\" ], \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1678787218 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" ] } In a typical DCR request the client or developer calls the client registration endpoint with a set of client metadata as specified in RFC7591 curl -X POST -k -i 'https://my.jans.server/jans-auth/restv1/register' \\ --data '{ \\ \"redirect_uris\": [\"https://client.example.org/cb\"] \\ \"client_id\": \"c3BhdRkqfX\", \\ \"client_secret\": \"bd136123eeffeef234235805d\", \\ \"grant_types\": [\"authorization_code\", \"refresh_token\"], \\ \"token_endpoint_auth_method\": \"client_secret_basic\", \\ \"jwks_uri\": \"https://client.example.org/my_public_keys.jwks\", \\ \"client_name\": \"My Example\", \\ \"client_name#fr\": \"Mon Exemple\" \\ }' Using signed request object (JWT) # In some use-cases like FAPI implementation, DCR request payload is a JWT. Example: curl -X POST -k -H 'Content-Type: application/jwt' \\ -H 'Accept: application/json' \\ -i 'https://my-jans-server/jans-auth/restv1/register' \\ --data 'eyJraWQiOiJrWTIyZXBUT......ueOg2HkjpggwAEP84jq9Q' When such will be the nature of client registration requests, the following configuration properties should be set in the authorization server: dcrSignatureValidationEnabled - enables DCR signature validation dcrSignatureValidationJwksUri - specifies JWKS URI for all DCR's validations. dcrSignatureValidationJwks - specifies JWKS for all DCR's validations. Configure the Janssen AS using steps explained in the link Using software statement # A signed assertion from a trusted party, a Software statement or Software Statement Assertion (SSA), is used to dynamically register clients to an Authorization server. Example: curl -X POST https://my.jans.server/jans-auth/restv1/register \\ -H \"Content-Type: application/json\" \\ --data-binary @- <<DATA \\ { \"redirect_uris\": [ \"https://client.example.org/cab1\" ], \\ \"software_statement\":\"eyJ0eXAi........j3ouyeYOv8\", \\ \"jwks_uri\":\"https://my.portal/portal/jwks\" \\ } DATA To enable client registrations using Software statements, the AS should be configured using the following configuration parameters: softwareStatementValidationType - The value of this variable is one of the following: NONE - validation is skipped for software statement SCRIPT - (default), invokes getSoftwareStatementJwks of dynamic registration script which has to return jwks. JWKS - claim name within software statement that has inlined JWKS JWKS_URI - claim name within software statement that points to JWKS URI that should lead to keys. dcrSignatureValidationSoftwareStatementJwksURIClaim - specifies claim name inside software statement that should point to JWKS URI. dcrSignatureValidationSoftwareStatementJwksClaim - specifies claim name inside software statement. Value of claim should point to inlined JWKS. trustedSsaIssuers - map of trusted SSA issuers with configuration (e.g. automatically granted scopes). When empty - no issuers validation is performed. When not empty - AS forces validation and each SSA must match at least one entry from list. automaticallyGrantedScopes - automatically granted scopes for trusted issuer { \"https://trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"a\" , \"b\" ] }, \"https://another-trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"d\" ] } } Configure the AS using steps explained in the link Special mention about FAPI: # In case of a typical client registration request in FAPI implementation , the request object which is a signed JWT (as seen in point 3) is also called an SSA (Software statement Assertion) or DCR payload. This SSA can contain the software_statement inside it which is also a signed JWT. Each of the JWTs, the outer JWT called the SSA and the inner JWT called the software_statement are signed by different entities - the TPP and OBIE respectively. Security Pointers # If dynamicRegistrationEnabled is enabled in the Authorization Server, assess the following points to minimize potential exposure of sensitive personal data: trustedClientEnabled and dynamicRegistrationPersistClientAuthorizations properties determine whether clients are trusted and if consent should be sought from the user before releasing their personal data to the RP dynamicRegistrationScopesParamEnabled controls whether default scopes are globally enabled. If dynamicRegistrationScopesParamEnabled is true then scopes defined as default will be automatically added to any dynamically registered client entry without consent of OP's administrator. Therefore, make an informed decision before setting this field to true . CURL commands to configure Jans-auth server # Jans-auth server is configured using Jans Config Api : Obtain the access token # curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/jans-auth-server/config/properties.write\" Patch jans-auth server configurations # Patch jans-auth server configurations to reflect anExampleConfigField with the value anExampleConfigField_value curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://<your.jans.server>/jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"anExampleConfigField\", \"value\": \"anExampleConfigField_value\" } ]' For example, to patch the jans-auth server configurations to reflect dynamicRegistrationEnabled with value as true curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://<your.jans.server>/jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"dynamicRegistrationEnabled\", \"value\": \"true\" } ]' Client metadata # Command to obtain metadata schema jans cli --schema /components/schemas/Client Output: { \"dn\" : \"string\" , \"inum\" : \"string\" , \"displayName\" : \"string\" , \"clientSecret\" : \"string\" , \"frontChannelLogoutUri\" : \"string\" , \"frontChannelLogoutSessionRequired\" : true , \"registrationAccessToken\" : \"string\" , \"clientIdIssuedAt\" : \"2022-08-31T10:39:31.385Z\" , \"clientSecretExpiresAt\" : \"2022-08-31T10:39:31.385Z\" , \"redirectUris\" : [ \"https://client.example.org/cb\" ], \"claimRedirectUris\" : [ \"string\" ], \"responseTypes\" : [ \"code\" ], \"grantTypes\" : [ \"authorization_code\" ], \"applicationType\" : \"web\" , \"contacts\" : [ \"string\" ], \"idTokenTokenBindingCnf\" : \"string\" , \"logoUri\" : \"string\" , \"clientUri\" : \"string\" , \"policyUri\" : \"string\" , \"tosUri\" : \"string\" , \"jwksUri\" : \"string\" , \"jwks\" : \"{ \\\"keys\\\" : [ { \\\"e\\\" : \\\"AQAB\\\", \\\"n\\\" : \\\"gmlDX_mgMcHX..\\\" ] }\" , \"sectorIdentifierUri\" : \"string\" , \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"HS256\" , \"idTokenEncryptedResponseAlg\" : \"RSA1_5\" , \"idTokenEncryptedResponseEnc\" : \"A128CBC+HS256\" , \"userInfoSignedResponseAlg\" : \"HS256\" , \"userInfoEncryptedResponseAlg\" : \"RSA1_5\" , \"userInfoEncryptedResponseEnc\" : \"A128CBC+HS256\" , \"requestObjectSigningAlg\" : \"HS256\" , \"requestObjectEncryptionAlg\" : \"RSA1_5\" , \"requestObjectEncryptionEnc\" : \"A128CBC+HS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"tokenEndpointAuthSigningAlg\" : \"HS256\" , \"defaultMaxAge\" : 1000000 , \"requireAuthTime\" : true , \"defaultAcrValues\" : [ \"string\" ], \"initiateLoginUri\" : \"string\" , \"postLogoutRedirectUris\" : [ \"https://client.example.org/logout/page1\" , \"https://client.example.org/logout/page2\" , \"https://client.example.org/logout/page3\" ], \"requestUris\" : [ \"string\" ], \"scopes\" : [ \"read write dolphin\" ], \"claims\" : [ \"string\" ], \"trustedClient\" : false , \"lastAccessTime\" : \"2022-08-31T10:39:31.385Z\" , \"lastLogonTime\" : \"2022-08-31T10:39:31.385Z\" , \"persistClientAuthorizations\" : true , \"includeClaimsInIdToken\" : false , \"refreshTokenLifetime\" : 100000000 , \"accessTokenLifetime\" : 100000000 , \"customAttributes\" : [ { \"name\" : \"name, displayName, birthdate, email\" , \"multiValued\" : true , \"values\" : [ \"string\" ] } ], \"customObjectClasses\" : [ \"string\" ], \"rptAsJwt\" : true , \"accessTokenAsJwt\" : true , \"accessTokenSigningAlg\" : \"HS256\" , \"disabled\" : false , \"authorizedOrigins\" : [ \"string\" ], \"softwareId\" : \"4NRB1-0XZABZI9E6-5SM3R\" , \"softwareVersion\" : \"2.1\" , \"softwareStatement\" : \"string\" , \"attributes\" : { \"tlsClientAuthSubjectDn\" : \"string\" , \"runIntrospectionScriptBeforeAccessTokenAsJwtCreationAndIncludeClaims\" : true , \"keepClientAuthorizationAfterExpiration\" : true , \"allowSpontaneousScopes\" : true , \"spontaneousScopes\" : [ \"string\" ], \"spontaneousScopeScriptDns\" : [ \"string\" ], \"updateTokenScriptDns\" : [ \"string\" ], \"backchannelLogoutUri\" : [ \"string\" ], \"backchannelLogoutSessionRequired\" : true , \"additionalAudience\" : [ \"string\" ], \"postAuthnScripts\" : [ \"string\" ], \"consentGatheringScripts\" : [ \"string\" ], \"introspectionScripts\" : [ \"string\" ], \"rptClaimsScripts\" : [ \"string\" ], \"ropcScripts\" : [ \"string\" ], \"parLifetime\" : 0 , \"requirePar\" : true , \"jansAuthSignedRespAlg\" : \"string\" , \"jansAuthEncRespAlg\" : \"string\" , \"jansAuthEncRespEnc\" : \"string\" , \"jansSubAttr\" : \"string\" , \"redirectUrisRegex\" : \"string\" , \"jansAuthorizedAcr\" : [ \"string\" ], \"jansDefaultPromptLogin\" : true }, \"backchannelTokenDeliveryMode\" : \"poll\" , \"backchannelClientNotificationEndpoint\" : \"string\" , \"backchannelAuthenticationRequestSigningAlg\" : \"RS256\" , \"backchannelUserCodeParameter\" : true , \"expirationDate\" : \"2022-08-31T10:39:31.385Z\" , \"deletable\" : false , \"jansId\" : \"string\" , \"description\" : \"string\" } Signed DCR and SSA validation # In OpenBanking case DCR (Dynamic Client Request) is signed and must contain SSA (Software Statement Assertion) inside it. Non-Normative Example: POST /register HTTP/1.1 Content-Type: application/jwt Accept: application/json Host: auth.bankone.com eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJJREFtYX... Decoded DCR Example: { \"typ\" : \"JWT\" , \"alg\" : \"ES256\" , \"kid\" : \"ABCD1234\" } { \"iss\" : \"Amazon TPPID\" , \"iat\" : 1492760444 , \"exp\" : 1524296444 , \"aud\" : \"https://authn.gluu.org\" , \"scope\" : \"openid makepayment\" , \"token_endpoint_auth_method\" : \"private_key_jwt\" , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"response_types\" : [ \"code\" ], \"id_token_signed_response_alg\" : \"ES256\" , \"request_object_signing_alg\" : \"ES256\" , \"software_id\" : \"65d1f27c-4aea-4549-9c21-60e495a7a86f\" , \"software_statement\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJlbXB0eSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJhZG1pbiI6dHJ1ZSwic2NvcGUiOiJzY29wZTEgc2NvcGUyIiwiY2xhaW1zIjoiY2xhaW0xIGNsYWltMiIsImlhdCI6MTY2OTgwNjc2MywiZXhwIjoxNjY5ODEwMzYzfQ.db0WQh2lmHkNYCWT8tSW684hqWTPJDTElppy42XM_lc\" } { Sig nature } AS has dcrSsaValidationConfigs configuration value which holds json array. It can be used to validated both DCR and SSA. Single item of this array has following properties: id - REQUIRED primary key for the entity type - REQUIRED either ssa or dcr displayName - Human friendly name in case we build an admin GUI for this description - Human friendly details scope - For SSA only -- list of allowed scopes the issuer can enable the client to request automatically. If not present, all scopes are allowed. allowed_claims - Any claims not listed in this list will be dropped. If not present, all claims are allowed. jwks - Public key jwks_uri - URI of public key issuers - For MTLS, list of issuers trusted configuration_endpoint - points to discovery page, e.g. https://examle.com/.well-known/openid-configuration configuration_endpoint_claim - e.g. ssa_jwks_endpoint shared_secret - for MTLS HMAC One of jwks , jwks_uri or issuers or configuration_endpoint is required. Non-normative example of dcrSsaValidationConfigs [ { \"id\" : \"735ee1c0-895d-4398-9c1b-9ad852257cc0\" , \"type\" : \"DCR\" , \"scopes\" : [ \"read\" , \"write\" ], \"allowedClaims\" : [ \"exp\" , \"iat\" ], \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"Acme\" ], \"sharedSecret\" : \"secret\" }, { \"id\" : \"7907cd0b-0f9f-4b4f-aaa2-0d0614546246\" , \"type\" : \"SSA\" , \"scopes\" : [ \"my_read\" , \"my_write\" ], \"allowedClaims\" : [ \"test_exp\" , \"test_iat\" ], \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"jans-auth\" ], \"sharedSecret\" : \"secret\" }, { \"id\" : \"1e95c9b1-04d0-4440-9362-88f4e1e62d76\" , \"type\" : \"SSA\" , \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"empty\" ], \"sharedSecret\" : \"secret\" } ] Signed DCR validation # DCR can be validated with two approaches. Via dcrSsaValidationConfigs configuration property - RECOMMENDED When create entry in dcrSsaValidationConfigs configuration property : - type MUST be equal to DCR value - issuers MUST have value which equals to iss claim in DCR. Via other configuration properties trustedSsaIssuers - map of trusted SSA issuers with configuration (e.g. automatically granted scopes). When empty - no issuers validation is performed. When not empty - AS forces validation and each SSA must match at least one entry from list. automaticallyGrantedScopes - automatically granted scopes for trusted issuer { \"https://trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"a\" , \"b\" ] }, \"https://another-trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"d\" ] } } dcrSignatureValidationJwks - specifies JWKS for DCR's validations dcrSignatureValidationJwksUri - specifies JWKS URI for DCR's validations dcrSignatureValidationSharedSecret - if HMAC is used, this is the shared secret dcrSignatureValidationEnabled - boolean value enables DCR signature validation. Default is false dcrSignatureValidationSoftwareStatementJwksURIClaim - specifies claim name inside software statement. Value of claim should point to JWKS URI dcrSignatureValidationSoftwareStatementJwksClaim - specifies claim name inside software statement. Value of claim should point to inlined JWKS dcrAuthorizationWithClientCredentials - boolean value indicating if DCR authorization to be performed using client credentials SSA Validation # SSA is validated based on softwareStatementValidationType which is enum. softwareStatementValidationType = builtin - validation is performed against dcrSsaValidationConfigs configuration property, where type MUST be equal to SSA value issuers MUST have value which equals to iss claim in DCR. softwareStatementValidationType = script - jwks and hmac secret are returned by dynamic client registration script softwareStatementValidationType = jwks_uri , allows to specify jwks_uri claim name from software_statement. Claim name specified by softwareStatementValidationClaimName configuration property. softwareStatementValidationType = jwks , allows to specify jwks claim name from software_statement. Claim name specified by softwareStatementValidationClaimName configuration property. softwareStatementValidationType = none , no validation. Customizing the behavior of the AS using Interception script # Janssen's allows developers to register a client with the Authorization Server (AS) without any intervention by the administrator. By default, all clients are given the same default scopes and attributes. Through the use of an interception script, this behavior can be modified. These scripts can be used to analyze the registration request and apply customizations to the registered client. For example, a client can be given specific scopes by analyzing the Software Statement that is sent with the registration request. Further reading here The Use of Attestation in Dynamic Client Registration # AS supports \"The Use of Attestation in OAuth 2.0 Dynamic Client Registration\" specification draft . Specification draft does not define exact attestation request/response formats. Thus AS supports Attestation calls to Verifier via ClientRegistrationType custom script type. Use createClient method of ClientRegistrationType to prevent client creation if attestation result does not satisfy expectation. def createClient ( self , context ): print \"Client registration. CreateClient method\" registerRequest = context . getRegisterRequest () configurationAttributes = context . getConfigurationAttibutes () client = context . getClient () # getting evidence as string or as JWT evidenceAsString = registerRequest . getEvidence () evidenceAsJwt = context . getEvidence () # following code depends on attestation client used to make calls to Verifier attestationResult = attestationClient . attestation ( evidence ) if attestationResult . isFail : print \"Attestation result forbids client creation\" return False print \"Attestation result is OK\" return True Configuration options - dcrAttestationEvidenceRequired - Boolean value indicating if DCR attestation evidence is required. Default value is false . If evidence request parameter is not present and dcrAttestationEvidenceRequired is true AS returns stale_evidence error: HTTP/1.1 400 Bad Request Content-Type: application/json Cache-Control: no-store Pragma: no-cache { \"error\": \"stale_evidence\", \"error_description\": \"The provided evidence is not current.\", \"nonce\": \"lBjvTtuPbpzIaqyiAOOkrIol3WmflPUUepzUXNDFuUgMKUL\" } It is common to get nonce value from Attestation Server. In this case set dcrAttestationEvidenceRequired=false and throw error from custom script. def createClient ( self , context ): evidenceAsString = registerRequest . getEvidence () if StringHelper . isEmpty ( evidenceAsString ) nonceFromVerifier = attestationClient . requestNonce () context . createStaleEvidenceWebApplicationException ( nonceFromVerifier ) return False ... print \"Attestation result is OK\" return True context.createStaleEvidenceWebApplicationException(nonceFromVerifier) leads to stale_evidence error creation, see example above ( nonceFromVerifier must be string value). In case goal is to create own custom error, please use standard context.createWebApplicationException methods and return False from script to prevent client creation. Example entity = < construct error message > context . createWebApplicationException ( 400 , entity ) Dynamic registration custom attributes # CRUD Operations # Janssen Server allows client management through client configuration endpoint (RFC 7592) . JSON response to client registration request contains registration_client_uri and registration_access_token data elements. The URI mentioned using registration_client_uri provides functionality to read, update and delete the client. This endpoint is a protected endpoint where request has to be authenticated using access token registration_access_token . Read client metadata # A read request to the same client that got created in earlier section should be as shown in the example below. HTTP method GET is used to send the request which signifies that it is a request to read client metadata. curl -k -H 'Authorization: Bearer eaee20de-54ce-4217-b960-6b72b55e6cab' \\ -i 'https://my.jans.server/jans-auth/restv1/register?client_id=85192707-a38c-496c-806c-ef01a6a3ae4a' JSON response from Janssen Server will contain the current state of client metadata. Update client metadata # Client metadata can be updated by sending request with PUT HTTP method to registration_client_uri . Janssen Server replaces current metadata with the one sent with update request as outlined in the specification Delete Client # Client can be deleted by sending a request using DELETE method to registration_client_uri . A successful delete action will invalidate the \"client_id\", \"client_secret\", and \"registration_access_token\" for this client, thereby preventing the \"client_id\" from being used at either the authorization endpoint or token endpoint of the authorization server. Internationalization for Client metadata #", "title": "Client Registration"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#dynamic-client-registration-dcr", "text": "Dynamic client registration refers to the process by which a client submits a registration request to the Authorization server and how that request is served by the Authorization server. It is explained in the following specifications: For OpenID Connect relying parties For OAuth 2.0 client (without OpenID Connect features) Client management (CRUD) operations OpenBanking OpenID Dynamic Client Registration", "title": "Dynamic Client Registration (DCR)"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#client-registration-endpoint", "text": "The URI to dynamically register a client to a Janssen Auth Server can be found by checking the registration_endpoint claim of the OpenID Connect configuration reponse, typically deployed at https://<my.jans.server>/.well-known/openid-configuration", "title": "Client Registration endpoint"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#configuring-janssen-as-to-allow-clients-to-dynamically-register", "text": "The Janssen Authorization server will serve a DCR request if the following configuration parameters are set: dynamicRegistrationEnabled : true or false dynamicRegistrationExpirationTime : Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire dcrForbidExpirationTimeInRequest : Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration.. Default value is false . Client expiration Client expiration is set based on dynamicRegistrationExpirationTime AS configuration property or otherwise if dcrForbidExpirationTimeInRequest is false then it can be requested in Dynamic Client Registration Request via lifetime parameter which expected value in seconds. Configure the Janssen AS using steps explained in the link", "title": "Configuring Janssen AS to allow clients to dynamically register"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#client-registration-requests", "text": "Client registration request primarily does two things: Communicate client metadata to the authorization server, and optionally authenticate. There are different ways in which the client metadata is communicated to the authorization server using dynamic client registration requests. Using request body Using signed request object (JWT) Using software statement", "title": "Client registration Requests"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#using-request-body", "text": "A minimal DCR request with only mandatory parameters, looks like the one below. curl -X POST -k -H 'Content-Type: application/json' -i 'https://my.jans.server/jans-auth/restv1/register' \\ --data '{\"redirect_uris\": [\"https://my.jans.client/page\"]}' If the registration is successful, Janssen Server will respond with http response code 201 with JSON body as shown in example below: { \"allow_spontaneous_scopes\" : false , \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://my.jans.server/jans-auth/restv1/register?client_id=85192707-a38c-496c-806c-ef01a6a3ae4a\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"eaee20de-54ce-4217-b960-6b72b55e6cab\" , \"client_id\" : \"85192707-a38c-496c-806c-ef01a6a3ae4a\" , \"token_endpoint_auth_method\" : \"client_secret_basic\" , \"scope\" : \"profile work_phone phone user_name device_sso openid permission uma_protection address email clientinfo org_name offline_access https://jans.io/auth/ssa.portal test https://jans.io/auth/ssa.admin https://jans.io/auth/ssa.developer\" , \"client_secret\" : \"4148f812-92d6-4245-80e0-243524b3b6a4\" , \"client_id_issued_at\" : 1678700818 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"client_name\" : \"my.jans.client\" , \"par_lifetime\" : 600 , \"lifetime\" : 3600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : false , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" ], \"subject_type\" : \"pairwise\" , \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris\" : [ \"https://my.jans.client/page\" ], \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1678787218 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" ] } In a typical DCR request the client or developer calls the client registration endpoint with a set of client metadata as specified in RFC7591 curl -X POST -k -i 'https://my.jans.server/jans-auth/restv1/register' \\ --data '{ \\ \"redirect_uris\": [\"https://client.example.org/cb\"] \\ \"client_id\": \"c3BhdRkqfX\", \\ \"client_secret\": \"bd136123eeffeef234235805d\", \\ \"grant_types\": [\"authorization_code\", \"refresh_token\"], \\ \"token_endpoint_auth_method\": \"client_secret_basic\", \\ \"jwks_uri\": \"https://client.example.org/my_public_keys.jwks\", \\ \"client_name\": \"My Example\", \\ \"client_name#fr\": \"Mon Exemple\" \\ }'", "title": "Using request body"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#using-signed-request-object-jwt", "text": "In some use-cases like FAPI implementation, DCR request payload is a JWT. Example: curl -X POST -k -H 'Content-Type: application/jwt' \\ -H 'Accept: application/json' \\ -i 'https://my-jans-server/jans-auth/restv1/register' \\ --data 'eyJraWQiOiJrWTIyZXBUT......ueOg2HkjpggwAEP84jq9Q' When such will be the nature of client registration requests, the following configuration properties should be set in the authorization server: dcrSignatureValidationEnabled - enables DCR signature validation dcrSignatureValidationJwksUri - specifies JWKS URI for all DCR's validations. dcrSignatureValidationJwks - specifies JWKS for all DCR's validations. Configure the Janssen AS using steps explained in the link", "title": "Using signed request object (JWT)"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#using-software-statement", "text": "A signed assertion from a trusted party, a Software statement or Software Statement Assertion (SSA), is used to dynamically register clients to an Authorization server. Example: curl -X POST https://my.jans.server/jans-auth/restv1/register \\ -H \"Content-Type: application/json\" \\ --data-binary @- <<DATA \\ { \"redirect_uris\": [ \"https://client.example.org/cab1\" ], \\ \"software_statement\":\"eyJ0eXAi........j3ouyeYOv8\", \\ \"jwks_uri\":\"https://my.portal/portal/jwks\" \\ } DATA To enable client registrations using Software statements, the AS should be configured using the following configuration parameters: softwareStatementValidationType - The value of this variable is one of the following: NONE - validation is skipped for software statement SCRIPT - (default), invokes getSoftwareStatementJwks of dynamic registration script which has to return jwks. JWKS - claim name within software statement that has inlined JWKS JWKS_URI - claim name within software statement that points to JWKS URI that should lead to keys. dcrSignatureValidationSoftwareStatementJwksURIClaim - specifies claim name inside software statement that should point to JWKS URI. dcrSignatureValidationSoftwareStatementJwksClaim - specifies claim name inside software statement. Value of claim should point to inlined JWKS. trustedSsaIssuers - map of trusted SSA issuers with configuration (e.g. automatically granted scopes). When empty - no issuers validation is performed. When not empty - AS forces validation and each SSA must match at least one entry from list. automaticallyGrantedScopes - automatically granted scopes for trusted issuer { \"https://trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"a\" , \"b\" ] }, \"https://another-trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"d\" ] } } Configure the AS using steps explained in the link", "title": "Using software statement"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#special-mention-about-fapi", "text": "In case of a typical client registration request in FAPI implementation , the request object which is a signed JWT (as seen in point 3) is also called an SSA (Software statement Assertion) or DCR payload. This SSA can contain the software_statement inside it which is also a signed JWT. Each of the JWTs, the outer JWT called the SSA and the inner JWT called the software_statement are signed by different entities - the TPP and OBIE respectively.", "title": "Special mention about FAPI:"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#security-pointers", "text": "If dynamicRegistrationEnabled is enabled in the Authorization Server, assess the following points to minimize potential exposure of sensitive personal data: trustedClientEnabled and dynamicRegistrationPersistClientAuthorizations properties determine whether clients are trusted and if consent should be sought from the user before releasing their personal data to the RP dynamicRegistrationScopesParamEnabled controls whether default scopes are globally enabled. If dynamicRegistrationScopesParamEnabled is true then scopes defined as default will be automatically added to any dynamically registered client entry without consent of OP's administrator. Therefore, make an informed decision before setting this field to true .", "title": "Security Pointers"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#curl-commands-to-configure-jans-auth-server", "text": "Jans-auth server is configured using Jans Config Api :", "title": "CURL commands to configure Jans-auth server"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#obtain-the-access-token", "text": "curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/jans-auth-server/config/properties.write\"", "title": "Obtain the access token"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#patch-jans-auth-server-configurations", "text": "Patch jans-auth server configurations to reflect anExampleConfigField with the value anExampleConfigField_value curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://<your.jans.server>/jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"anExampleConfigField\", \"value\": \"anExampleConfigField_value\" } ]' For example, to patch the jans-auth server configurations to reflect dynamicRegistrationEnabled with value as true curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://<your.jans.server>/jans-config-api/api/v1/jans-auth-server/config' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"dynamicRegistrationEnabled\", \"value\": \"true\" } ]'", "title": "Patch jans-auth server configurations"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#client-metadata", "text": "Command to obtain metadata schema jans cli --schema /components/schemas/Client Output: { \"dn\" : \"string\" , \"inum\" : \"string\" , \"displayName\" : \"string\" , \"clientSecret\" : \"string\" , \"frontChannelLogoutUri\" : \"string\" , \"frontChannelLogoutSessionRequired\" : true , \"registrationAccessToken\" : \"string\" , \"clientIdIssuedAt\" : \"2022-08-31T10:39:31.385Z\" , \"clientSecretExpiresAt\" : \"2022-08-31T10:39:31.385Z\" , \"redirectUris\" : [ \"https://client.example.org/cb\" ], \"claimRedirectUris\" : [ \"string\" ], \"responseTypes\" : [ \"code\" ], \"grantTypes\" : [ \"authorization_code\" ], \"applicationType\" : \"web\" , \"contacts\" : [ \"string\" ], \"idTokenTokenBindingCnf\" : \"string\" , \"logoUri\" : \"string\" , \"clientUri\" : \"string\" , \"policyUri\" : \"string\" , \"tosUri\" : \"string\" , \"jwksUri\" : \"string\" , \"jwks\" : \"{ \\\"keys\\\" : [ { \\\"e\\\" : \\\"AQAB\\\", \\\"n\\\" : \\\"gmlDX_mgMcHX..\\\" ] }\" , \"sectorIdentifierUri\" : \"string\" , \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"HS256\" , \"idTokenEncryptedResponseAlg\" : \"RSA1_5\" , \"idTokenEncryptedResponseEnc\" : \"A128CBC+HS256\" , \"userInfoSignedResponseAlg\" : \"HS256\" , \"userInfoEncryptedResponseAlg\" : \"RSA1_5\" , \"userInfoEncryptedResponseEnc\" : \"A128CBC+HS256\" , \"requestObjectSigningAlg\" : \"HS256\" , \"requestObjectEncryptionAlg\" : \"RSA1_5\" , \"requestObjectEncryptionEnc\" : \"A128CBC+HS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"tokenEndpointAuthSigningAlg\" : \"HS256\" , \"defaultMaxAge\" : 1000000 , \"requireAuthTime\" : true , \"defaultAcrValues\" : [ \"string\" ], \"initiateLoginUri\" : \"string\" , \"postLogoutRedirectUris\" : [ \"https://client.example.org/logout/page1\" , \"https://client.example.org/logout/page2\" , \"https://client.example.org/logout/page3\" ], \"requestUris\" : [ \"string\" ], \"scopes\" : [ \"read write dolphin\" ], \"claims\" : [ \"string\" ], \"trustedClient\" : false , \"lastAccessTime\" : \"2022-08-31T10:39:31.385Z\" , \"lastLogonTime\" : \"2022-08-31T10:39:31.385Z\" , \"persistClientAuthorizations\" : true , \"includeClaimsInIdToken\" : false , \"refreshTokenLifetime\" : 100000000 , \"accessTokenLifetime\" : 100000000 , \"customAttributes\" : [ { \"name\" : \"name, displayName, birthdate, email\" , \"multiValued\" : true , \"values\" : [ \"string\" ] } ], \"customObjectClasses\" : [ \"string\" ], \"rptAsJwt\" : true , \"accessTokenAsJwt\" : true , \"accessTokenSigningAlg\" : \"HS256\" , \"disabled\" : false , \"authorizedOrigins\" : [ \"string\" ], \"softwareId\" : \"4NRB1-0XZABZI9E6-5SM3R\" , \"softwareVersion\" : \"2.1\" , \"softwareStatement\" : \"string\" , \"attributes\" : { \"tlsClientAuthSubjectDn\" : \"string\" , \"runIntrospectionScriptBeforeAccessTokenAsJwtCreationAndIncludeClaims\" : true , \"keepClientAuthorizationAfterExpiration\" : true , \"allowSpontaneousScopes\" : true , \"spontaneousScopes\" : [ \"string\" ], \"spontaneousScopeScriptDns\" : [ \"string\" ], \"updateTokenScriptDns\" : [ \"string\" ], \"backchannelLogoutUri\" : [ \"string\" ], \"backchannelLogoutSessionRequired\" : true , \"additionalAudience\" : [ \"string\" ], \"postAuthnScripts\" : [ \"string\" ], \"consentGatheringScripts\" : [ \"string\" ], \"introspectionScripts\" : [ \"string\" ], \"rptClaimsScripts\" : [ \"string\" ], \"ropcScripts\" : [ \"string\" ], \"parLifetime\" : 0 , \"requirePar\" : true , \"jansAuthSignedRespAlg\" : \"string\" , \"jansAuthEncRespAlg\" : \"string\" , \"jansAuthEncRespEnc\" : \"string\" , \"jansSubAttr\" : \"string\" , \"redirectUrisRegex\" : \"string\" , \"jansAuthorizedAcr\" : [ \"string\" ], \"jansDefaultPromptLogin\" : true }, \"backchannelTokenDeliveryMode\" : \"poll\" , \"backchannelClientNotificationEndpoint\" : \"string\" , \"backchannelAuthenticationRequestSigningAlg\" : \"RS256\" , \"backchannelUserCodeParameter\" : true , \"expirationDate\" : \"2022-08-31T10:39:31.385Z\" , \"deletable\" : false , \"jansId\" : \"string\" , \"description\" : \"string\" }", "title": "Client metadata"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#signed-dcr-and-ssa-validation", "text": "In OpenBanking case DCR (Dynamic Client Request) is signed and must contain SSA (Software Statement Assertion) inside it. Non-Normative Example: POST /register HTTP/1.1 Content-Type: application/jwt Accept: application/json Host: auth.bankone.com eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJJREFtYX... Decoded DCR Example: { \"typ\" : \"JWT\" , \"alg\" : \"ES256\" , \"kid\" : \"ABCD1234\" } { \"iss\" : \"Amazon TPPID\" , \"iat\" : 1492760444 , \"exp\" : 1524296444 , \"aud\" : \"https://authn.gluu.org\" , \"scope\" : \"openid makepayment\" , \"token_endpoint_auth_method\" : \"private_key_jwt\" , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"response_types\" : [ \"code\" ], \"id_token_signed_response_alg\" : \"ES256\" , \"request_object_signing_alg\" : \"ES256\" , \"software_id\" : \"65d1f27c-4aea-4549-9c21-60e495a7a86f\" , \"software_statement\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJlbXB0eSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJhZG1pbiI6dHJ1ZSwic2NvcGUiOiJzY29wZTEgc2NvcGUyIiwiY2xhaW1zIjoiY2xhaW0xIGNsYWltMiIsImlhdCI6MTY2OTgwNjc2MywiZXhwIjoxNjY5ODEwMzYzfQ.db0WQh2lmHkNYCWT8tSW684hqWTPJDTElppy42XM_lc\" } { Sig nature } AS has dcrSsaValidationConfigs configuration value which holds json array. It can be used to validated both DCR and SSA. Single item of this array has following properties: id - REQUIRED primary key for the entity type - REQUIRED either ssa or dcr displayName - Human friendly name in case we build an admin GUI for this description - Human friendly details scope - For SSA only -- list of allowed scopes the issuer can enable the client to request automatically. If not present, all scopes are allowed. allowed_claims - Any claims not listed in this list will be dropped. If not present, all claims are allowed. jwks - Public key jwks_uri - URI of public key issuers - For MTLS, list of issuers trusted configuration_endpoint - points to discovery page, e.g. https://examle.com/.well-known/openid-configuration configuration_endpoint_claim - e.g. ssa_jwks_endpoint shared_secret - for MTLS HMAC One of jwks , jwks_uri or issuers or configuration_endpoint is required. Non-normative example of dcrSsaValidationConfigs [ { \"id\" : \"735ee1c0-895d-4398-9c1b-9ad852257cc0\" , \"type\" : \"DCR\" , \"scopes\" : [ \"read\" , \"write\" ], \"allowedClaims\" : [ \"exp\" , \"iat\" ], \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"Acme\" ], \"sharedSecret\" : \"secret\" }, { \"id\" : \"7907cd0b-0f9f-4b4f-aaa2-0d0614546246\" , \"type\" : \"SSA\" , \"scopes\" : [ \"my_read\" , \"my_write\" ], \"allowedClaims\" : [ \"test_exp\" , \"test_iat\" ], \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"jans-auth\" ], \"sharedSecret\" : \"secret\" }, { \"id\" : \"1e95c9b1-04d0-4440-9362-88f4e1e62d76\" , \"type\" : \"SSA\" , \"jwks\" : \"{jwks here}\" , \"issuers\" : [ \"empty\" ], \"sharedSecret\" : \"secret\" } ]", "title": "Signed DCR and SSA validation"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#signed-dcr-validation", "text": "DCR can be validated with two approaches. Via dcrSsaValidationConfigs configuration property - RECOMMENDED When create entry in dcrSsaValidationConfigs configuration property : - type MUST be equal to DCR value - issuers MUST have value which equals to iss claim in DCR. Via other configuration properties trustedSsaIssuers - map of trusted SSA issuers with configuration (e.g. automatically granted scopes). When empty - no issuers validation is performed. When not empty - AS forces validation and each SSA must match at least one entry from list. automaticallyGrantedScopes - automatically granted scopes for trusted issuer { \"https://trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"a\" , \"b\" ] }, \"https://another-trusted.as.com\" : { \"automaticallyGrantedScopes\" : [ \"d\" ] } } dcrSignatureValidationJwks - specifies JWKS for DCR's validations dcrSignatureValidationJwksUri - specifies JWKS URI for DCR's validations dcrSignatureValidationSharedSecret - if HMAC is used, this is the shared secret dcrSignatureValidationEnabled - boolean value enables DCR signature validation. Default is false dcrSignatureValidationSoftwareStatementJwksURIClaim - specifies claim name inside software statement. Value of claim should point to JWKS URI dcrSignatureValidationSoftwareStatementJwksClaim - specifies claim name inside software statement. Value of claim should point to inlined JWKS dcrAuthorizationWithClientCredentials - boolean value indicating if DCR authorization to be performed using client credentials", "title": "Signed DCR validation"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#ssa-validation", "text": "SSA is validated based on softwareStatementValidationType which is enum. softwareStatementValidationType = builtin - validation is performed against dcrSsaValidationConfigs configuration property, where type MUST be equal to SSA value issuers MUST have value which equals to iss claim in DCR. softwareStatementValidationType = script - jwks and hmac secret are returned by dynamic client registration script softwareStatementValidationType = jwks_uri , allows to specify jwks_uri claim name from software_statement. Claim name specified by softwareStatementValidationClaimName configuration property. softwareStatementValidationType = jwks , allows to specify jwks claim name from software_statement. Claim name specified by softwareStatementValidationClaimName configuration property. softwareStatementValidationType = none , no validation.", "title": "SSA Validation"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#customizing-the-behavior-of-the-as-using-interception-script", "text": "Janssen's allows developers to register a client with the Authorization Server (AS) without any intervention by the administrator. By default, all clients are given the same default scopes and attributes. Through the use of an interception script, this behavior can be modified. These scripts can be used to analyze the registration request and apply customizations to the registered client. For example, a client can be given specific scopes by analyzing the Software Statement that is sent with the registration request. Further reading here", "title": "Customizing the behavior of the AS using Interception script"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#the-use-of-attestation-in-dynamic-client-registration", "text": "AS supports \"The Use of Attestation in OAuth 2.0 Dynamic Client Registration\" specification draft . Specification draft does not define exact attestation request/response formats. Thus AS supports Attestation calls to Verifier via ClientRegistrationType custom script type. Use createClient method of ClientRegistrationType to prevent client creation if attestation result does not satisfy expectation. def createClient ( self , context ): print \"Client registration. CreateClient method\" registerRequest = context . getRegisterRequest () configurationAttributes = context . getConfigurationAttibutes () client = context . getClient () # getting evidence as string or as JWT evidenceAsString = registerRequest . getEvidence () evidenceAsJwt = context . getEvidence () # following code depends on attestation client used to make calls to Verifier attestationResult = attestationClient . attestation ( evidence ) if attestationResult . isFail : print \"Attestation result forbids client creation\" return False print \"Attestation result is OK\" return True Configuration options - dcrAttestationEvidenceRequired - Boolean value indicating if DCR attestation evidence is required. Default value is false . If evidence request parameter is not present and dcrAttestationEvidenceRequired is true AS returns stale_evidence error: HTTP/1.1 400 Bad Request Content-Type: application/json Cache-Control: no-store Pragma: no-cache { \"error\": \"stale_evidence\", \"error_description\": \"The provided evidence is not current.\", \"nonce\": \"lBjvTtuPbpzIaqyiAOOkrIol3WmflPUUepzUXNDFuUgMKUL\" } It is common to get nonce value from Attestation Server. In this case set dcrAttestationEvidenceRequired=false and throw error from custom script. def createClient ( self , context ): evidenceAsString = registerRequest . getEvidence () if StringHelper . isEmpty ( evidenceAsString ) nonceFromVerifier = attestationClient . requestNonce () context . createStaleEvidenceWebApplicationException ( nonceFromVerifier ) return False ... print \"Attestation result is OK\" return True context.createStaleEvidenceWebApplicationException(nonceFromVerifier) leads to stale_evidence error creation, see example above ( nonceFromVerifier must be string value). In case goal is to create own custom error, please use standard context.createWebApplicationException methods and return False from script to prevent client creation. Example entity = < construct error message > context . createWebApplicationException ( 400 , entity )", "title": "The Use of Attestation in Dynamic Client Registration"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#dynamic-registration-custom-attributes", "text": "", "title": "Dynamic registration custom attributes"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#crud-operations", "text": "Janssen Server allows client management through client configuration endpoint (RFC 7592) . JSON response to client registration request contains registration_client_uri and registration_access_token data elements. The URI mentioned using registration_client_uri provides functionality to read, update and delete the client. This endpoint is a protected endpoint where request has to be authenticated using access token registration_access_token .", "title": "CRUD Operations"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#read-client-metadata", "text": "A read request to the same client that got created in earlier section should be as shown in the example below. HTTP method GET is used to send the request which signifies that it is a request to read client metadata. curl -k -H 'Authorization: Bearer eaee20de-54ce-4217-b960-6b72b55e6cab' \\ -i 'https://my.jans.server/jans-auth/restv1/register?client_id=85192707-a38c-496c-806c-ef01a6a3ae4a' JSON response from Janssen Server will contain the current state of client metadata.", "title": "Read client metadata"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#update-client-metadata", "text": "Client metadata can be updated by sending request with PUT HTTP method to registration_client_uri . Janssen Server replaces current metadata with the one sent with update request as outlined in the specification", "title": "Update client metadata"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#delete-client", "text": "Client can be deleted by sending a request using DELETE method to registration_client_uri . A successful delete action will invalidate the \"client_id\", \"client_secret\", and \"registration_access_token\" for this client, thereby preventing the \"client_id\" from being used at either the authorization endpoint or token endpoint of the authorization server.", "title": "Delete Client"}, {"location": "janssen-server/auth-server/endpoints/client-registration/#internationalization-for-client-metadata", "text": "", "title": "Internationalization for Client metadata"}, {"location": "janssen-server/auth-server/endpoints/clientinfo/", "tags": ["administration", "auth-server", "clientinfo", "endpoint"], "text": "Overview # /clientinfo endpoint is an OAuth2 protected endpoint that is used to retrieve claims about registered client. URL to access clientinfo endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration clientinfo_endpoint claim in the response specifies the URL for clientinfo endpoint. By default, clientinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/clientinfo Since clientinfo endpoint is an OAuth2 protected resource, a valid access token with appropriate scope is required to access the endpoint. More information about request and response of the clientinfo endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # /clientinfo endpoint can be enabled or disable using clientinfo feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable clientinfo flag as required. Configuration Properties # Clientinfo endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . clientInfoEndpoint mtlsClientInfoEndpoint Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Clientinfo"}, {"location": "janssen-server/auth-server/endpoints/clientinfo/#overview", "text": "/clientinfo endpoint is an OAuth2 protected endpoint that is used to retrieve claims about registered client. URL to access clientinfo endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration clientinfo_endpoint claim in the response specifies the URL for clientinfo endpoint. By default, clientinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/clientinfo Since clientinfo endpoint is an OAuth2 protected resource, a valid access token with appropriate scope is required to access the endpoint. More information about request and response of the clientinfo endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/clientinfo/#disabling-the-endpoint-using-feature-flag", "text": "/clientinfo endpoint can be enabled or disable using clientinfo feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable clientinfo flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/clientinfo/#configuration-properties", "text": "Clientinfo endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . clientInfoEndpoint mtlsClientInfoEndpoint", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/clientinfo/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/configuration/", "tags": ["administration", "auth-server", "well-known", "configuration", "endpoint"], "text": "OpenID Configuration Endpoint aka .well-known/openid-configuration # The Configuration Endpoint returns both the OP server metadata, and OAuth AS metdata, most of which is defined in the OpenID Discovery Spec , although other configuration metadata is defined in other OpenID specifications, or in OAuth specifications. If you want to customize the configuration response, you can use the OpenID Config Interception Script , which enables you to filter the results, modify claim values, or add claims. If you want to explicitly allow only certain OpenID Metadata claims, you can supply a list of the claims in the opConfigMetadataAllowList Auth Server Property. Below is a list of all the current available claims, and where they are specified. Claim Origin access_token_signing_alg_values_supported ? acr_values_supported OpenID authorization_encryption_alg_values_supported ? authorization_encryption_enc_values_supported ? authorization_endpoint OpenID authorization_signing_alg_values_supported ? backchannel_authentication_endpoint ? backchannel_logout_session_supported ? backchannel_logout_supported ? backchannel_token_delivery_modes_supported ? backchannel_user_code_parameter_supported ? check_session_iframe ? claim_types_supported ? claims_locales_supported ? claims_parameter_supported ? claims_supported OpenID clientinfo_endpoint ? device_authorization_endpoint ? display_values_supported ? dpop_signing_alg_values_supported ? end_session_endpoint ? frontchannel_logout_session_supported ? frontchannel_logout_supported ? grant_types_supported ? id_token_encryption_alg_values_supported ? id_token_encryption_enc_values_supported ? id_token_signing_alg_values_supported ? id_token_token_binding_cnf_values_supported ? introspection_endpoint ? issuer OpenID jwks_uri OpenID op_tos_uri OpenID pushed_authorization_request_endpoint ? registration_endpoint OpenID request_object_encryption_alg_values_supported OpenID request_object_encryption_enc_values_supported OpenID request_object_signing_alg_values_supported OpenID request_parameter_supported OpenID request_uri_parameter_supported OpenID require_pushed_authorization_requests ? require_request_uri_registration ? response_modes_supported OpenID response_types_supported OpenID revocation_endpoint ? scopes_supported ? service_documentation ? session_revocation_endpoint ? ssa_endpoint Janssen subject_types_supported OpenID tls_client_certificate_bound_access_tokens ? token_endpoint OpenID token_endpoint_auth_methods_supported OpenID token_endpoint_auth_signing_alg_values_supported OpenID ui_locales_supported OpenID userinfo_encryption_alg_values_supported OpenID userinfo_encryption_enc_values_supported OpenID userinfo_endpoint OpenID userinfo_signing_alg_values_supported OpenID Notes on specific OP Server Metadata claims # claims_supported Each user claim (in Jans jargon, \"Attribute\") has a property called jansHideOnDiscovery --if you don't want a claim to appear in .well-known/openid-configuration , set this to true for the Attribute entity. ssa_endpoint This is the endpoint which issues Software Statement Assertions JWT's. It is an OAuth protected endpoint.", "title": "OpenID Configuration"}, {"location": "janssen-server/auth-server/endpoints/configuration/#openid-configuration-endpoint-aka-well-knownopenid-configuration", "text": "The Configuration Endpoint returns both the OP server metadata, and OAuth AS metdata, most of which is defined in the OpenID Discovery Spec , although other configuration metadata is defined in other OpenID specifications, or in OAuth specifications. If you want to customize the configuration response, you can use the OpenID Config Interception Script , which enables you to filter the results, modify claim values, or add claims. If you want to explicitly allow only certain OpenID Metadata claims, you can supply a list of the claims in the opConfigMetadataAllowList Auth Server Property. Below is a list of all the current available claims, and where they are specified. Claim Origin access_token_signing_alg_values_supported ? acr_values_supported OpenID authorization_encryption_alg_values_supported ? authorization_encryption_enc_values_supported ? authorization_endpoint OpenID authorization_signing_alg_values_supported ? backchannel_authentication_endpoint ? backchannel_logout_session_supported ? backchannel_logout_supported ? backchannel_token_delivery_modes_supported ? backchannel_user_code_parameter_supported ? check_session_iframe ? claim_types_supported ? claims_locales_supported ? claims_parameter_supported ? claims_supported OpenID clientinfo_endpoint ? device_authorization_endpoint ? display_values_supported ? dpop_signing_alg_values_supported ? end_session_endpoint ? frontchannel_logout_session_supported ? frontchannel_logout_supported ? grant_types_supported ? id_token_encryption_alg_values_supported ? id_token_encryption_enc_values_supported ? id_token_signing_alg_values_supported ? id_token_token_binding_cnf_values_supported ? introspection_endpoint ? issuer OpenID jwks_uri OpenID op_tos_uri OpenID pushed_authorization_request_endpoint ? registration_endpoint OpenID request_object_encryption_alg_values_supported OpenID request_object_encryption_enc_values_supported OpenID request_object_signing_alg_values_supported OpenID request_parameter_supported OpenID request_uri_parameter_supported OpenID require_pushed_authorization_requests ? require_request_uri_registration ? response_modes_supported OpenID response_types_supported OpenID revocation_endpoint ? scopes_supported ? service_documentation ? session_revocation_endpoint ? ssa_endpoint Janssen subject_types_supported OpenID tls_client_certificate_bound_access_tokens ? token_endpoint OpenID token_endpoint_auth_methods_supported OpenID token_endpoint_auth_signing_alg_values_supported OpenID ui_locales_supported OpenID userinfo_encryption_alg_values_supported OpenID userinfo_encryption_enc_values_supported OpenID userinfo_endpoint OpenID userinfo_signing_alg_values_supported OpenID", "title": "OpenID Configuration Endpoint aka .well-known/openid-configuration"}, {"location": "janssen-server/auth-server/endpoints/configuration/#notes-on-specific-op-server-metadata-claims", "text": "claims_supported Each user claim (in Jans jargon, \"Attribute\") has a property called jansHideOnDiscovery --if you don't want a claim to appear in .well-known/openid-configuration , set this to true for the Attribute entity. ssa_endpoint This is the endpoint which issues Software Statement Assertions JWT's. It is an OAuth protected endpoint.", "title": "Notes on specific OP Server Metadata claims"}, {"location": "janssen-server/auth-server/endpoints/device-authorization/", "tags": ["administration", "auth-server", "endpoint", "device authorization", "RFC 8628"], "text": "Device Authorization endpoint # The URI to invoke the Device Authorization Endpoint in Janssen Auth Server can be found by checking the introspection_endpoint claim of the OpenID Connect configuration response, typically deployed at https://<my.jans.server>/.well-known/openid-configuration \"device_authorization_endpoint\" : \"https://<my.jans.server>/jans-auth/restv1/device_authorization\" Invoking the endpoint in Device Authorization Flow # The Device Authorization Grant defined by RFC 8628 contains a call to the Device Authorization endpoint in Step 2 of the diagram below. The details of the entire flow can be found in this article sequenceDiagram autonumber 1 title Oauth2.0 Device Authorization flow participant User participant Browser on Computer / Smartphone participant Device App participant Jans AS participant Third Party App User->>Device App:Opens an app on device Device App->>Jans AS:Sends authorization request \\n\"jans-server.com/jans-auth/restv1/device_authorization\" Jans AS->>Device App:Response - \\nuser_code, device_code, verification_url, interval, expiration Device App ->>User: Instructs the user to access Verification URL \\nand enter user_code note over Device App:Device App will keep polling AS for Access Token \\nuntil device authorization is completed loop till Device App recieves Access Token: Device App->>Jans AS:request Access Token Jans AS->>Device App:Response - \\naccess_denied \\nOR expired_token \\nOR authorization_pending \\nOR Access token end User->>Browser on Computer / Smartphone:Opens a browser \\nand access verification URL Browser on Computer / Smartphone->>Jans AS:send user_code to verification URL Jans AS -->> Browser on Computer / Smartphone :Login and authorization prompt Browser on Computer / Smartphone->>Jans AS:Authentication and consent Jans AS->>Jans AS: Mark device as Authorized note over Jans AS:Subsequent polling by the Device App \\nwill return an Access Token as indicated \\nby the loop above Device App->>Third Party App:Invoke API with Access Token Third Party App->>Device App: return Response Request: POST /restv1/device_authorization HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.org Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 client_id=123-123-123&scope=openid+profile+address+email+phone Response: HTTP/1.1 200 Content-Length: 307 Content-Type: application/json Server: Jetty(9.4.19.v20190610) { \"user_code\": \"SJFP-DTPL\", \"device_code\": \"aeb28bdc90d806ac58d4b0f832f06c3ac9c4bd03292f0c09\", \"interval\": 5, \"verification_uri_complete\": \"https://test.jans.io:8443/device-code?user_code=SJFP-DTPL\", \"verification_uri\": \"https://test.jans.io:8443/device-code\", \"expires_in\": 1800 }", "title": "Device Authorization"}, {"location": "janssen-server/auth-server/endpoints/device-authorization/#device-authorization-endpoint", "text": "The URI to invoke the Device Authorization Endpoint in Janssen Auth Server can be found by checking the introspection_endpoint claim of the OpenID Connect configuration response, typically deployed at https://<my.jans.server>/.well-known/openid-configuration \"device_authorization_endpoint\" : \"https://<my.jans.server>/jans-auth/restv1/device_authorization\"", "title": "Device Authorization endpoint"}, {"location": "janssen-server/auth-server/endpoints/device-authorization/#invoking-the-endpoint-in-device-authorization-flow", "text": "The Device Authorization Grant defined by RFC 8628 contains a call to the Device Authorization endpoint in Step 2 of the diagram below. The details of the entire flow can be found in this article sequenceDiagram autonumber 1 title Oauth2.0 Device Authorization flow participant User participant Browser on Computer / Smartphone participant Device App participant Jans AS participant Third Party App User->>Device App:Opens an app on device Device App->>Jans AS:Sends authorization request \\n\"jans-server.com/jans-auth/restv1/device_authorization\" Jans AS->>Device App:Response - \\nuser_code, device_code, verification_url, interval, expiration Device App ->>User: Instructs the user to access Verification URL \\nand enter user_code note over Device App:Device App will keep polling AS for Access Token \\nuntil device authorization is completed loop till Device App recieves Access Token: Device App->>Jans AS:request Access Token Jans AS->>Device App:Response - \\naccess_denied \\nOR expired_token \\nOR authorization_pending \\nOR Access token end User->>Browser on Computer / Smartphone:Opens a browser \\nand access verification URL Browser on Computer / Smartphone->>Jans AS:send user_code to verification URL Jans AS -->> Browser on Computer / Smartphone :Login and authorization prompt Browser on Computer / Smartphone->>Jans AS:Authentication and consent Jans AS->>Jans AS: Mark device as Authorized note over Jans AS:Subsequent polling by the Device App \\nwill return an Access Token as indicated \\nby the loop above Device App->>Third Party App:Invoke API with Access Token Third Party App->>Device App: return Response Request: POST /restv1/device_authorization HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.org Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 client_id=123-123-123&scope=openid+profile+address+email+phone Response: HTTP/1.1 200 Content-Length: 307 Content-Type: application/json Server: Jetty(9.4.19.v20190610) { \"user_code\": \"SJFP-DTPL\", \"device_code\": \"aeb28bdc90d806ac58d4b0f832f06c3ac9c4bd03292f0c09\", \"interval\": 5, \"verification_uri_complete\": \"https://test.jans.io:8443/device-code?user_code=SJFP-DTPL\", \"verification_uri\": \"https://test.jans.io:8443/device-code\", \"expires_in\": 1800 }", "title": "Invoking the endpoint in Device Authorization Flow"}, {"location": "janssen-server/auth-server/endpoints/end-session/", "tags": ["administration", "auth-server", "end-session", "endpoint"], "text": "Overview # Janssen Server's /end_session endpoint supports logout using OpenId Connect RP-initiated Logout mechanism. When using OpenID Connect Logout, it is recommended to use Front-Channel Logout. In Front-Channel Logout the browser receives a page with a list of application logout urls within an iframe. This prompts the browser to call each application logout individually and the OpenID Connect end-session endpoint via Javascript. URL to access end session endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration end_session_endpoint claim in the response specifies the URL for end session endpoint. By default, end session ndpoint looks like below: https://janssen.server.host/jans-auth/restv1/end_session Refer to this article from Gluu Server documentation to understand how end session endpoint works in Janssen Server. More information about request and response of the end session endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # /end_session endpoint can be enabled or disable using END_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable END_SESSION flag as required. Configuration Properties # End session endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . allowEndSessionWithUnmatchedSid endSessionEndpoint endSessionWithAccessToken mtlsEndSessionEndpoint rejectEndSessionIfIdTokenExpired allowPostLogoutRedirectWithoutValidation forceIdTokenHintPresence Apart from the above-mentioned server properties, the properties relevant to individual clients can be configured during client registration or can be edited later. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Clients -> logout as show in image below: Interception Scripts # Response from end session endpoint can be further customized using end session interception script. This script can be used to customize the HTML response generated from end session endpoint. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "End Session"}, {"location": "janssen-server/auth-server/endpoints/end-session/#overview", "text": "Janssen Server's /end_session endpoint supports logout using OpenId Connect RP-initiated Logout mechanism. When using OpenID Connect Logout, it is recommended to use Front-Channel Logout. In Front-Channel Logout the browser receives a page with a list of application logout urls within an iframe. This prompts the browser to call each application logout individually and the OpenID Connect end-session endpoint via Javascript. URL to access end session endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration end_session_endpoint claim in the response specifies the URL for end session endpoint. By default, end session ndpoint looks like below: https://janssen.server.host/jans-auth/restv1/end_session Refer to this article from Gluu Server documentation to understand how end session endpoint works in Janssen Server. More information about request and response of the end session endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/end-session/#disabling-the-endpoint-using-feature-flag", "text": "/end_session endpoint can be enabled or disable using END_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable END_SESSION flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/end-session/#configuration-properties", "text": "End session endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . allowEndSessionWithUnmatchedSid endSessionEndpoint endSessionWithAccessToken mtlsEndSessionEndpoint rejectEndSessionIfIdTokenExpired allowPostLogoutRedirectWithoutValidation forceIdTokenHintPresence Apart from the above-mentioned server properties, the properties relevant to individual clients can be configured during client registration or can be edited later. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Clients -> logout as show in image below:", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/end-session/#interception-scripts", "text": "Response from end session endpoint can be further customized using end session interception script. This script can be used to customize the HTML response generated from end session endpoint.", "title": "Interception Scripts"}, {"location": "janssen-server/auth-server/endpoints/end-session/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/global-token-revocation/", "tags": ["administration", "auth-server", "session-revocation", "endpoint"], "text": "Overview # Janssen Server provides global token revocation endpoint to enable the client to revoke all tokens and sessions of a user. Janssen Server provides this endpoint to allow greater control and better management of sessions on OP. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration global_token_revocation_endpoint claim in the response specifies the URL for global token revocation endpoint. By default, global token revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/global-token-revocation More information about request and response of the global token revocation endpoint can be found in the OpenAPI specification of jans-auth-server module . Usage # A request to this endpoint can revoke all tokens and sessions of one particular user. Use the request parameters to specify criteria to select the user. If there are multiple users matching the given criteria, the first found user will be affected. View full sample execution log here Disabling The Endpoint Using Feature Flag # Global Token Revocation endpoint can be enabled or disable using GLOBAL_TOKEN_REVOCATION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable GLOBAL_TOKEN_REVOCATION flag as required. Required Scopes # A client must have the following scope in order to use this endpoint: global_token_revocation", "title": "Global Token Revocation"}, {"location": "janssen-server/auth-server/endpoints/global-token-revocation/#overview", "text": "Janssen Server provides global token revocation endpoint to enable the client to revoke all tokens and sessions of a user. Janssen Server provides this endpoint to allow greater control and better management of sessions on OP. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration global_token_revocation_endpoint claim in the response specifies the URL for global token revocation endpoint. By default, global token revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/global-token-revocation More information about request and response of the global token revocation endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/global-token-revocation/#usage", "text": "A request to this endpoint can revoke all tokens and sessions of one particular user. Use the request parameters to specify criteria to select the user. If there are multiple users matching the given criteria, the first found user will be affected. View full sample execution log here", "title": "Usage"}, {"location": "janssen-server/auth-server/endpoints/global-token-revocation/#disabling-the-endpoint-using-feature-flag", "text": "Global Token Revocation endpoint can be enabled or disable using GLOBAL_TOKEN_REVOCATION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable GLOBAL_TOKEN_REVOCATION flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/global-token-revocation/#required-scopes", "text": "A client must have the following scope in order to use this endpoint: global_token_revocation", "title": "Required Scopes"}, {"location": "janssen-server/auth-server/endpoints/introspection/", "tags": ["administration", "auth-server", "endpoint", "introspection", "accessTokenAsJwt", "introspectionScriptBackwardCompatibility"], "text": "Introspection Endpoint # Introspection endpoint allows a protected resource to determine the active state of an OAuth 2.0 token and to determine meta-information about this token. This endpoint can be used to introspect both opaque token (i.e. reference tokens) and structured tokens(i.e. value tokens). This endpoint conforms to OAuth2 token introspection specifications. The URI to invoke the introspection endpoint in Janssen Server can be found by checking the introspection_endpoint claim of the OpenID Connect configuration response, typically deployed at https://janssen.server.host/.well-known/openid-configuration \"introspection_endpoint\" : \"https://janssen.server.host/jans-auth/restv1/introspection\" ` More information about request and response of the Introspection endpoint can be found in the OpenAPI specification of jans-auth-server module . Request parameters token - REQUIRED. The string value of the token. For access tokens, this is the \"access_token\" value returned from the token endpoint token_type_hint - OPTIONAL. A hint about the type of the token submitted for introspection. Not used in current implementation of the AS. response_as_jwt - OPTIONAL. Boolean value with default value false. If true, returns introspection response as JWT (signed based on client configuration used for authentication to Introspection Endpoint). Sample GET Request # Request # curl -X 'GET' 'https://janssen.server.host/jans-auth/restv1/introspection?token=368fea2b-be14-4d30-bd57-bcc4cde2033c&response_as_jwt=false' -H 'accept: application/json' -H \"Authorization: Bearer 111d51a4-2828-4b47-abce-77034cddcfb5\" Response # { \"sub\" : \"\" , \"iss\" : \"https://janssen.server.host\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"1800.df1bb233-10b8-40ed-bbb9-07da50892a35\" , \"aud\" : \"1800.df1bb233-10b8-40ed-bbb9-07da50892a35\" , \"nbf\" : null , \"scope\" : \"https://jans.io/oauth/config/scripts.write\" , \"acr_values\" : null , \"cnf\" : null , \"exp\" : 1668705523 , \"iat\" : 1668705223 , \"jti\" : null , \"username\" : null } Sample POST Request # Request # curl -X 'POST' \\ 'https://janssen.server.host/jans-auth/restv1/introspection' \\ -H 'accept: application/json' \\ -H 'Content-Type: application/x-www-form-urlencoded' \\ -d 'token=eyJra....3ZkB-Ajwg' -H \"Authorization: Bearer eyJra...BpKo7g\" Response # { \"sub\" : \"\" , \"iss\" : \"https://janssen.server.host\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad\" , \"aud\" : \"3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad\" , \"nbf\" : null , \"scope\" : \"\" , \"acr_values\" : null , \"cnf\" : null , \"exp\" : 1668941216 , \"iat\" : 1668781885 , \"jti\" : null , \"username\" : null } Response as JWT # Response is returned as JWT if Accept header has value application/token-introspection+jwt or otherwise if explicit endpoint parameter response_as_jwt is set to true . POST /introspect HTTP/1.1 Host: as.example.com Accept: application/token-introspection+jwt Sample decoded JWT payload { \"iss\" : \"https://as.example.com/\" , \"aud\" : \"https://rs.example.com/resource\" , \"iat\" : 1514797892 , \"token_introspection\" : { \"active\" : true , \"iss\" : \"https://as.example.com/\" , \"aud\" : \"https://rs.example.com/resource\" , \"iat\" : 1514797822 , \"exp\" : 1514797942 , \"client_id\" : \"paiB2goo0a\" , \"scope\" : \"read write dolphin\" , \"sub\" : \"Z5O3upPC88QrAjx00dis\" , \"birthdate\" : \"1982-02-01\" , \"given_name\" : \"John\" , \"family_name\" : \"Doe\" , \"jti\" : \"t1FoCCaZd4Xv4ORJUWVUeTZfsKhW30CQCrWDDjwXy6w\" } } Sample response (line breaks in payload is for convenience) HTTP/1.1 200 OK Content-Type: application/token-introspection+jwt eyJraWQiOiJ3RzZEIiwidHlwIjoidG9rZW4taW50cm9zcGVjdGlvbitqd3QiLCJhbGc iOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6I mh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcmVzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4OTIs InRva2VuX2ludHJvc3BlY3Rpb24iOnsiYWN0aXZlIjp0cnVlLCJpc3MiOiJodHRwczo vL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6Imh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcm Vzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4MjIsImV4cCI6MTUxNDc5Nzk0MiwiY2xpZW50X 2lkIjoicGFpQjJnb28wYSIsInNjb3BlIjoicmVhZCB3cml0ZSBkb2xwaGluIiwic3Vi IjoiWjVPM3VwUEM4OFFyQWp4MDBkaXMiLCJiaXJ0aGRhdGUiOiIxOTgyLTAyLTAxIiw iZ2l2ZW5fbmFtZSI6IkpvaG4iLCJmYW1pbHlfbmFtZSI6IkRvZSIsImp0aSI6InQxRm 9DQ2FaZDRYdjRPUkpVV1ZVZVRaZnNLaFczMENRQ3JXRERqd1h5NncifX0.przJMU5Gh mNzvwtt1Sr-xa9xTkpiAg5IshbQsRiRVP_7eGR1GHYrNwQh84kxOkHCyje2g5WSRcYo sGEVIiC-eoPJJ-qBwqwSlgx9JEeCDw2W5DjrblOI_N0Jvsq_dUeOyoWVMqlOydOBhKN Y0smBrI4NZvEExucOm9WUJXMuJtvq1gBes-0go5j4TEv9sOP9uu81gqWTr_LOo6pgT0 tFFyZfWC4kbXPXiQ2YT6mxCiQRRNM-l9cBdF6Jx6IOrsfFhBuYdYQ_mlL19HgDDOFal eyqmru6lKlASOsaE8dmLSeKcX91FbG79FKN8un24iwIDCbKT9xlUFl54xWVShNDFA Disabling The Endpoint Using Feature Flag # /introspection endpoint can be enabled or disable using END_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable INTROSPECTION flag as required. Configuration Properties # Introspection endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . introspectionEndpoint mtlsIntrospectionEndpoint introspectionSkipAuthorization introspectionScriptBackwardCompatibility introspectionAccessTokenMustHaveUmaProtectionScope introspectionAccessTokenMustHaveIntrospectionScope introspectionResponseScopesBackwardCompatibility There difference between introspectionAccessTokenMustHaveUmaProtectionScope and introspectionAccessTokenMustHaveIntrospectionScope is that uma_protection scope is enabled for Dynamic Client Registration while introspection scope is not. Thus if set introspectionAccessTokenMustHaveIntrospectionScope to true value allows disable access to Introspection Endpoint to all clients which does not have explicitly granted introspection scope. Customising Introspection Endpoint Behaviour using Custom script: # Customizing certain aspects of endpoint behaviour, for example, one can modify claims of an access token as JWT, using introspection scripts . Use update token introspection script for transformation of claims and values in id-token and access-token. Configure below-mentioned client properties to enable usage of introspection scripts. When using Janssen Text-based UI(TUI) to configure these client properties, navigate to accessTokenAsJwt : Auth Server -> Clients ->select the client-> Tokens -> Access Token Type ->Select JWT runIntrospectionScriptBeforeJwtCreation : Auth Server -> Clients ->select the client-> Tokens ->enable Run Introspection Script before JWT access token creation References for custom scripts # Interface - IntrospectionType Introspection scripts Introspection script vs Update Token Script", "title": "Introspection"}, {"location": "janssen-server/auth-server/endpoints/introspection/#introspection-endpoint", "text": "Introspection endpoint allows a protected resource to determine the active state of an OAuth 2.0 token and to determine meta-information about this token. This endpoint can be used to introspect both opaque token (i.e. reference tokens) and structured tokens(i.e. value tokens). This endpoint conforms to OAuth2 token introspection specifications. The URI to invoke the introspection endpoint in Janssen Server can be found by checking the introspection_endpoint claim of the OpenID Connect configuration response, typically deployed at https://janssen.server.host/.well-known/openid-configuration \"introspection_endpoint\" : \"https://janssen.server.host/jans-auth/restv1/introspection\" ` More information about request and response of the Introspection endpoint can be found in the OpenAPI specification of jans-auth-server module . Request parameters token - REQUIRED. The string value of the token. For access tokens, this is the \"access_token\" value returned from the token endpoint token_type_hint - OPTIONAL. A hint about the type of the token submitted for introspection. Not used in current implementation of the AS. response_as_jwt - OPTIONAL. Boolean value with default value false. If true, returns introspection response as JWT (signed based on client configuration used for authentication to Introspection Endpoint).", "title": "Introspection Endpoint"}, {"location": "janssen-server/auth-server/endpoints/introspection/#sample-get-request", "text": "", "title": "Sample GET Request"}, {"location": "janssen-server/auth-server/endpoints/introspection/#request", "text": "curl -X 'GET' 'https://janssen.server.host/jans-auth/restv1/introspection?token=368fea2b-be14-4d30-bd57-bcc4cde2033c&response_as_jwt=false' -H 'accept: application/json' -H \"Authorization: Bearer 111d51a4-2828-4b47-abce-77034cddcfb5\"", "title": "Request"}, {"location": "janssen-server/auth-server/endpoints/introspection/#response", "text": "{ \"sub\" : \"\" , \"iss\" : \"https://janssen.server.host\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"1800.df1bb233-10b8-40ed-bbb9-07da50892a35\" , \"aud\" : \"1800.df1bb233-10b8-40ed-bbb9-07da50892a35\" , \"nbf\" : null , \"scope\" : \"https://jans.io/oauth/config/scripts.write\" , \"acr_values\" : null , \"cnf\" : null , \"exp\" : 1668705523 , \"iat\" : 1668705223 , \"jti\" : null , \"username\" : null }", "title": "Response"}, {"location": "janssen-server/auth-server/endpoints/introspection/#sample-post-request", "text": "", "title": "Sample POST Request"}, {"location": "janssen-server/auth-server/endpoints/introspection/#request_1", "text": "curl -X 'POST' \\ 'https://janssen.server.host/jans-auth/restv1/introspection' \\ -H 'accept: application/json' \\ -H 'Content-Type: application/x-www-form-urlencoded' \\ -d 'token=eyJra....3ZkB-Ajwg' -H \"Authorization: Bearer eyJra...BpKo7g\"", "title": "Request"}, {"location": "janssen-server/auth-server/endpoints/introspection/#response_1", "text": "{ \"sub\" : \"\" , \"iss\" : \"https://janssen.server.host\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad\" , \"aud\" : \"3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad\" , \"nbf\" : null , \"scope\" : \"\" , \"acr_values\" : null , \"cnf\" : null , \"exp\" : 1668941216 , \"iat\" : 1668781885 , \"jti\" : null , \"username\" : null }", "title": "Response"}, {"location": "janssen-server/auth-server/endpoints/introspection/#response-as-jwt", "text": "Response is returned as JWT if Accept header has value application/token-introspection+jwt or otherwise if explicit endpoint parameter response_as_jwt is set to true . POST /introspect HTTP/1.1 Host: as.example.com Accept: application/token-introspection+jwt Sample decoded JWT payload { \"iss\" : \"https://as.example.com/\" , \"aud\" : \"https://rs.example.com/resource\" , \"iat\" : 1514797892 , \"token_introspection\" : { \"active\" : true , \"iss\" : \"https://as.example.com/\" , \"aud\" : \"https://rs.example.com/resource\" , \"iat\" : 1514797822 , \"exp\" : 1514797942 , \"client_id\" : \"paiB2goo0a\" , \"scope\" : \"read write dolphin\" , \"sub\" : \"Z5O3upPC88QrAjx00dis\" , \"birthdate\" : \"1982-02-01\" , \"given_name\" : \"John\" , \"family_name\" : \"Doe\" , \"jti\" : \"t1FoCCaZd4Xv4ORJUWVUeTZfsKhW30CQCrWDDjwXy6w\" } } Sample response (line breaks in payload is for convenience) HTTP/1.1 200 OK Content-Type: application/token-introspection+jwt eyJraWQiOiJ3RzZEIiwidHlwIjoidG9rZW4taW50cm9zcGVjdGlvbitqd3QiLCJhbGc iOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6I mh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcmVzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4OTIs InRva2VuX2ludHJvc3BlY3Rpb24iOnsiYWN0aXZlIjp0cnVlLCJpc3MiOiJodHRwczo vL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6Imh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcm Vzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4MjIsImV4cCI6MTUxNDc5Nzk0MiwiY2xpZW50X 2lkIjoicGFpQjJnb28wYSIsInNjb3BlIjoicmVhZCB3cml0ZSBkb2xwaGluIiwic3Vi IjoiWjVPM3VwUEM4OFFyQWp4MDBkaXMiLCJiaXJ0aGRhdGUiOiIxOTgyLTAyLTAxIiw iZ2l2ZW5fbmFtZSI6IkpvaG4iLCJmYW1pbHlfbmFtZSI6IkRvZSIsImp0aSI6InQxRm 9DQ2FaZDRYdjRPUkpVV1ZVZVRaZnNLaFczMENRQ3JXRERqd1h5NncifX0.przJMU5Gh mNzvwtt1Sr-xa9xTkpiAg5IshbQsRiRVP_7eGR1GHYrNwQh84kxOkHCyje2g5WSRcYo sGEVIiC-eoPJJ-qBwqwSlgx9JEeCDw2W5DjrblOI_N0Jvsq_dUeOyoWVMqlOydOBhKN Y0smBrI4NZvEExucOm9WUJXMuJtvq1gBes-0go5j4TEv9sOP9uu81gqWTr_LOo6pgT0 tFFyZfWC4kbXPXiQ2YT6mxCiQRRNM-l9cBdF6Jx6IOrsfFhBuYdYQ_mlL19HgDDOFal eyqmru6lKlASOsaE8dmLSeKcX91FbG79FKN8un24iwIDCbKT9xlUFl54xWVShNDFA", "title": "Response as JWT"}, {"location": "janssen-server/auth-server/endpoints/introspection/#disabling-the-endpoint-using-feature-flag", "text": "/introspection endpoint can be enabled or disable using END_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable INTROSPECTION flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/introspection/#configuration-properties", "text": "Introspection endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . introspectionEndpoint mtlsIntrospectionEndpoint introspectionSkipAuthorization introspectionScriptBackwardCompatibility introspectionAccessTokenMustHaveUmaProtectionScope introspectionAccessTokenMustHaveIntrospectionScope introspectionResponseScopesBackwardCompatibility There difference between introspectionAccessTokenMustHaveUmaProtectionScope and introspectionAccessTokenMustHaveIntrospectionScope is that uma_protection scope is enabled for Dynamic Client Registration while introspection scope is not. Thus if set introspectionAccessTokenMustHaveIntrospectionScope to true value allows disable access to Introspection Endpoint to all clients which does not have explicitly granted introspection scope.", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/introspection/#customising-introspection-endpoint-behaviour-using-custom-script", "text": "Customizing certain aspects of endpoint behaviour, for example, one can modify claims of an access token as JWT, using introspection scripts . Use update token introspection script for transformation of claims and values in id-token and access-token. Configure below-mentioned client properties to enable usage of introspection scripts. When using Janssen Text-based UI(TUI) to configure these client properties, navigate to accessTokenAsJwt : Auth Server -> Clients ->select the client-> Tokens -> Access Token Type ->Select JWT runIntrospectionScriptBeforeJwtCreation : Auth Server -> Clients ->select the client-> Tokens ->enable Run Introspection Script before JWT access token creation", "title": "Customising Introspection Endpoint Behaviour using Custom script:"}, {"location": "janssen-server/auth-server/endpoints/introspection/#references-for-custom-scripts", "text": "Interface - IntrospectionType Introspection scripts Introspection script vs Update Token Script", "title": "References for custom scripts"}, {"location": "janssen-server/auth-server/endpoints/jwks-uri/", "tags": ["administration", "auth-server", "jwks", "json-web-key-set", "endpoint"], "text": "Overview # Janssen Server supports /jwks metadata endpoint and publishes its JSON Web Key Set (JWKS) at this endpoint. This endpoint publishes signing keys as well as encryption keys used by Janssen Server. RP can use these keys to validate signatures from Janssen Server, and also to perform encryption and decryption. Like other metadata endpoints, this is not a secure endpoint. Further details on this endpoint and JWKs can be found in OpenID Connect Discovery specification. URL to access jwks endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration jwks_uri claim in the response specifies the URL for jwks endpoint. By default, the jwks endpoint looks like below: https://janssen.server.host/jans-auth/restv1/jwks This endpoint is always enabled and can not be disabled using feature flags. Configuration Properties # End session endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . jwksUri jwksAlgorithmsSupported mtlsJwksUri Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "JWKS URI"}, {"location": "janssen-server/auth-server/endpoints/jwks-uri/#overview", "text": "Janssen Server supports /jwks metadata endpoint and publishes its JSON Web Key Set (JWKS) at this endpoint. This endpoint publishes signing keys as well as encryption keys used by Janssen Server. RP can use these keys to validate signatures from Janssen Server, and also to perform encryption and decryption. Like other metadata endpoints, this is not a secure endpoint. Further details on this endpoint and JWKs can be found in OpenID Connect Discovery specification. URL to access jwks endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration jwks_uri claim in the response specifies the URL for jwks endpoint. By default, the jwks endpoint looks like below: https://janssen.server.host/jans-auth/restv1/jwks This endpoint is always enabled and can not be disabled using feature flags.", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/jwks-uri/#configuration-properties", "text": "End session endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . jwksUri jwksAlgorithmsSupported mtlsJwksUri", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/jwks-uri/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/par/", "tags": ["administration", "auth-server", "par", "pushed authorization requests", "endpoint"], "text": "Pushed Authorization Request (PAR) Endpoint # PAR endpoint is used by client to send authorization request directly to the Janssen Server without using the usual redirection mechanism via user agent. When PAR endpoint receives a valid request, it responds with a request URI. The request URI is a reference created and stored by Janssen Server. It is a reference to authorization request and the metadata sent with it by the client. Client can send this request uri to the Janssen Server in a authorization request using user agent redirect mechanism. There are multiple benefits of using this flow which are described along with other details in PAR specification . Janssen Server PAR implementation conforms to PAR specification. URL to access PAR endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration pushed_authorization_request_endpoint claim in the response specifies the URL for the PAR endpoint. By default, PAR endpoint looks like below: https://jans-dynamic-mysql/jans-auth/restv1/par In response to a valid request, the PAR endpoint returns request_uri in response similar to below: HTTP/1.1 201 Created Content-Type: application/json Cache-Control: no-cache, no-store { \"request_uri\": \"urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c\", \"expires_in\": 60 } Since PAR endpoint is a protected resource. The client has to authenticate itself to the endpoint. Authentication methods used are same as the once used for client authentication at token endpoint . More information about request and response of the PAR endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # PAR endpoint can be enabled or disabled using PAR feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable PAR flag as required. Configuration Properties # Global Janssen Server configuration properties # PAR endpoint can be further configured using Janssen Server configuration properties listed below. It can be configured via Janssen Text-based UI(TUI) (navigate to Auth Server -> Properties ), admin UI or directly in persistence layer. mtlsParEndpoint - Mutual TLS (mTLS) Pushed Authorization Requests (PAR) endpoint URL parEndpoint - Pushed Authorization Requests (PAR) Endpoint location requirePar - Boolean value to indicate whether Pushed Authorisation Request (PAR) endpoint is required requestUriParameterSupported - Boolean value specifying whether the OP supports use of the request_uri parameter Client specific PAR related configuration properties # Some configuration properties are configured on client level to allow more granular configuration which depends on client. par_lifetime - PAR object lifetime in seconds. If value is not specified then defaults to 600 value. require_par - specified whether all authorization requests made by this client to Authorization Endpoint must be PAR. If true and authorization request is not PAR then error is returned back by Authorization Server. Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "PAR"}, {"location": "janssen-server/auth-server/endpoints/par/#pushed-authorization-request-par-endpoint", "text": "PAR endpoint is used by client to send authorization request directly to the Janssen Server without using the usual redirection mechanism via user agent. When PAR endpoint receives a valid request, it responds with a request URI. The request URI is a reference created and stored by Janssen Server. It is a reference to authorization request and the metadata sent with it by the client. Client can send this request uri to the Janssen Server in a authorization request using user agent redirect mechanism. There are multiple benefits of using this flow which are described along with other details in PAR specification . Janssen Server PAR implementation conforms to PAR specification. URL to access PAR endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration pushed_authorization_request_endpoint claim in the response specifies the URL for the PAR endpoint. By default, PAR endpoint looks like below: https://jans-dynamic-mysql/jans-auth/restv1/par In response to a valid request, the PAR endpoint returns request_uri in response similar to below: HTTP/1.1 201 Created Content-Type: application/json Cache-Control: no-cache, no-store { \"request_uri\": \"urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c\", \"expires_in\": 60 } Since PAR endpoint is a protected resource. The client has to authenticate itself to the endpoint. Authentication methods used are same as the once used for client authentication at token endpoint . More information about request and response of the PAR endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Pushed Authorization Request (PAR) Endpoint"}, {"location": "janssen-server/auth-server/endpoints/par/#disabling-the-endpoint-using-feature-flag", "text": "PAR endpoint can be enabled or disabled using PAR feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable PAR flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/par/#configuration-properties", "text": "", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/par/#global-janssen-server-configuration-properties", "text": "PAR endpoint can be further configured using Janssen Server configuration properties listed below. It can be configured via Janssen Text-based UI(TUI) (navigate to Auth Server -> Properties ), admin UI or directly in persistence layer. mtlsParEndpoint - Mutual TLS (mTLS) Pushed Authorization Requests (PAR) endpoint URL parEndpoint - Pushed Authorization Requests (PAR) Endpoint location requirePar - Boolean value to indicate whether Pushed Authorisation Request (PAR) endpoint is required requestUriParameterSupported - Boolean value specifying whether the OP supports use of the request_uri parameter", "title": "Global Janssen Server configuration properties"}, {"location": "janssen-server/auth-server/endpoints/par/#client-specific-par-related-configuration-properties", "text": "Some configuration properties are configured on client level to allow more granular configuration which depends on client. par_lifetime - PAR object lifetime in seconds. If value is not specified then defaults to 600 value. require_par - specified whether all authorization requests made by this client to Authorization Endpoint must be PAR. If true and authorization request is not PAR then error is returned back by Authorization Server.", "title": "Client specific PAR related configuration properties"}, {"location": "janssen-server/auth-server/endpoints/par/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/endpoints/par/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/endpoints/session-revocation/", "tags": ["administration", "auth-server", "session-revocation", "endpoint"], "text": "Overview # Janssen Server provides session revocation endpoint to enable the client to revoke all sessions of a users. Though not being part of any industry standard/specification, Janssen Server provides this endpoint to allow greater control and better management of sessions on OP. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration session_revocation_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/revoke_session More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module . Usage # A request to this endpoint can revoke all sessions of one particular user. Use the request parameters to specify criteria to select the user. If there are multiple users matching the given criteria, the first found user will be affected. Disabling The Endpoint Using Feature Flag # Session revocation endpoint can be enabled or disable using REVOKE_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable REVOKE_SESSION flag as required. Required Scopes # A client must have the following scope in order to use this endpoint: revoke_session", "title": "Session Revocation"}, {"location": "janssen-server/auth-server/endpoints/session-revocation/#overview", "text": "Janssen Server provides session revocation endpoint to enable the client to revoke all sessions of a users. Though not being part of any industry standard/specification, Janssen Server provides this endpoint to allow greater control and better management of sessions on OP. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration session_revocation_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/revoke_session More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/session-revocation/#usage", "text": "A request to this endpoint can revoke all sessions of one particular user. Use the request parameters to specify criteria to select the user. If there are multiple users matching the given criteria, the first found user will be affected.", "title": "Usage"}, {"location": "janssen-server/auth-server/endpoints/session-revocation/#disabling-the-endpoint-using-feature-flag", "text": "Session revocation endpoint can be enabled or disable using REVOKE_SESSION feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable REVOKE_SESSION flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/session-revocation/#required-scopes", "text": "A client must have the following scope in order to use this endpoint: revoke_session", "title": "Required Scopes"}, {"location": "janssen-server/auth-server/endpoints/ssa/", "tags": ["administration", "auth-server", "SSA", "endpoint"], "text": "Software Statement Assertion (SSA) # Janssen Server provides SSA endpoint that enables management of SSAs. The SSA is a JSON Web Token (JWT) containing client metadata and some custom attributes. Specification for SSAs has been outlined as part of Dynamic Client Registration Protocol . URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration ssa_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/ssa More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # /ssa endpoint can be enabled or disable using SSA feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable SSA flag as required. Configuration Properties # SSA endpoint can be further configured using Janssen Server configuration property ssaConfiguration . When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties to update value for this property. This property take JSON configuration with parameters as described below: \"ssaConfiguration\": { \"ssaEndpoint\": \"{{your-url}}/ssa\", \"ssaCustomAttributes\": [ \"myCustomAttr1\", \"myCustomAttr2\", ... ], \"ssaSigningAlg\": \"RS512\", \"ssaExpirationInDays\": 30 } ssaEndpoint \u2014 Base endpoint for SSA. ssaCustomAttributes \u2014 List of custom attributes, which are received in the request when creating an SSA. ssaSigningAlg \u2014 Algorithm to sign the JWT that is returned after creating an SSA. ssaExpirationInDays \u2014 Expiration expressed in days, when an SSA is created and the expiration is not sent. SSA Security # To call SSA services, a token of type client_credentials must be generated with the following scopes enabled: https://jans.io/auth/ssa.admin \u2014 Allows calling all SSA services. https://jans.io/auth/ssa.portal \u2014 Allows only call Get SSA service. https://jans.io/auth/ssa.developer \u2014 Allows only call Get SSA , but you can only filter ssa that have been created by the same client. Create a new SSA # Create SSA for the organization with expiration (optional). Request body description # Field Detail Optional org_id The \"org_id\" is used for organization identification. false description Describe SSA false software_id The \"software_id\" is used for software identification. false software_roles List of string values, fixed value [\"password\", \"notify\"] . false grant_types Fixed value Fixed value [\"client_credentials\"] . false expiration Expiration date. (Default value: calculated based on global SSA settings) true one_time_use Defined whether the SSA will be used only once or can be used multiple times. (Default value: true) true rotate_ssa TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. (Default value: true) true lifetime SSA Lifetime in seconds true Note: You can add more custom attributes in the request, (you must have previously configured in the SSA global configuration). It should be clarified that these values are persisted in the database and are not returned in the SSA JWT. Example: { \"org_id\": \"your-org-id\", \"description\": \"your description\", ..., \"myCustomAttr1\": \"Your value custom attr 1\", \"myCustomAttr2\": \"Your value custom attr 2\" } Response description # Returned SSA is a JWT, containing the following structure: { \"ssa\": \"eyJraWQiOiI1NTk3MGFkZS00M2MwLTQ4YWMtODEyZi0yZTY1MzhjMTEyN2Zfc2lnX3JzNTEyIiwidHlwIjoiand0IiwiYWxnIjoiUlM1MTIifQ.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoxLCJpc3MiOiJodHRwczovL2phbnMubG9jYWxob3N0Iiwic29mdHdhcmVfcm9sZXMiOlsicGFzc3d1cmQiXSwiZXhwIjoxNjY4NjA5MDA1LCJpYXQiOjE2Njg2NDE5NjcsImp0aSI6ImU4OWVjYTQxLTM0ODUtNDUxNi1hMTYyLWZiODYyNjJhYmFjMyJ9.jRgh8_aiwMTJxeT9cwfup9QP9LBc6gQstvabCzUOJvELnzosxiNJHeU2mrvavaNK6BGvs_lbNjODVDeetGCD48_F2ay9r8qmo-f3GPzdzcJozKgfzonSkAE5Ran9LKcQQJpVc1rDYcV2xYiJLJ6FSuvnoClkDEE1tXysxshLPs-GXOZE7rD8XUXzezuxZWUE1jXwA-EFajoat8CP6QulHGxlcn_sKIhawhGODxJPz4Pf3jgeZVLG_7HfRJgxNiKcdzQIxnkbdpuS-0Q4-oc5yntsXhFhn31Pa3vGsiPPH9f3ndL2ZZKk3xCgyImLDJuGaxXg-qEVoIG4zNWNHMUNUQ\" } Header alg \u2014 The signature algorithm which used RS256 . typ \u2014 The type which used. kid \u2014 The key identification gluu-scan-api-rs256-ssa-signature-key . Payload iat \u2014 The time the JWT was created. iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. software_id \u2014 The \"software_id\" is used for software identification. org_id \u2014 The \"org_id\" is used for organization identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . lifetime \u2014 SSA lifetime in seconds. exp \u2014 Expiration Time. myCustom1, myCustom2, ... : if you have custom attributes, they will be displayed here. Example: # Request: POST {{your-url}}/ssa Content-Type: application/json Authorization: Bearer {{your-token}} { \"org_id\": \"your-org-id\", \"description\": \"This is test description\", \"software_id\": \"gluu-scan-api\", \"software_roles\": [ \"passwurd\" ], \"grant_types\": [ \"client_credentials\" ], \"expiration\": \"1696799089\", \"one_time_use\": false, \"rotate_ssa\": false, \"lifetime\": 86400 } Response: HTTP/1.1 201 Created Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 757 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" } Get SSA # Get existing active SSA based on jti or org_id . Query Parameters # jti \u2014 Unique identifier org_id \u2014 Organization ID Response description # [ { \"ssa\": { \"jti\": \"c3eb1c16-be9b-4e96-974e-aea5e3cf95b0\", \"org_id\": 1, \"software_id\": \"gluu-scan-api\", \"software_roles\": [ \"password\" ], \"grant_types\": [ \"client_credentials\" ], \"iss\": \"https://jans.localhost\", \"exp\": 1668608852, \"iat\": 1668608851, \"description: \"test description\", \"one_time_use\": true, \"rotate_ssa\": false, \"lifetime\": 86400 }, \"iss\": \"ed4d5f74-ce41-4180-aed4-54cffa974630\", \"created_at\": 1668608851, \"expiration\": 1668608852, \"status\": \"ACTIVE\" } ] SSA jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. org_id \u2014 The \"org_id\" is used for organization identification. software_id \u2014 The \"software_id\" is used for software identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. exp \u2014 Expiration time. iat \u2014 Creation time. description \u2014 Describe SSA. one_time_use \u2014 Defined whether the SSA will be used only once or can be used multiple times. rotate_ssa \u2014 TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. lifetime \u2014 SSA lifetime in seconds. myCustom1, myCustom2, ... \u2014 if you have custom attributes, they will be displayed here. iss \u2014 The \"iss\" is related to the client that created this SSA. created_at \u2014 Creation time. expiration \u2014 Expiration time. status \u2014 SSA status ( ACTIVE , USED , EXPIRED or REVOKED ). Example: # Request: Get SSA using jti . GET {{your-url}}/ssa?jti={{your-jti}} Content-Type: application/json Authorization: Bearer {{your-token}} Get SSA using org_id . GET {{your-url}}/ssa?org_id={{your-org_id}} Content-Type: application/json Authorization: Bearer {{your-token}} Response: HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 432 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive [ { \"ssa\": { \"software_id\": \"gluu-scan-api\", \"grant_types\": [ \"client_credentials\" ], \"org_id\": 1, \"iss\": \"https://jans.localhost\", \"software_roles\": [ \"passwurd\" ], \"exp\": 1668608852, \"iat\": 1668608851, \"jti\": \"c3eb1c16-be9b-4e96-974e-aea5e3cf95b0\", \"description: \"test description\", \"one_time_use\": true, \"rotate_ssa\": false }, \"iss\": \"ed4d5f74-ce41-4180-aed4-54cffa974630\", \"created_at\": 1668608851, \"expiration\": 1668608852, \"status\": \"ACTIVE\" } ] Get JWT SSA # Get existing active SSA based on jti . Query Parameters # jti \u2014 Unique identifier Response description # Returned SSA is a JWT, containing the following structure: { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" } Header alg \u2014 The signature algorithm which used RS256 . typ \u2014 The type which used. kid \u2014 The key identification gluu-scan-api-rs256-ssa-signature-key . Payload iat \u2014 The time the JWT was created. iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. software_id \u2014 The \"software_id\" is used for software identification. org_id \u2014 The \"org_id\" is used for organization identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . exp \u2014 Expiration Time. myCustom1, myCustom2, ... : if you have custom attributes, they will be displayed here. Example: # Request: GET {{your-url}}/ssa/jwt?jti={{your-jti}} Content-Type: application/json Authorization: Bearer {{your-token}} Response: HTTP/1.1 201 Created Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 757 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" } Validate SSA # Validate existing active SSA based on jti Header Parameters # jti \u2014 Unique identifier Response description # Method returns status 200 with an empty body if the corresponding SSA exists and is active. Example: # POST {{your-url}}/ssa/validation jti: {{your-jti}} HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Keep-Alive: timeout=5, max=100 Connection: Keep-Alive <Response body is empty> Revoke SSA # Revoke existing active SSA based on jti or org_id . Query Parameters # jti \u2014 for revoke only one SSA, the specified by jti org_id \u2014 for revoke all SSA of the specified organization. Response description # Method returns status 200 with an empty body if all required SSAs were revoked correctly. Example: # Request: Revoke using jti . DELETE {{your-url}}/ssa?jti={{your-jti}} Authorization: Bearer {{your-token}} Revoke using org_id . DELETE {{your-url}}/ssa?org_id={{your-org_id}} Authorization: Bearer {{your-token}} Response: HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 0 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive <Response body is empty> SSA Custom Script # The custom script will allow us to modify the SSA process. SSA Custom Script Modify the JWT returned by the creation SSA web service. Modify the list returned by the get SSA web service. Run a process after revoking an SSA. Create method # This method is executed after having generated the jwt that the service will return. In the following example, new fields is added to the header and payload of the JWT. def create(self, jsonWebResponse, context): print \"Modify ssa response script. Modify idToken: %s\" % jsonWebResponse jsonWebResponse.getHeader().setClaim(\"custom_header_name\", \"custom_header_value\") jsonWebResponse.getClaims().setClaim(\"custom_claim_name\", \"custom_claim_value\") print \"Modify ssa response script. After modify idToken: %s\" % jsonWebResponse return True Parameters # jsonWebResponse \u2014 JWT with SSA structure using io.jans.as.model.jwt.Jwt class context \u2014 Contains, SSA global configuration class, client, execution context, etc. Get method # This method is executed after having generated the SSA list that will be returned by the service. def get(self, jsonArray, context): print \"Modify ssa response script. Modify get ssa list: %s\" % jsonArray return True Parameters # jsonArray \u2014 Contains SSA list using org.json.JSONArray class context \u2014 Contains, SSA global configuration class, client, execution context, etc. Revoke method # This method is executed after the SSA list has been revoked. def revoke(self, ssaList, context): print \"Modify ssa response script. Modify revoke ssaList: %s\" % ssaList return True Parameters # ssaList \u2014 SSA revoked list. context \u2014 Contains, SSA global configuration class, client, execution context, etc. SSA Class structure # The SSA entity contains the following fields: id type String \u2014 Unique class identifier, and is used as the jti identifier for the JWT . orgId type String \u2014 Organization ID. description type String \u2014 SSA Description. state type enum SsaState \u2014 Contains the following SSA status values ( ACTIVE , EXPIRED , REVOKED , USED ). creationDate type Date \u2014 SSA Creation date. creatorId type String \u2014 Client that created SSA. creatorType type enum CreatorType \u2014 Contains the following CreatorType values ( NONE , CLIENT , USER , AUTO ). ttl type Integer \u2014 SSA lifetime in seconds. atributes type class SsaAtributes oneTimeUse type Boolean \u2014 Whether the SSA will be single use. lifetime type Integer \u2014 SSA lifetime in seconds. rotateSsa type Boolean \u2014 TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. clientDn type String \u2014 Client's DN. customAttributes type Map<String, String> \u2014 Contain additional fields, previously configured in the SSA global configuration. softwareId type String \u2014 Is used for software identification. softwareRoles type List<String> \u2014 List of string values, fixed value [\"password\", \"notify\"] . grantTypes type List<String> \u2014 Fixed value [\"client_credentials\"] .", "title": "SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#software-statement-assertion-ssa", "text": "Janssen Server provides SSA endpoint that enables management of SSAs. The SSA is a JSON Web Token (JWT) containing client metadata and some custom attributes. Specification for SSAs has been outlined as part of Dynamic Client Registration Protocol . URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration ssa_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://janssen.server.host/jans-auth/restv1/ssa More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Software Statement Assertion (SSA)"}, {"location": "janssen-server/auth-server/endpoints/ssa/#disabling-the-endpoint-using-feature-flag", "text": "/ssa endpoint can be enabled or disable using SSA feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable SSA flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/ssa/#configuration-properties", "text": "SSA endpoint can be further configured using Janssen Server configuration property ssaConfiguration . When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties to update value for this property. This property take JSON configuration with parameters as described below: \"ssaConfiguration\": { \"ssaEndpoint\": \"{{your-url}}/ssa\", \"ssaCustomAttributes\": [ \"myCustomAttr1\", \"myCustomAttr2\", ... ], \"ssaSigningAlg\": \"RS512\", \"ssaExpirationInDays\": 30 } ssaEndpoint \u2014 Base endpoint for SSA. ssaCustomAttributes \u2014 List of custom attributes, which are received in the request when creating an SSA. ssaSigningAlg \u2014 Algorithm to sign the JWT that is returned after creating an SSA. ssaExpirationInDays \u2014 Expiration expressed in days, when an SSA is created and the expiration is not sent.", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/ssa/#ssa-security", "text": "To call SSA services, a token of type client_credentials must be generated with the following scopes enabled: https://jans.io/auth/ssa.admin \u2014 Allows calling all SSA services. https://jans.io/auth/ssa.portal \u2014 Allows only call Get SSA service. https://jans.io/auth/ssa.developer \u2014 Allows only call Get SSA , but you can only filter ssa that have been created by the same client.", "title": "SSA Security"}, {"location": "janssen-server/auth-server/endpoints/ssa/#create-a-new-ssa", "text": "Create SSA for the organization with expiration (optional).", "title": "Create a new SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#request-body-description", "text": "Field Detail Optional org_id The \"org_id\" is used for organization identification. false description Describe SSA false software_id The \"software_id\" is used for software identification. false software_roles List of string values, fixed value [\"password\", \"notify\"] . false grant_types Fixed value Fixed value [\"client_credentials\"] . false expiration Expiration date. (Default value: calculated based on global SSA settings) true one_time_use Defined whether the SSA will be used only once or can be used multiple times. (Default value: true) true rotate_ssa TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. (Default value: true) true lifetime SSA Lifetime in seconds true Note: You can add more custom attributes in the request, (you must have previously configured in the SSA global configuration). It should be clarified that these values are persisted in the database and are not returned in the SSA JWT. Example: { \"org_id\": \"your-org-id\", \"description\": \"your description\", ..., \"myCustomAttr1\": \"Your value custom attr 1\", \"myCustomAttr2\": \"Your value custom attr 2\" }", "title": "Request body description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#response-description", "text": "Returned SSA is a JWT, containing the following structure: { \"ssa\": \"eyJraWQiOiI1NTk3MGFkZS00M2MwLTQ4YWMtODEyZi0yZTY1MzhjMTEyN2Zfc2lnX3JzNTEyIiwidHlwIjoiand0IiwiYWxnIjoiUlM1MTIifQ.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoxLCJpc3MiOiJodHRwczovL2phbnMubG9jYWxob3N0Iiwic29mdHdhcmVfcm9sZXMiOlsicGFzc3d1cmQiXSwiZXhwIjoxNjY4NjA5MDA1LCJpYXQiOjE2Njg2NDE5NjcsImp0aSI6ImU4OWVjYTQxLTM0ODUtNDUxNi1hMTYyLWZiODYyNjJhYmFjMyJ9.jRgh8_aiwMTJxeT9cwfup9QP9LBc6gQstvabCzUOJvELnzosxiNJHeU2mrvavaNK6BGvs_lbNjODVDeetGCD48_F2ay9r8qmo-f3GPzdzcJozKgfzonSkAE5Ran9LKcQQJpVc1rDYcV2xYiJLJ6FSuvnoClkDEE1tXysxshLPs-GXOZE7rD8XUXzezuxZWUE1jXwA-EFajoat8CP6QulHGxlcn_sKIhawhGODxJPz4Pf3jgeZVLG_7HfRJgxNiKcdzQIxnkbdpuS-0Q4-oc5yntsXhFhn31Pa3vGsiPPH9f3ndL2ZZKk3xCgyImLDJuGaxXg-qEVoIG4zNWNHMUNUQ\" } Header alg \u2014 The signature algorithm which used RS256 . typ \u2014 The type which used. kid \u2014 The key identification gluu-scan-api-rs256-ssa-signature-key . Payload iat \u2014 The time the JWT was created. iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. software_id \u2014 The \"software_id\" is used for software identification. org_id \u2014 The \"org_id\" is used for organization identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . lifetime \u2014 SSA lifetime in seconds. exp \u2014 Expiration Time. myCustom1, myCustom2, ... : if you have custom attributes, they will be displayed here.", "title": "Response description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#example", "text": "Request: POST {{your-url}}/ssa Content-Type: application/json Authorization: Bearer {{your-token}} { \"org_id\": \"your-org-id\", \"description\": \"This is test description\", \"software_id\": \"gluu-scan-api\", \"software_roles\": [ \"passwurd\" ], \"grant_types\": [ \"client_credentials\" ], \"expiration\": \"1696799089\", \"one_time_use\": false, \"rotate_ssa\": false, \"lifetime\": 86400 } Response: HTTP/1.1 201 Created Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 757 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" }", "title": "Example:"}, {"location": "janssen-server/auth-server/endpoints/ssa/#get-ssa", "text": "Get existing active SSA based on jti or org_id .", "title": "Get SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#query-parameters", "text": "jti \u2014 Unique identifier org_id \u2014 Organization ID", "title": "Query Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#response-description_1", "text": "[ { \"ssa\": { \"jti\": \"c3eb1c16-be9b-4e96-974e-aea5e3cf95b0\", \"org_id\": 1, \"software_id\": \"gluu-scan-api\", \"software_roles\": [ \"password\" ], \"grant_types\": [ \"client_credentials\" ], \"iss\": \"https://jans.localhost\", \"exp\": 1668608852, \"iat\": 1668608851, \"description: \"test description\", \"one_time_use\": true, \"rotate_ssa\": false, \"lifetime\": 86400 }, \"iss\": \"ed4d5f74-ce41-4180-aed4-54cffa974630\", \"created_at\": 1668608851, \"expiration\": 1668608852, \"status\": \"ACTIVE\" } ] SSA jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. org_id \u2014 The \"org_id\" is used for organization identification. software_id \u2014 The \"software_id\" is used for software identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. exp \u2014 Expiration time. iat \u2014 Creation time. description \u2014 Describe SSA. one_time_use \u2014 Defined whether the SSA will be used only once or can be used multiple times. rotate_ssa \u2014 TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. lifetime \u2014 SSA lifetime in seconds. myCustom1, myCustom2, ... \u2014 if you have custom attributes, they will be displayed here. iss \u2014 The \"iss\" is related to the client that created this SSA. created_at \u2014 Creation time. expiration \u2014 Expiration time. status \u2014 SSA status ( ACTIVE , USED , EXPIRED or REVOKED ).", "title": "Response description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#example_1", "text": "Request: Get SSA using jti . GET {{your-url}}/ssa?jti={{your-jti}} Content-Type: application/json Authorization: Bearer {{your-token}} Get SSA using org_id . GET {{your-url}}/ssa?org_id={{your-org_id}} Content-Type: application/json Authorization: Bearer {{your-token}} Response: HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 432 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive [ { \"ssa\": { \"software_id\": \"gluu-scan-api\", \"grant_types\": [ \"client_credentials\" ], \"org_id\": 1, \"iss\": \"https://jans.localhost\", \"software_roles\": [ \"passwurd\" ], \"exp\": 1668608852, \"iat\": 1668608851, \"jti\": \"c3eb1c16-be9b-4e96-974e-aea5e3cf95b0\", \"description: \"test description\", \"one_time_use\": true, \"rotate_ssa\": false }, \"iss\": \"ed4d5f74-ce41-4180-aed4-54cffa974630\", \"created_at\": 1668608851, \"expiration\": 1668608852, \"status\": \"ACTIVE\" } ]", "title": "Example:"}, {"location": "janssen-server/auth-server/endpoints/ssa/#get-jwt-ssa", "text": "Get existing active SSA based on jti .", "title": "Get JWT SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#query-parameters_1", "text": "jti \u2014 Unique identifier", "title": "Query Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#response-description_2", "text": "Returned SSA is a JWT, containing the following structure: { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" } Header alg \u2014 The signature algorithm which used RS256 . typ \u2014 The type which used. kid \u2014 The key identification gluu-scan-api-rs256-ssa-signature-key . Payload iat \u2014 The time the JWT was created. iss \u2014 The \"iss\" (issuer) claim identifies the principal that issued the JWT. jti \u2014 The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. software_id \u2014 The \"software_id\" is used for software identification. org_id \u2014 The \"org_id\" is used for organization identification. software_roles \u2014 List of string values, fixed value [\"password\", \"notify\"] . grant_types \u2014 Fixed value [\"client_credentials\"] . exp \u2014 Expiration Time. myCustom1, myCustom2, ... : if you have custom attributes, they will be displayed here.", "title": "Response description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#example_2", "text": "Request: GET {{your-url}}/ssa/jwt?jti={{your-jti}} Content-Type: application/json Authorization: Bearer {{your-token}} Response: HTTP/1.1 201 Created Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 757 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive { \"ssa\": \"eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg\" }", "title": "Example:"}, {"location": "janssen-server/auth-server/endpoints/ssa/#validate-ssa", "text": "Validate existing active SSA based on jti", "title": "Validate SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#header-parameters", "text": "jti \u2014 Unique identifier", "title": "Header Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#response-description_3", "text": "Method returns status 200 with an empty body if the corresponding SSA exists and is active.", "title": "Response description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#example_3", "text": "POST {{your-url}}/ssa/validation jti: {{your-jti}} HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Keep-Alive: timeout=5, max=100 Connection: Keep-Alive <Response body is empty>", "title": "Example:"}, {"location": "janssen-server/auth-server/endpoints/ssa/#revoke-ssa", "text": "Revoke existing active SSA based on jti or org_id .", "title": "Revoke SSA"}, {"location": "janssen-server/auth-server/endpoints/ssa/#query-parameters_2", "text": "jti \u2014 for revoke only one SSA, the specified by jti org_id \u2014 for revoke all SSA of the specified organization.", "title": "Query Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#response-description_4", "text": "Method returns status 200 with an empty body if all required SSAs were revoked correctly.", "title": "Response description"}, {"location": "janssen-server/auth-server/endpoints/ssa/#example_4", "text": "Request: Revoke using jti . DELETE {{your-url}}/ssa?jti={{your-jti}} Authorization: Bearer {{your-token}} Revoke using org_id . DELETE {{your-url}}/ssa?org_id={{your-org_id}} Authorization: Bearer {{your-token}} Response: HTTP/1.1 200 OK Server: Apache/2.4.52 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 0 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive <Response body is empty>", "title": "Example:"}, {"location": "janssen-server/auth-server/endpoints/ssa/#ssa-custom-script", "text": "The custom script will allow us to modify the SSA process. SSA Custom Script Modify the JWT returned by the creation SSA web service. Modify the list returned by the get SSA web service. Run a process after revoking an SSA.", "title": "SSA Custom Script"}, {"location": "janssen-server/auth-server/endpoints/ssa/#create-method", "text": "This method is executed after having generated the jwt that the service will return. In the following example, new fields is added to the header and payload of the JWT. def create(self, jsonWebResponse, context): print \"Modify ssa response script. Modify idToken: %s\" % jsonWebResponse jsonWebResponse.getHeader().setClaim(\"custom_header_name\", \"custom_header_value\") jsonWebResponse.getClaims().setClaim(\"custom_claim_name\", \"custom_claim_value\") print \"Modify ssa response script. After modify idToken: %s\" % jsonWebResponse return True", "title": "Create method"}, {"location": "janssen-server/auth-server/endpoints/ssa/#parameters", "text": "jsonWebResponse \u2014 JWT with SSA structure using io.jans.as.model.jwt.Jwt class context \u2014 Contains, SSA global configuration class, client, execution context, etc.", "title": "Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#get-method", "text": "This method is executed after having generated the SSA list that will be returned by the service. def get(self, jsonArray, context): print \"Modify ssa response script. Modify get ssa list: %s\" % jsonArray return True", "title": "Get method"}, {"location": "janssen-server/auth-server/endpoints/ssa/#parameters_1", "text": "jsonArray \u2014 Contains SSA list using org.json.JSONArray class context \u2014 Contains, SSA global configuration class, client, execution context, etc.", "title": "Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#revoke-method", "text": "This method is executed after the SSA list has been revoked. def revoke(self, ssaList, context): print \"Modify ssa response script. Modify revoke ssaList: %s\" % ssaList return True", "title": "Revoke method"}, {"location": "janssen-server/auth-server/endpoints/ssa/#parameters_2", "text": "ssaList \u2014 SSA revoked list. context \u2014 Contains, SSA global configuration class, client, execution context, etc.", "title": "Parameters"}, {"location": "janssen-server/auth-server/endpoints/ssa/#ssa-class-structure", "text": "The SSA entity contains the following fields: id type String \u2014 Unique class identifier, and is used as the jti identifier for the JWT . orgId type String \u2014 Organization ID. description type String \u2014 SSA Description. state type enum SsaState \u2014 Contains the following SSA status values ( ACTIVE , EXPIRED , REVOKED , USED ). creationDate type Date \u2014 SSA Creation date. creatorId type String \u2014 Client that created SSA. creatorType type enum CreatorType \u2014 Contains the following CreatorType values ( NONE , CLIENT , USER , AUTO ). ttl type Integer \u2014 SSA lifetime in seconds. atributes type class SsaAtributes oneTimeUse type Boolean \u2014 Whether the SSA will be single use. lifetime type Integer \u2014 SSA lifetime in seconds. rotateSsa type Boolean \u2014 TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. clientDn type String \u2014 Client's DN. customAttributes type Map<String, String> \u2014 Contain additional fields, previously configured in the SSA global configuration. softwareId type String \u2014 Is used for software identification. softwareRoles type List<String> \u2014 List of string values, fixed value [\"password\", \"notify\"] . grantTypes type List<String> \u2014 Fixed value [\"client_credentials\"] .", "title": "SSA Class structure"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/", "tags": ["administration", "auth-server", "token-revocation", "endpoint"], "text": "Overview # Janssen Server supports token revocation endpoint enables a client to notify the server that previously obtained refresh or access token is no longer needed, allowing the server to clean up security credentials. Implementation conforms with token revocation specification . Since a token is part of a grant, when the token is invalidated, all other token within the same grant are also revoked. i.e when a refresh token related to a grant is invalidated, all access tokens from the same grant are also invalidated and vice-versa. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://<jans-server-host>/jans-auth/.well-known/openid-configuration revocation_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://jans-dynamic-mysql/jans-auth/restv1/revoke More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # Token revocation endpoint can be enabled or disable using REVOKE_TOKEN feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable REVOKE_TOKEN flag as required. Configuration Properties # Token revocation endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . mtlstokenrevocationendpoint tokenRevocationEndpoint allowRevokeForOtherClients Revoke all tokens by client_id # To remove all tokens for given client_id it's required: - set allowAllValueForRevokeEndpoint AS configuration property to true - pass in request parameter token_type_hint=all client is identified by Client Authentication performed by AS to grant access to /revoke endpoint. Revoke tokens of other clients # By default Revoke Endpoint allows revoke only own client's tokens. However it is possible to allow revoking of any token (which is issued with other client). For this it is required: - set global AS configuration property allowRevokeForOtherClients to true - add revoke_any_token scope to client which performs revoke call Revoke Interception Script # Endpoint can provide custom behavior via implementing Revoke Token interception script .", "title": "Token Revocation"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#overview", "text": "Janssen Server supports token revocation endpoint enables a client to notify the server that previously obtained refresh or access token is no longer needed, allowing the server to clean up security credentials. Implementation conforms with token revocation specification . Since a token is part of a grant, when the token is invalidated, all other token within the same grant are also revoked. i.e when a refresh token related to a grant is invalidated, all access tokens from the same grant are also invalidated and vice-versa. URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://<jans-server-host>/jans-auth/.well-known/openid-configuration revocation_endpoint claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint looks like below: https://jans-dynamic-mysql/jans-auth/restv1/revoke More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#disabling-the-endpoint-using-feature-flag", "text": "Token revocation endpoint can be enabled or disable using REVOKE_TOKEN feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable REVOKE_TOKEN flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#configuration-properties", "text": "Token revocation endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . mtlstokenrevocationendpoint tokenRevocationEndpoint allowRevokeForOtherClients", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#revoke-all-tokens-by-client_id", "text": "To remove all tokens for given client_id it's required: - set allowAllValueForRevokeEndpoint AS configuration property to true - pass in request parameter token_type_hint=all client is identified by Client Authentication performed by AS to grant access to /revoke endpoint.", "title": "Revoke all tokens by client_id"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#revoke-tokens-of-other-clients", "text": "By default Revoke Endpoint allows revoke only own client's tokens. However it is possible to allow revoking of any token (which is issued with other client). For this it is required: - set global AS configuration property allowRevokeForOtherClients to true - add revoke_any_token scope to client which performs revoke call", "title": "Revoke tokens of other clients"}, {"location": "janssen-server/auth-server/endpoints/token-revocation/#revoke-interception-script", "text": "Endpoint can provide custom behavior via implementing Revoke Token interception script .", "title": "Revoke Interception Script"}, {"location": "janssen-server/auth-server/endpoints/token/", "tags": ["administration", "auth-server", "token", "endpoint"], "text": "Overview # Token endpoint is an OAuth2 protected endpoint that is used to grant tokens to client in response to valid request. Token endpoint is defined in the OAuth 2.0 framework , OpenID Connect specification and other specifications relevant to them. Tokens granted by this endpoint depends on grant type and scopes that are specified in the token request. The token endpoint is used with every authorization grant type except for the implicit grant type (since an access token is issued directly). Based on request, this endpoint can grant following types of tokens: Access Token Refresh Token ID Token URL to access token endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration token_endpoint claim in the response specifies the URL for userinfo endpoint. By default, userinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/token In response to a valid request, the token endpoint returns token/s in JSON format similar to below. This is just a sample response. Actual response can greatly vary in its contents based on request: HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store Pragma: no-cache { \"access_token\": \"SlAV32hkKG\", \"token_type\": \"Bearer\", \"refresh_token\": \"8xLOxBtZp8\", \"expires_in\": 3600, \"id_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5 NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4 XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg\" } More information about request and response of the token endpoint can be found in the OpenAPI specification of jans-auth-server module . Configuration Properties # Token endpoint and tokens issued by token endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . tokenEndpoint tokenEndpointAuthMethodsSupported tokenEndpointAuthSigningAlgValuesSupported accessTokenLifetime checkUserPresenceOnRefreshToken defaultSignatureAlgorithm forceOfflineAccessScopeToEnableRefreshToken grantTypesSupported accessTokenSigningAlgValuesSupported idTokenEncryptionAlgValuesSupported idTokenEncryptionEncValuesSupported idTokenFilterClaimsBasedOnAccessToken idTokenLifetime idTokenSigningAlgValuesSupported accessTokenSigningAlgValuesSupported legacyIdTokenClaims mtlsTokenEndpoint openidScopeBackwardCompatibility persistIdToken persistRefreshToken refreshTokenExtendLifetimeOnRotation refreshTokenLifetime responseTypesSupported skipRefreshTokenDuringRefreshing refreshTokenLifetime Client Authentication # Janssen Server Token Endpoint requires confidential clients to authenticate using one of the supported client authentication method listed below: client_secret_basic client_secret_post client_secret_jwt private_key_jwt Refer to Client Authentication section of OpenID Connect core specification for more details on these authentication methods. AS provides ability to customer Client Authentication behavior via Client Authentication custom script Client can specify the default authentication method. To set default authentication method using Janssen Text-based UI(TUI) , navigate via Auth Server -> Clients -> Add Client -> Basic -> Authn Method Token Endpoint . Supported Grant Types # Token endpoint supports below mentioned grant types. Authorization Code Implicit Refresh Token Client Credentials Password Token Exchange Transaction Tokens Device Grant CIBA Client can configure all the possible grant types it can request from token endpoint during client configuration. To select the available grant types using Janssen Text-based UI(TUI) , navigate via Auth Server -> Clients -> Add Client / search client -> Basic -> Grant . Interception Scripts # Token endpoint response can be further customized using interception scripts . Following interception scripts are relevant to token endpoint: Update Token Client can configure a particular script to be executed using client configuration. To update configuration using Janssen Text-based UI(TUI) navigate via Auth Server -> Clients -> Add Client / search -> Client Scripts", "title": "Token"}, {"location": "janssen-server/auth-server/endpoints/token/#overview", "text": "Token endpoint is an OAuth2 protected endpoint that is used to grant tokens to client in response to valid request. Token endpoint is defined in the OAuth 2.0 framework , OpenID Connect specification and other specifications relevant to them. Tokens granted by this endpoint depends on grant type and scopes that are specified in the token request. The token endpoint is used with every authorization grant type except for the implicit grant type (since an access token is issued directly). Based on request, this endpoint can grant following types of tokens: Access Token Refresh Token ID Token URL to access token endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration token_endpoint claim in the response specifies the URL for userinfo endpoint. By default, userinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/token In response to a valid request, the token endpoint returns token/s in JSON format similar to below. This is just a sample response. Actual response can greatly vary in its contents based on request: HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store Pragma: no-cache { \"access_token\": \"SlAV32hkKG\", \"token_type\": \"Bearer\", \"refresh_token\": \"8xLOxBtZp8\", \"expires_in\": 3600, \"id_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5 NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4 XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg\" } More information about request and response of the token endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/token/#configuration-properties", "text": "Token endpoint and tokens issued by token endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . tokenEndpoint tokenEndpointAuthMethodsSupported tokenEndpointAuthSigningAlgValuesSupported accessTokenLifetime checkUserPresenceOnRefreshToken defaultSignatureAlgorithm forceOfflineAccessScopeToEnableRefreshToken grantTypesSupported accessTokenSigningAlgValuesSupported idTokenEncryptionAlgValuesSupported idTokenEncryptionEncValuesSupported idTokenFilterClaimsBasedOnAccessToken idTokenLifetime idTokenSigningAlgValuesSupported accessTokenSigningAlgValuesSupported legacyIdTokenClaims mtlsTokenEndpoint openidScopeBackwardCompatibility persistIdToken persistRefreshToken refreshTokenExtendLifetimeOnRotation refreshTokenLifetime responseTypesSupported skipRefreshTokenDuringRefreshing refreshTokenLifetime", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/token/#client-authentication", "text": "Janssen Server Token Endpoint requires confidential clients to authenticate using one of the supported client authentication method listed below: client_secret_basic client_secret_post client_secret_jwt private_key_jwt Refer to Client Authentication section of OpenID Connect core specification for more details on these authentication methods. AS provides ability to customer Client Authentication behavior via Client Authentication custom script Client can specify the default authentication method. To set default authentication method using Janssen Text-based UI(TUI) , navigate via Auth Server -> Clients -> Add Client -> Basic -> Authn Method Token Endpoint .", "title": "Client Authentication"}, {"location": "janssen-server/auth-server/endpoints/token/#supported-grant-types", "text": "Token endpoint supports below mentioned grant types. Authorization Code Implicit Refresh Token Client Credentials Password Token Exchange Transaction Tokens Device Grant CIBA Client can configure all the possible grant types it can request from token endpoint during client configuration. To select the available grant types using Janssen Text-based UI(TUI) , navigate via Auth Server -> Clients -> Add Client / search client -> Basic -> Grant .", "title": "Supported Grant Types"}, {"location": "janssen-server/auth-server/endpoints/token/#interception-scripts", "text": "Token endpoint response can be further customized using interception scripts . Following interception scripts are relevant to token endpoint: Update Token Client can configure a particular script to be executed using client configuration. To update configuration using Janssen Text-based UI(TUI) navigate via Auth Server -> Clients -> Add Client / search -> Client Scripts", "title": "Interception Scripts"}, {"location": "janssen-server/auth-server/endpoints/userinfo/", "tags": ["administration", "auth-server", "userinfo", "endpoint"], "text": "Overview # Userinfo endpoint is an OAuth2 protected endpoint that is used to retrieve claims about an authenticated end-user. Userinfo endpoint is defined in the OpenID Connect specification . URL to access userinfo endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration userinfo_endpoint claim in the response specifies the URL for userinfo endpoint. By default, userinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/userinfo In response to a valid request, the userinfo endpoint returns user information in JSON format similar to below: HTTP/1.1 200 OK Content-Type: application/json { \"sub\": \"3482897610054\", \"jti\": \"sdu28g9c761g0y0g5\", \"client_id\": \"db6daf8c-ab1b-4010-9fb0\", \"name\": \"Chad Wick\", \"given_name\": \"Chad\", \"family_name\": \"Wick\", \"preferred_username\": \"c.wick\", \"email\": \"cwick@jans.com\", \"picture\": \"http://mysite.com/mypic.jpg\" } User Info response should contain: sub , jti and client_id claims. Since userinfo endpoint is an OAuth2 protected resource, a valid access token with appropriate scope is required to access the endpoint. More information about request and response of the userinfo endpoint can be found in the OpenAPI specification of jans-auth-server module . Disabling The Endpoint Using Feature Flag # userinfo endpoint can be enabled or disable using USERINFO feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable USERINFO flag as required. Configuration Properties # Userinfo endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . mtlsUserInfoEndpoint userInfoEncryptionAlgValuesSupported userInfoEncryptionEncValuesSupported userInfoEndpoint userInfoSigningAlgValuesSupported Using Scopes To Control Claim Release # Standard Scopes # In context of OpenID Connect specification, claim information released by userinfo endpoint can be controlled using scopes. Janssen Server supports all standard scopes and releases corresponding claims as per OpenID Connect specification. Administrator can customise standard scopes and define claims to be linked to each standard scope. When using Janssen Text-based UI(TUI) to configure the scopes, navigate via Auth Server -> Scopes -> Add Scopes -> Scope Type as OpenID ->search for a standard scope like address Dynamic Scopes # In addition to standard scopes, Janssen server allows defining custom scopes which can be associated to user-defined list of claims. This allows administrators to create custom groupings of claims. When using Janssen Text-based UI(TUI) , navigate via Auth Server -> Scopes -> Add Scopes -> Scope Type as Dynamic Interception Scripts # Response from userinfo can be further customized using dynamic scope interception script. Administrator can attach a dynamic scope script to a dynamic scope using Janssen Text-based UI(TUI) . Navigate to Auth Server -> Scopes -> Add Scopes -> Scope Type as Dynamic -> Dynamic Scope Script Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Userinfo"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#overview", "text": "Userinfo endpoint is an OAuth2 protected endpoint that is used to retrieve claims about an authenticated end-user. Userinfo endpoint is defined in the OpenID Connect specification . URL to access userinfo endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration userinfo_endpoint claim in the response specifies the URL for userinfo endpoint. By default, userinfo endpoint looks like below: https://janssen.server.host/jans-auth/restv1/userinfo In response to a valid request, the userinfo endpoint returns user information in JSON format similar to below: HTTP/1.1 200 OK Content-Type: application/json { \"sub\": \"3482897610054\", \"jti\": \"sdu28g9c761g0y0g5\", \"client_id\": \"db6daf8c-ab1b-4010-9fb0\", \"name\": \"Chad Wick\", \"given_name\": \"Chad\", \"family_name\": \"Wick\", \"preferred_username\": \"c.wick\", \"email\": \"cwick@jans.com\", \"picture\": \"http://mysite.com/mypic.jpg\" } User Info response should contain: sub , jti and client_id claims. Since userinfo endpoint is an OAuth2 protected resource, a valid access token with appropriate scope is required to access the endpoint. More information about request and response of the userinfo endpoint can be found in the OpenAPI specification of jans-auth-server module .", "title": "Overview"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#disabling-the-endpoint-using-feature-flag", "text": "userinfo endpoint can be enabled or disable using USERINFO feature flag . Use Janssen Text-based UI(TUI) or Janssen command-line interface to perform this task. When using TUI, navigate via Auth Server -> Properties -> enabledFeatureFlags to screen below. From here, enable or disable USERINFO flag as required.", "title": "Disabling The Endpoint Using Feature Flag"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#configuration-properties", "text": "Userinfo endpoint can be further configured using Janssen Server configuration properties listed below. When using Janssen Text-based UI(TUI) to configure the properties, navigate via Auth Server -> Properties . mtlsUserInfoEndpoint userInfoEncryptionAlgValuesSupported userInfoEncryptionEncValuesSupported userInfoEndpoint userInfoSigningAlgValuesSupported", "title": "Configuration Properties"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#using-scopes-to-control-claim-release", "text": "", "title": "Using Scopes To Control Claim Release"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#standard-scopes", "text": "In context of OpenID Connect specification, claim information released by userinfo endpoint can be controlled using scopes. Janssen Server supports all standard scopes and releases corresponding claims as per OpenID Connect specification. Administrator can customise standard scopes and define claims to be linked to each standard scope. When using Janssen Text-based UI(TUI) to configure the scopes, navigate via Auth Server -> Scopes -> Add Scopes -> Scope Type as OpenID ->search for a standard scope like address", "title": "Standard Scopes"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#dynamic-scopes", "text": "In addition to standard scopes, Janssen server allows defining custom scopes which can be associated to user-defined list of claims. This allows administrators to create custom groupings of claims. When using Janssen Text-based UI(TUI) , navigate via Auth Server -> Scopes -> Add Scopes -> Scope Type as Dynamic", "title": "Dynamic Scopes"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#interception-scripts", "text": "Response from userinfo can be further customized using dynamic scope interception script. Administrator can attach a dynamic scope script to a dynamic scope using Janssen Text-based UI(TUI) . Navigate to Auth Server -> Scopes -> Add Scopes -> Scope Type as Dynamic -> Dynamic Scope Script", "title": "Interception Scripts"}, {"location": "janssen-server/auth-server/endpoints/userinfo/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/international/client-config/", "tags": ["administration", "auth-server", "i18n"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Client Configuration"}, {"location": "janssen-server/auth-server/international/client-config/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/international/client-config/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/international/client-config/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/international/scope-descriptions/", "tags": ["administration", "auth-server", "i18n"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Scope Descriptions"}, {"location": "janssen-server/auth-server/international/scope-descriptions/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/international/scope-descriptions/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/international/scope-descriptions/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/international/web-pages/", "tags": ["administration", "auth-server", "i18n"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Web Pages"}, {"location": "janssen-server/auth-server/international/web-pages/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/international/web-pages/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/international/web-pages/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/logging/audit-logs/", "tags": ["administration", "auth-server", "logging"], "text": "Audit Logs # Audit logs are located in jans-auth_audit.log log file. All jans-auth-server log files are located in /opt/jans/jetty/jans-auth/logs/ . Audit is disabled by default on AS and can be enabled via enabledOAuthAuditLogging AS configuration property. Audit logs are logged to file when enabled, however if JMS configuration is specified it will be logged to JMS as well. JMS Configuration must be set inside AS global configuration Name Description jmsBrokerURISet JMS Broker URI Set jmsUserName JMS UserName jmsPassword JMS Password. Audit events: - CLIENT_REGISTRATION - CLIENT_UPDATE - CLIENT_READ - CLIENT_DELETE - USER_AUTHORIZATION - BACKCHANNEL_AUTHENTICATION - BACKCHANNEL_DEVICE_REGISTRATION - USER_INFO - TOKEN_REQUEST - TOKEN_VALIDATE - TOKEN_REVOCATION - SESSION_UNAUTHENTICATED - SESSION_AUTHENTICATED - SESSION_DESTROYED - DEVICE_CODE_AUTHORIZATION - SSA_CREATE - SSA_READ Enable/Disable Audit Logs on Jans TUI # Using Jans TUI we can easily Enable or Disable Audit Logs. Go to jans tui select Auth Server tab then Properties tab. Now set the value of enabledOAuthAuditLogging pressing Enter button on your keyboard. Save it and let's see below image Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Audit Logs"}, {"location": "janssen-server/auth-server/logging/audit-logs/#audit-logs", "text": "Audit logs are located in jans-auth_audit.log log file. All jans-auth-server log files are located in /opt/jans/jetty/jans-auth/logs/ . Audit is disabled by default on AS and can be enabled via enabledOAuthAuditLogging AS configuration property. Audit logs are logged to file when enabled, however if JMS configuration is specified it will be logged to JMS as well. JMS Configuration must be set inside AS global configuration Name Description jmsBrokerURISet JMS Broker URI Set jmsUserName JMS UserName jmsPassword JMS Password. Audit events: - CLIENT_REGISTRATION - CLIENT_UPDATE - CLIENT_READ - CLIENT_DELETE - USER_AUTHORIZATION - BACKCHANNEL_AUTHENTICATION - BACKCHANNEL_DEVICE_REGISTRATION - USER_INFO - TOKEN_REQUEST - TOKEN_VALIDATE - TOKEN_REVOCATION - SESSION_UNAUTHENTICATED - SESSION_AUTHENTICATED - SESSION_DESTROYED - DEVICE_CODE_AUTHORIZATION - SSA_CREATE - SSA_READ", "title": "Audit Logs"}, {"location": "janssen-server/auth-server/logging/audit-logs/#enabledisable-audit-logs-on-jans-tui", "text": "Using Jans TUI we can easily Enable or Disable Audit Logs. Go to jans tui select Auth Server tab then Properties tab. Now set the value of enabledOAuthAuditLogging pressing Enter button on your keyboard. Save it and let's see below image", "title": "Enable/Disable Audit Logs on Jans TUI"}, {"location": "janssen-server/auth-server/logging/audit-logs/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/logging/audit-logs/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/logging/custom-logs/", "tags": ["administration", "auth-server", "logging", "custom-logs"], "text": "Customize logs # Sometimes it can be useful to customize logging behavior or override AS loggers. It is possible to fully override AS logging configuration by specifying own log4j2.xml file in externalLoggerConfiguration AS configuration property. It must point to valid log4j2.xml file. Note: invalid external log4j2.xml can lead to AS start up issues and no logs in standard log files or otherwise in other log files if such are defined by log4j2.xml . Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Custom Logs"}, {"location": "janssen-server/auth-server/logging/custom-logs/#customize-logs", "text": "Sometimes it can be useful to customize logging behavior or override AS loggers. It is possible to fully override AS logging configuration by specifying own log4j2.xml file in externalLoggerConfiguration AS configuration property. It must point to valid log4j2.xml file. Note: invalid external log4j2.xml can lead to AS start up issues and no logs in standard log files or otherwise in other log files if such are defined by log4j2.xml .", "title": "Customize logs"}, {"location": "janssen-server/auth-server/logging/custom-logs/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/logging/custom-logs/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/logging/log-levels/", "tags": ["administration", "auth-server", "logging-levels"], "text": "Log Levels # Log level for AS can be set in loggingLevel AS configuration property. AS under the hood is using log4j2 and slf4j . Thus logging levels in loggingLevel stick to log4j2 and are following: Log Level Description OFF No events will be logged. FATAL A fatal event that will prevent the application from continuing. ERROR An error in the application, possibly recoverable. WARN An event that might possible lead to an error. INFO An event for informational purposes. DEBUG A general debugging event. TRACE A fine-grained debug message, typically capturing the flow through the application. ALL All events should be logged. Select Log Levels on TUI # Go to Jans TUI jans tui . Select Auth Server tab then select Logging tab after that select Auth Server Log Level finally save logging and exit from TUI. Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Log Levels"}, {"location": "janssen-server/auth-server/logging/log-levels/#log-levels", "text": "Log level for AS can be set in loggingLevel AS configuration property. AS under the hood is using log4j2 and slf4j . Thus logging levels in loggingLevel stick to log4j2 and are following: Log Level Description OFF No events will be logged. FATAL A fatal event that will prevent the application from continuing. ERROR An error in the application, possibly recoverable. WARN An event that might possible lead to an error. INFO An event for informational purposes. DEBUG A general debugging event. TRACE A fine-grained debug message, typically capturing the flow through the application. ALL All events should be logged.", "title": "Log Levels"}, {"location": "janssen-server/auth-server/logging/log-levels/#select-log-levels-on-tui", "text": "Go to Jans TUI jans tui . Select Auth Server tab then select Logging tab after that select Auth Server Log Level finally save logging and exit from TUI.", "title": "Select Log Levels on TUI"}, {"location": "janssen-server/auth-server/logging/log-levels/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/logging/log-levels/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/logging/log4j2/", "tags": ["administration", "auth-server", "logging"], "text": "log4j2 # AS under the hood is using log4j2 and slf4j . AS is configured by log4j2.xml Main structure of which defines standard logs and which can be overwritten by specifying own custom log4j2.xml . Please reference log4j configuration for available logging options. Sample <?xml version=\"1.0\" encoding=\"UTF-8\"?> <Configuration packages= \"io.jans.log\" > <Appenders> <Console name= \"STDOUT\" target= \"SYSTEM_OUT\" > <PatternLayout pattern= \"%d %-5p [%t] [%C{6}] (%F:%L) - %m%n\" /> </Console> <RollingFile name= \"JANS_AUTH_HTTP_REQUEST_RESPONSE_FILE\" fileName= \"${sys:log.base}/logs/http_request_response.log\" filePattern= \"${sys:log.base}/logs/http_request_response-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"FILE\" fileName= \"${sys:log.base}/logs/jans-auth.log\" filePattern= \"${sys:log.base}/logs/jans-auth-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_PERSISTENCE_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_persistence.log\" filePattern= \"${sys:log.base}/logs/jans-auth_persistence-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_persistence_duration.log\" filePattern= \"${sys:log.base}/logs/jans-auth_persistence_duration-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_SCRIPT_LOG_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_script.log\" filePattern= \"${sys:log.base}/logs/jans-auth_script-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_AUDIT_LOG_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_audit.log\" filePattern= \"${sys:log.base}/logs/jans-auth_audit-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%macAddr] [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> </Appenders> <Loggers> <!-- ############### Gluu ################# --> <Logger name= \"io.jans\" level= \"${log4j.default.log.level}\" /> <!-- EMB-6, JMS activation throws an error due to deployment ordering, but as there is a timeout and retry the tests pass. Hide the error message --> <Logger name= \"jboss.resource.adapter.jms.inflow.JmsActivation\" level= \"error\" /> <Logger name= \"com.ocpsoft\" level= \"info\" /> <!-- ############### Hibernate logging ################# --> <Logger name= \"org.hibernate\" level= \"error\" /> <Logger name= \"io.jans.as.server.audit.debug\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_HTTP_REQUEST_RESPONSE_FILE\" /> </Logger> <Logger name= \"io.jans.orm\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_FILE\" /> </Logger> <logger name= \"com.couchbase.client\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_FILE\" /> </logger> <Logger name= \"io.jans.orm.couchbase.operation.watch\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" /> </Logger> <Logger name= \"io.jans.orm.watch\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" /> </Logger> <Logger name= \"io.jans.service.PythonService\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.service.custom.script\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.as.server.service.custom\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.agama.engine.script.LogUtils\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.as.server.audit.ApplicationAuditLogger\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_AUDIT_LOG_FILE\" /> </Logger> <Root level= \"info\" > <AppenderRef ref= \"FILE\" /> <AppenderRef ref= \"STDOUT\" /> </Root> </Loggers> </Configuration> Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "log4j2 Configuration"}, {"location": "janssen-server/auth-server/logging/log4j2/#log4j2", "text": "AS under the hood is using log4j2 and slf4j . AS is configured by log4j2.xml Main structure of which defines standard logs and which can be overwritten by specifying own custom log4j2.xml . Please reference log4j configuration for available logging options. Sample <?xml version=\"1.0\" encoding=\"UTF-8\"?> <Configuration packages= \"io.jans.log\" > <Appenders> <Console name= \"STDOUT\" target= \"SYSTEM_OUT\" > <PatternLayout pattern= \"%d %-5p [%t] [%C{6}] (%F:%L) - %m%n\" /> </Console> <RollingFile name= \"JANS_AUTH_HTTP_REQUEST_RESPONSE_FILE\" fileName= \"${sys:log.base}/logs/http_request_response.log\" filePattern= \"${sys:log.base}/logs/http_request_response-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"FILE\" fileName= \"${sys:log.base}/logs/jans-auth.log\" filePattern= \"${sys:log.base}/logs/jans-auth-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_PERSISTENCE_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_persistence.log\" filePattern= \"${sys:log.base}/logs/jans-auth_persistence-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_persistence_duration.log\" filePattern= \"${sys:log.base}/logs/jans-auth_persistence_duration-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_SCRIPT_LOG_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_script.log\" filePattern= \"${sys:log.base}/logs/jans-auth_script-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> <RollingFile name= \"JANS_AUTH_AUDIT_LOG_FILE\" fileName= \"${sys:log.base}/logs/jans-auth_audit.log\" filePattern= \"${sys:log.base}/logs/jans-auth_audit-%d{yyyy-MM-dd}-%i.log\" > <PatternLayout pattern= \"%d %-5p [%macAddr] [%t] %X{X-Correlation-Id} [%C{6}] (%F:%L) - %m%n\" /> <Policies> <TimeBasedTriggeringPolicy interval= \"1\" modulate= \"true\" /> <SizeBasedTriggeringPolicy size= \"250 MB\" /> </Policies> <DefaultRolloverStrategy max= \"30\" /> </RollingFile> </Appenders> <Loggers> <!-- ############### Gluu ################# --> <Logger name= \"io.jans\" level= \"${log4j.default.log.level}\" /> <!-- EMB-6, JMS activation throws an error due to deployment ordering, but as there is a timeout and retry the tests pass. Hide the error message --> <Logger name= \"jboss.resource.adapter.jms.inflow.JmsActivation\" level= \"error\" /> <Logger name= \"com.ocpsoft\" level= \"info\" /> <!-- ############### Hibernate logging ################# --> <Logger name= \"org.hibernate\" level= \"error\" /> <Logger name= \"io.jans.as.server.audit.debug\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_HTTP_REQUEST_RESPONSE_FILE\" /> </Logger> <Logger name= \"io.jans.orm\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_FILE\" /> </Logger> <logger name= \"com.couchbase.client\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_FILE\" /> </logger> <Logger name= \"io.jans.orm.couchbase.operation.watch\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" /> </Logger> <Logger name= \"io.jans.orm.watch\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_PERSISTENCE_DURATION_FILE\" /> </Logger> <Logger name= \"io.jans.service.PythonService\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.service.custom.script\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.as.server.service.custom\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.agama.engine.script.LogUtils\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_SCRIPT_LOG_FILE\" /> </Logger> <Logger name= \"io.jans.as.server.audit.ApplicationAuditLogger\" level= \"${log4j.default.log.level}\" additivity= \"false\" > <AppenderRef ref= \"JANS_AUTH_AUDIT_LOG_FILE\" /> </Logger> <Root level= \"info\" > <AppenderRef ref= \"FILE\" /> <AppenderRef ref= \"STDOUT\" /> </Root> </Loggers> </Configuration>", "title": "log4j2"}, {"location": "janssen-server/auth-server/logging/log4j2/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/logging/log4j2/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/logging/standard-logs/", "tags": ["administration", "auth-server", "logging"], "text": "Standard Logs # All jans-auth-server log files are located in /opt/jans/jetty/jans-auth/logs/ . jans-auth.log - main AS log file. All logs during execution goes here. jans-auth_script.log : - contains custom interception scripts related log messages. Use scriptLogger inside custom script to log messages to this log file. jans-auth_persistence.log - log which contains entries from AS persistance layer jans-auth_persistence_duration.log - log which contains duration of query execution. It can be useful during performance issues investigation app_persistence_orm_statistics.log - contains statistics about persistence layer activities jans-auth_audit.log - contains audit log information (audit is disabled by default and can be enabled via enabledOAuthAuditLogging AS configuration property) http_request_response.log - contains http request/response data. It can be enabled via httpLoggingEnabled AS configuration property. Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Standard Logs"}, {"location": "janssen-server/auth-server/logging/standard-logs/#standard-logs", "text": "All jans-auth-server log files are located in /opt/jans/jetty/jans-auth/logs/ . jans-auth.log - main AS log file. All logs during execution goes here. jans-auth_script.log : - contains custom interception scripts related log messages. Use scriptLogger inside custom script to log messages to this log file. jans-auth_persistence.log - log which contains entries from AS persistance layer jans-auth_persistence_duration.log - log which contains duration of query execution. It can be useful during performance issues investigation app_persistence_orm_statistics.log - contains statistics about persistence layer activities jans-auth_audit.log - contains audit log information (audit is disabled by default and can be enabled via enabledOAuthAuditLogging AS configuration property) http_request_response.log - contains http request/response data. It can be enabled via httpLoggingEnabled AS configuration property.", "title": "Standard Logs"}, {"location": "janssen-server/auth-server/logging/standard-logs/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/logging/standard-logs/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/oauth-features/auth-code-grant/", "tags": ["administration", "auth-server", "oauth", "feature", "grant", "code"], "text": "OAuth 2.0 Authorization Code Grant # The Authorization Code grant type is used by confidential and public clients to exchange an authorization code for an access token. After the user returns to the client via the redirect URL, the application will get the authorization code from the URL and use it to request an access token. Sequence Diagram # sequenceDiagram title Authorization code flow autonumber 1 participant Resource owner User activate Resource owner User Client->>Jans AS:Authorization Request activate Client activate Jans AS Resource owner User ->>Jans AS:User login and consent Jans AS-->>Client:Authorization code response deactivate Client deactivate Jans AS Client->>Jans AS: Exchange code for Access Token activate Client activate Jans AS Jans AS-->>Client: Access Token with optional Refresh Token deactivate Client deactivate Jans AS loop Client->>Resource Server: Call API with Access Token activate Client activate Resource Server Resource Server-->>Client: Protected Resource deactivate Client deactivate Resource Server end Client->>Resource Server: Call API with expired Access Token activate Client activate Resource Server Resource Server-->>Client: Invalid token error deactivate Client deactivate Resource Server Client->>Jans AS: Resource Token activate Client activate Jans AS Jans AS-->>Client: Access Token with optional Refresh Token deactivate Client deactivate Jans AS deactivate Resource owner User Testing # https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/AuthorizationCodeFlowHttpTest.java On a browser access https://my.jans.server/jans-auth/restv1/authorize?redirect_uri=https://my-redirect-app:8080&client_id=Put_client_id_here&scope=username+openid&response_type=code Based on the default authentication method set (acr), the user will be presented with credentials for login. The OpenID Provider (Gluu Server) verifies the user\u2019s identity and authenticates the user. In the back channel the following steps take place : The OpenID Provider (Gluu Server) sends the user back to the application with an authorization code. The application sends the code to the Token Endpoint to receive an Access Token and ID Token in the response. The application uses the ID Token to authorize the user. At this point the application/RP can access the UserInfo endpoint for claims.", "title": "Authorization Code Grant"}, {"location": "janssen-server/auth-server/oauth-features/auth-code-grant/#oauth-20-authorization-code-grant", "text": "The Authorization Code grant type is used by confidential and public clients to exchange an authorization code for an access token. After the user returns to the client via the redirect URL, the application will get the authorization code from the URL and use it to request an access token.", "title": "OAuth 2.0 Authorization Code Grant"}, {"location": "janssen-server/auth-server/oauth-features/auth-code-grant/#sequence-diagram", "text": "sequenceDiagram title Authorization code flow autonumber 1 participant Resource owner User activate Resource owner User Client->>Jans AS:Authorization Request activate Client activate Jans AS Resource owner User ->>Jans AS:User login and consent Jans AS-->>Client:Authorization code response deactivate Client deactivate Jans AS Client->>Jans AS: Exchange code for Access Token activate Client activate Jans AS Jans AS-->>Client: Access Token with optional Refresh Token deactivate Client deactivate Jans AS loop Client->>Resource Server: Call API with Access Token activate Client activate Resource Server Resource Server-->>Client: Protected Resource deactivate Client deactivate Resource Server end Client->>Resource Server: Call API with expired Access Token activate Client activate Resource Server Resource Server-->>Client: Invalid token error deactivate Client deactivate Resource Server Client->>Jans AS: Resource Token activate Client activate Jans AS Jans AS-->>Client: Access Token with optional Refresh Token deactivate Client deactivate Jans AS deactivate Resource owner User", "title": "Sequence Diagram"}, {"location": "janssen-server/auth-server/oauth-features/auth-code-grant/#testing", "text": "https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/AuthorizationCodeFlowHttpTest.java On a browser access https://my.jans.server/jans-auth/restv1/authorize?redirect_uri=https://my-redirect-app:8080&client_id=Put_client_id_here&scope=username+openid&response_type=code Based on the default authentication method set (acr), the user will be presented with credentials for login. The OpenID Provider (Gluu Server) verifies the user\u2019s identity and authenticates the user. In the back channel the following steps take place : The OpenID Provider (Gluu Server) sends the user back to the application with an authorization code. The application sends the code to the Token Endpoint to receive an Access Token and ID Token in the response. The application uses the ID Token to authorize the user. At this point the application/RP can access the UserInfo endpoint for claims.", "title": "Testing"}, {"location": "janssen-server/auth-server/oauth-features/client-credential-grant/", "tags": ["administration", "auth-server", "oauth", "feature", "grant", "client-credentials"], "text": "OAuth 2.0 client credentials Grant # Sequence Diagram # sequenceDiagram title Client credentials flow autonumber 1 activate Resource owner Client Resource owner Client->>Jans AS:Client Authentication activate Jans AS Jans AS-->>Resource owner Client:Access Token deactivate Jans AS Testing # https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/ClientCredentialsGrantHttpTest.java CURL Command: curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=put_scope_name_here\"", "title": "Client Credential Grant"}, {"location": "janssen-server/auth-server/oauth-features/client-credential-grant/#oauth-20-client-credentials-grant", "text": "", "title": "OAuth 2.0 client credentials Grant"}, {"location": "janssen-server/auth-server/oauth-features/client-credential-grant/#sequence-diagram", "text": "sequenceDiagram title Client credentials flow autonumber 1 activate Resource owner Client Resource owner Client->>Jans AS:Client Authentication activate Jans AS Jans AS-->>Resource owner Client:Access Token deactivate Jans AS", "title": "Sequence Diagram"}, {"location": "janssen-server/auth-server/oauth-features/client-credential-grant/#testing", "text": "https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/ClientCredentialsGrantHttpTest.java CURL Command: curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=put_scope_name_here\"", "title": "Testing"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/", "tags": ["administration", "auth-server", "oauth", "feature", "device", "grant"], "text": "OAuth 2.0 Device Authorization Grant # This OAuth 2.0 protocol extension enables OAuth clients to request user authorization from applications on devices (e.g. smart TVs, media consoles, printers) that are input-constrained or browser-less . The authorization flow defined by this RFC 8628 , sometimes referred to as the \"device flow\", instructs the user to review the authorization request on a secondary device, such as a smartphone or a personal computer, which has the requisite input and browser capabilities to complete the user interaction. Sequence Diagram # Paste the following source text of the sequence diagram on sequencediagram.org title Oauth2.0 Device Authorization flow participant User participant Browser on Computer / Smartphone participant Device App participant Jans AS participant Third Party App User->Device App:Opens an app on device Device App->Jans AS:Sends authorization request \\n\"jans-server.com/jans-auth/restv1/device_authorization\" Jans AS->Device App:Response - \\nuser_code, device_code, verification_url, interval, expiration Device App ->User: Instructs the user to access Verification URL \\nand enter user_code note over Device App:Device App will keep polling AS for Access Token \\nuntil device authorization is completed loop till Device App recieves Access Token: Device App->Jans AS:request Access Token Jans AS->Device App:Response - \\naccess_denied \\nOR expired_token \\nOR authorization_pending \\nOR Access token end User->Browser on Computer / Smartphone:Opens a browser \\nand access verification URL Browser on Computer / Smartphone->Jans AS:send user_code to verification URL Browser on Computer / Smartphone <-Jans AS:Login and authorization prompt Browser on Computer / Smartphone->Jans AS:Authentication and consent Jans AS->Jans AS: Mark device as Authorized note over Jans AS:Subsequent polling by the Device App \\nwill return an Access Token as indicated \\nby the loop above Device App->Third Party App:Invoke API with Access Token Third Party App->Device App: return Response User Experience # First, the user requests authorization from the device: At the URL displayed on the screen, the user can input the displayed code in the device. After that, user could need to authenticate, then decide whether permissions will be granted. acr value can be specified in deviceAuthzAcr AS configuration property. Finally, the confirmation screen will be shown. ACR value during Device Authorization # User is required to authenticate if not authenticated yet. By default acr_values is not set in authorization request, which means it relies on default AS handling. However it's possible explicitly set acr value during Device Authorization by setting deviceAuthzAcr AS configuration property. Request user and device codes # This first step, device sends an HTTP POST request to Jans authorization server, at /jans-auth/restv1/device_authorization which is also presented in the Discovery url published by Jans Server, this endpoint could process a common authentication method or it could also not do any authentication, depending on the configuration for the client in Jans Server. Parameters # Parameter Description client_id Required The client ID for your application. scope Required A space separated list of scopes that identify the resources that the device could access on the user's behalf. These values inform the consent screen that Jans server displays to the user. Example # POST /restv1/device_authorization HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.org Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 client_id=123-123-123&scope=openid+profile+address+email+phone Device Request response # In response, the Jans authorization server generates a unique device verification code and an end-user code that are valid for a limited time and includes them in the HTTP response body using the \"application/json\" format with a 200 (OK) status code. The response contains the following parameters: Parameter Description user_code Required The end-user verification code device_code Required The device verification code verification_uri Required The end-user verification URI on the authorization server. This should be shown to the end-user because he should open this url in the rich user-agent. verification_uri_complete Optional This is similar than verification_uri , however it also includes user_code as a query param in the url. It's issued if the device wants to use QR mode for example. expires_in Required The lifetime in seconds of the device_code and user_code . interval Required The minimum amount of time in seconds that the client should wait between polling requests to the token endpoint. Example: # HTTP/1.1 200 Content-Length: 307 Content-Type: application/json Server: Jetty(9.4.19.v20190610) { \"user_code\": \"SJFP-DTPL\", \"device_code\": \"aeb28bdc90d806ac58d4b0f832f06c3ac9c4bd03292f0c09\", \"interval\": 5, \"verification_uri_complete\": \"https://test.jans.io:8443/device-code?user_code=SJFP-DTPL\", \"verification_uri\": \"https://test.jans.io:8443/device-code\", \"expires_in\": 1800 } Device Display # Common flow, the device should display verification_url and user_code received from Jans server. The content that the device displays to the user should instruct the user to navigate to the verification_url on a separate device and enter the user_code . Design device interface following these rules: user_code has the following format: XXXX-XXXX where Xs represent to any ASCII character, for example: RTXD-HTLK . The length of the user_code will be always the same, therefore it's highly recommended to show it as clear and big that the user can read it easly. verification_url should be displayed also in a way that the user can read it easily. The normal length should be around 40 characters, however it could depends also on the domain used for the server. Remember that the user will need to write the whole URL manually in the web browser, therefore it's recommended to use a short URL. verification_url_complete will be used for those cases where device can show QR (Quick Response) codes or NFC (Near Field Communication) to save the user from typing the whole URI. Interaction between device and Jans server will be the same, however user can process the authorization faster. For example: User Login & Authorization # The user will need to put user_code value in the browser and after that, he will be redirected to the common authorization flow, it requires login whether there is no session between the user-agent and the Jans server and grant the permissions based on the device request. Poll Token # Since the user will be using a separate device to navigate to the verification_url and grant or deny access, the requesting device is not automatically notified when the user responds to the access request. For that reason, the requesting device needs to poll the Jans Server to determine when the user has responded to the request. The requesting device should continue sending polling requests until it receives a response indicating that the user has responded to the access request or until the device_code expires. The parameter interval returned in step 2 specifies the amount of time, in seconds, to wait between requests. The URL of the endpoint to poll is /jans-auth/restv1/token . The polling request contains the following parameters: Parameters # Parameter Description client_id Required The client ID for your application. grant_type Required Must be urn:ietf:params:oauth:grant-type:device_code . device_code Required The device verification code which is returned by Jans server in Step 2. Authentication can be done using any of those authentication methods for this token endpoint. Example: # POST /restv1/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.io Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&device_code=0bd7068e7fdab4bb91b313296a96462256a7370d12f073f0 Token Response # The Jans authorization server responds to each polling request with one of the following responses: Access granted If the user granted access to the device (by clicking Allow on the consent screen), then the response contains an access token and a refresh token. The tokens enable the device to access to the resource server on the user's behalf. In this case, the server responds with all tokens required and allowed to be issued depending on the configuration in the server. Example: HTTP/1.1 200 Content-Length: 858 Content-Type: application/json Server: Jetty(9.4.19.v20190610) {\"access_token\":\"c31fc092-453b-4275-a36f-b2740c3eb1a6\",\"id_token\":\"eyJraWQiOiJlY4.2Tc4NDgxYy05OTJkLTRmN2UtYTkzMS03NjM2NTYyMzgwZjVfc2lnX3JzMjU2IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoidWdMSnAzMkxXdnI4QUdlbmdNTlF3QSIsImF1ZCI6IjEyMy0xMjMtMTIzIiwic3ViIjoiM2M2M25HdWZnWFNkMWFwNU81NFZkVjlUUDdmdjJHc0YtLWl0eVBHeFJBTSIsImlzcyI6Imh0dHBzOi8vdGVzdC5nbHV1Lm9yZzo4NDQzIiwiZXhwIjoxNTk1NjQzOTg0LCJpYXQiOjE1OTU2NDAzODQsIm94T3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCJ9.fElZtuUslhSSuqTOuvGeafG4QuQoHKLpya25RHWkC5V9Xf9ODYa6tD_Tdav2D9Gff2Zz7pt8WKso-WYOqmJ3NrgMoVU7d1SMj6pYGilTL1JokjB18Yw1TI6oR6Z4wegy8_ajftLLhqosI5-ZE36TzPwoAKzjPl-iZEpV2U1OPHWZrdwc9N3YOyO0I_IJGQmFnXC_oacitMV2VZaTxfuCew5cPwNp5durooFNvv3DPzc9JYEctmaLsiRtfqN7pCaV30B3hnYTYZ4p2HNsUbOewBI8_Brm1v1CByitQPUFqETgmPGbf4HCTEoaH-7DfaXnAsePt73blNwJrlTlUBieew\",\"token_type\":\"bearer\",\"expires_in\":299} Access denied If the user refuses to grant access to the device, then the server response has a 400 HTTP response status code. The response contains the following error: HTTP/1.1 400 Cache-Control: no-store Content-Length: 74 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"access_denied\", \"error\": \"access_denied\" } Authorization pending It means that the request hasn't been processed by the end-user yet, therefore the request is still in process. Example: HTTP/1.1 400 Cache-Control: no-store Content-Length: 90 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"authorization_pending\", \"error\": \"authorization_pending\" } Polling too frequently If the device sends polling requests too frequently, then the server returns a 400 HTTP response status code. Then the device should increase the time interval between requests. Example: HTTP/1.1 400 Cache-Control: no-store Content-Length: 66 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"slow_down\", \"error\": \"slow_down\" } Other errors This token endpoint can return any error code already defined, for example whether client can't be authenticated or the grant type sent is invalid. Some of them could be: invalid_client , invalid_grant , invalid_request and others. Customizing Device Grant page # More about customising this page to include your organization's stylesheets, images and content in this article", "title": "Device Grant"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#oauth-20-device-authorization-grant", "text": "This OAuth 2.0 protocol extension enables OAuth clients to request user authorization from applications on devices (e.g. smart TVs, media consoles, printers) that are input-constrained or browser-less . The authorization flow defined by this RFC 8628 , sometimes referred to as the \"device flow\", instructs the user to review the authorization request on a secondary device, such as a smartphone or a personal computer, which has the requisite input and browser capabilities to complete the user interaction.", "title": "OAuth 2.0 Device Authorization Grant"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#sequence-diagram", "text": "Paste the following source text of the sequence diagram on sequencediagram.org title Oauth2.0 Device Authorization flow participant User participant Browser on Computer / Smartphone participant Device App participant Jans AS participant Third Party App User->Device App:Opens an app on device Device App->Jans AS:Sends authorization request \\n\"jans-server.com/jans-auth/restv1/device_authorization\" Jans AS->Device App:Response - \\nuser_code, device_code, verification_url, interval, expiration Device App ->User: Instructs the user to access Verification URL \\nand enter user_code note over Device App:Device App will keep polling AS for Access Token \\nuntil device authorization is completed loop till Device App recieves Access Token: Device App->Jans AS:request Access Token Jans AS->Device App:Response - \\naccess_denied \\nOR expired_token \\nOR authorization_pending \\nOR Access token end User->Browser on Computer / Smartphone:Opens a browser \\nand access verification URL Browser on Computer / Smartphone->Jans AS:send user_code to verification URL Browser on Computer / Smartphone <-Jans AS:Login and authorization prompt Browser on Computer / Smartphone->Jans AS:Authentication and consent Jans AS->Jans AS: Mark device as Authorized note over Jans AS:Subsequent polling by the Device App \\nwill return an Access Token as indicated \\nby the loop above Device App->Third Party App:Invoke API with Access Token Third Party App->Device App: return Response", "title": "Sequence Diagram"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#user-experience", "text": "First, the user requests authorization from the device: At the URL displayed on the screen, the user can input the displayed code in the device. After that, user could need to authenticate, then decide whether permissions will be granted. acr value can be specified in deviceAuthzAcr AS configuration property. Finally, the confirmation screen will be shown.", "title": "User Experience"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#acr-value-during-device-authorization", "text": "User is required to authenticate if not authenticated yet. By default acr_values is not set in authorization request, which means it relies on default AS handling. However it's possible explicitly set acr value during Device Authorization by setting deviceAuthzAcr AS configuration property.", "title": "ACR value during Device Authorization"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#request-user-and-device-codes", "text": "This first step, device sends an HTTP POST request to Jans authorization server, at /jans-auth/restv1/device_authorization which is also presented in the Discovery url published by Jans Server, this endpoint could process a common authentication method or it could also not do any authentication, depending on the configuration for the client in Jans Server.", "title": "Request user and device codes"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#parameters", "text": "Parameter Description client_id Required The client ID for your application. scope Required A space separated list of scopes that identify the resources that the device could access on the user's behalf. These values inform the consent screen that Jans server displays to the user.", "title": "Parameters"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#example", "text": "POST /restv1/device_authorization HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.org Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 client_id=123-123-123&scope=openid+profile+address+email+phone", "title": "Example"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#device-request-response", "text": "In response, the Jans authorization server generates a unique device verification code and an end-user code that are valid for a limited time and includes them in the HTTP response body using the \"application/json\" format with a 200 (OK) status code. The response contains the following parameters: Parameter Description user_code Required The end-user verification code device_code Required The device verification code verification_uri Required The end-user verification URI on the authorization server. This should be shown to the end-user because he should open this url in the rich user-agent. verification_uri_complete Optional This is similar than verification_uri , however it also includes user_code as a query param in the url. It's issued if the device wants to use QR mode for example. expires_in Required The lifetime in seconds of the device_code and user_code . interval Required The minimum amount of time in seconds that the client should wait between polling requests to the token endpoint.", "title": "Device Request response"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#example_1", "text": "HTTP/1.1 200 Content-Length: 307 Content-Type: application/json Server: Jetty(9.4.19.v20190610) { \"user_code\": \"SJFP-DTPL\", \"device_code\": \"aeb28bdc90d806ac58d4b0f832f06c3ac9c4bd03292f0c09\", \"interval\": 5, \"verification_uri_complete\": \"https://test.jans.io:8443/device-code?user_code=SJFP-DTPL\", \"verification_uri\": \"https://test.jans.io:8443/device-code\", \"expires_in\": 1800 }", "title": "Example:"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#device-display", "text": "Common flow, the device should display verification_url and user_code received from Jans server. The content that the device displays to the user should instruct the user to navigate to the verification_url on a separate device and enter the user_code . Design device interface following these rules: user_code has the following format: XXXX-XXXX where Xs represent to any ASCII character, for example: RTXD-HTLK . The length of the user_code will be always the same, therefore it's highly recommended to show it as clear and big that the user can read it easly. verification_url should be displayed also in a way that the user can read it easily. The normal length should be around 40 characters, however it could depends also on the domain used for the server. Remember that the user will need to write the whole URL manually in the web browser, therefore it's recommended to use a short URL. verification_url_complete will be used for those cases where device can show QR (Quick Response) codes or NFC (Near Field Communication) to save the user from typing the whole URI. Interaction between device and Jans server will be the same, however user can process the authorization faster. For example:", "title": "Device Display"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#user-login-authorization", "text": "The user will need to put user_code value in the browser and after that, he will be redirected to the common authorization flow, it requires login whether there is no session between the user-agent and the Jans server and grant the permissions based on the device request.", "title": "User Login & Authorization"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#poll-token", "text": "Since the user will be using a separate device to navigate to the verification_url and grant or deny access, the requesting device is not automatically notified when the user responds to the access request. For that reason, the requesting device needs to poll the Jans Server to determine when the user has responded to the request. The requesting device should continue sending polling requests until it receives a response indicating that the user has responded to the access request or until the device_code expires. The parameter interval returned in step 2 specifies the amount of time, in seconds, to wait between requests. The URL of the endpoint to poll is /jans-auth/restv1/token . The polling request contains the following parameters:", "title": "Poll Token"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#parameters_1", "text": "Parameter Description client_id Required The client ID for your application. grant_type Required Must be urn:ietf:params:oauth:grant-type:device_code . device_code Required The device verification code which is returned by Jans server in Step 2. Authentication can be done using any of those authentication methods for this token endpoint.", "title": "Parameters"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#example_2", "text": "POST /restv1/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: test.jans.io Authorization: Basic MTIzLTEyMy0xMjM6WkE1aWxpTFFDYUR4 grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&device_code=0bd7068e7fdab4bb91b313296a96462256a7370d12f073f0", "title": "Example:"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#token-response", "text": "The Jans authorization server responds to each polling request with one of the following responses: Access granted If the user granted access to the device (by clicking Allow on the consent screen), then the response contains an access token and a refresh token. The tokens enable the device to access to the resource server on the user's behalf. In this case, the server responds with all tokens required and allowed to be issued depending on the configuration in the server. Example: HTTP/1.1 200 Content-Length: 858 Content-Type: application/json Server: Jetty(9.4.19.v20190610) {\"access_token\":\"c31fc092-453b-4275-a36f-b2740c3eb1a6\",\"id_token\":\"eyJraWQiOiJlY4.2Tc4NDgxYy05OTJkLTRmN2UtYTkzMS03NjM2NTYyMzgwZjVfc2lnX3JzMjU2IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoidWdMSnAzMkxXdnI4QUdlbmdNTlF3QSIsImF1ZCI6IjEyMy0xMjMtMTIzIiwic3ViIjoiM2M2M25HdWZnWFNkMWFwNU81NFZkVjlUUDdmdjJHc0YtLWl0eVBHeFJBTSIsImlzcyI6Imh0dHBzOi8vdGVzdC5nbHV1Lm9yZzo4NDQzIiwiZXhwIjoxNTk1NjQzOTg0LCJpYXQiOjE1OTU2NDAzODQsIm94T3BlbklEQ29ubmVjdFZlcnNpb24iOiJvcGVuaWRjb25uZWN0LTEuMCJ9.fElZtuUslhSSuqTOuvGeafG4QuQoHKLpya25RHWkC5V9Xf9ODYa6tD_Tdav2D9Gff2Zz7pt8WKso-WYOqmJ3NrgMoVU7d1SMj6pYGilTL1JokjB18Yw1TI6oR6Z4wegy8_ajftLLhqosI5-ZE36TzPwoAKzjPl-iZEpV2U1OPHWZrdwc9N3YOyO0I_IJGQmFnXC_oacitMV2VZaTxfuCew5cPwNp5durooFNvv3DPzc9JYEctmaLsiRtfqN7pCaV30B3hnYTYZ4p2HNsUbOewBI8_Brm1v1CByitQPUFqETgmPGbf4HCTEoaH-7DfaXnAsePt73blNwJrlTlUBieew\",\"token_type\":\"bearer\",\"expires_in\":299} Access denied If the user refuses to grant access to the device, then the server response has a 400 HTTP response status code. The response contains the following error: HTTP/1.1 400 Cache-Control: no-store Content-Length: 74 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"access_denied\", \"error\": \"access_denied\" } Authorization pending It means that the request hasn't been processed by the end-user yet, therefore the request is still in process. Example: HTTP/1.1 400 Cache-Control: no-store Content-Length: 90 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"authorization_pending\", \"error\": \"authorization_pending\" } Polling too frequently If the device sends polling requests too frequently, then the server returns a 400 HTTP response status code. Then the device should increase the time interval between requests. Example: HTTP/1.1 400 Cache-Control: no-store Content-Length: 66 Content-Type: application/json Pragma: no-cache Server: Jetty(9.4.19.v20190610) { \"error_description\": \"slow_down\", \"error\": \"slow_down\" } Other errors This token endpoint can return any error code already defined, for example whether client can't be authenticated or the grant type sent is invalid. Some of them could be: invalid_client , invalid_grant , invalid_request and others.", "title": "Token Response"}, {"location": "janssen-server/auth-server/oauth-features/device-grant/#customizing-device-grant-page", "text": "More about customising this page to include your organization's stylesheets, images and content in this article", "title": "Customizing Device Grant page"}, {"location": "janssen-server/auth-server/oauth-features/dpop/", "tags": ["administration", "auth-server", "oauth", "feature", "dpop"], "text": "DPoP (Demonstrating Proof-of-Possession at the Application Layer) # Janssen Server supports DPoP (Demonstrating Proof-of-Possession) at the Application Layer, which is OAuth 2.0 feature to enhance the security of resources protected by access tokens. When DPoP is being used, the Janssen Server checks whether the presenter of the access token is the one to whom the access token was issued. Hence, making sure that a stolen access token is not being used by someone else to access the protected resource. OAuth 2.0 DPoP specification is available here Janssen Server also supports OAuth MTLS(Mutual TLS) as a mechanism to ensure that the token presenting party is legitimate. While MTLS should be preferred whenever it is possible to use it, for other cases like single page application(SPA), DPoP can be used. Using DPoP # Using DPoP Proof JWT # To use DPoP protection, the client needs to create DPoP Proof JWT (or DPoP Proof) and send it using DPoP request header to Janssen Server when: Requesting for a new access token Accessing a protected resource using the access token DPoP proofs are created differently for the cases listed above. DPoP specification describes how . When an access token is requested with the DPoP header (1 above), the Janssen Server returns an access token (or refresh token) that is bound(mapped) to the public key attached with the DPoP proof. Subsequently, when the client uses the access token to access the protected resource (2 above), it again creates and attaches the DPoP Proof with the request. The resource server checks the validity of the request by ensuring that the access token used is bound to the same public key which is presented in the DPoP proof in the request. The resource server uses steps laid out in the specification to acertain this. sequenceDiagram title DPoP sender-constraint access_token and refresh_token autonumber note right of RP: Authorization Code Flow RP->AS: Request authorization with dpop_jtk AS->AS: dpop_jkt saved for authorization code AS->RP: Return authorization code note right of RP: Token Request RP->AS: Request token with DPoP JWT AS->AS: Validates DPoP JWT AS->AS: Validates dpop_jkt against DPoP JWT if it's authz code AS->AS: Creates access_token bound to public key cnf/jkt note right of AS: if AT is bearer cnf/jkt is available via introspection AS->RP: Returns DPoP-bound access_token with cnf/jkt (response token_type=DPoP) RP->RS: Request resource with access_token and DPoP JWT (with \"ath\" - AT hash) RS->RS: Validates access_token against DPoP (public key match cnf/jkt) RS->RS: Validates DPoP against access_token (access_token hash in DPoP \"ath\") RS->RP: Return protected resource Authorization Code Binding to DPoP Key # Authorization Endpoint supports dpop_jkt parameter for DPoP binding of authorization code. GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz\\ &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb\\ &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\\ &code_challenge_method=S256\\ &dpop_jkt=NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs HTTP/1.1 Host: server.example.com For PAR, both ways of binging are supported: Via dpop_jkt Via DPoP header where dpop_jkt is calculated out of DPoP header value Using Introspection Endpoint # Janssen Server introspection endpoint supports the JWK thumbprint confirmation method. Using this, the resource server can introspect an access token and obtain the hash of the public key associated with the access token. Response from the introspection endpoint will share this information in the format recommended in the specificaiton Janssen Server Configuration for DPoP # Following properties of the Janssen Server can be used to tailor the behavior concerning DPoP. dpopJtiCacheTime dpopSigningAlgValuesSupported dpopTimeframe dpopUseNonce dpopNonceCacheTime dpopJktForceForAuthorizationCode Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "DPoP"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#dpop-demonstrating-proof-of-possession-at-the-application-layer", "text": "Janssen Server supports DPoP (Demonstrating Proof-of-Possession) at the Application Layer, which is OAuth 2.0 feature to enhance the security of resources protected by access tokens. When DPoP is being used, the Janssen Server checks whether the presenter of the access token is the one to whom the access token was issued. Hence, making sure that a stolen access token is not being used by someone else to access the protected resource. OAuth 2.0 DPoP specification is available here Janssen Server also supports OAuth MTLS(Mutual TLS) as a mechanism to ensure that the token presenting party is legitimate. While MTLS should be preferred whenever it is possible to use it, for other cases like single page application(SPA), DPoP can be used.", "title": "DPoP (Demonstrating Proof-of-Possession at the Application Layer)"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#using-dpop", "text": "", "title": "Using DPoP"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#using-dpop-proof-jwt", "text": "To use DPoP protection, the client needs to create DPoP Proof JWT (or DPoP Proof) and send it using DPoP request header to Janssen Server when: Requesting for a new access token Accessing a protected resource using the access token DPoP proofs are created differently for the cases listed above. DPoP specification describes how . When an access token is requested with the DPoP header (1 above), the Janssen Server returns an access token (or refresh token) that is bound(mapped) to the public key attached with the DPoP proof. Subsequently, when the client uses the access token to access the protected resource (2 above), it again creates and attaches the DPoP Proof with the request. The resource server checks the validity of the request by ensuring that the access token used is bound to the same public key which is presented in the DPoP proof in the request. The resource server uses steps laid out in the specification to acertain this. sequenceDiagram title DPoP sender-constraint access_token and refresh_token autonumber note right of RP: Authorization Code Flow RP->AS: Request authorization with dpop_jtk AS->AS: dpop_jkt saved for authorization code AS->RP: Return authorization code note right of RP: Token Request RP->AS: Request token with DPoP JWT AS->AS: Validates DPoP JWT AS->AS: Validates dpop_jkt against DPoP JWT if it's authz code AS->AS: Creates access_token bound to public key cnf/jkt note right of AS: if AT is bearer cnf/jkt is available via introspection AS->RP: Returns DPoP-bound access_token with cnf/jkt (response token_type=DPoP) RP->RS: Request resource with access_token and DPoP JWT (with \"ath\" - AT hash) RS->RS: Validates access_token against DPoP (public key match cnf/jkt) RS->RS: Validates DPoP against access_token (access_token hash in DPoP \"ath\") RS->RP: Return protected resource", "title": "Using DPoP Proof JWT"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#authorization-code-binding-to-dpop-key", "text": "Authorization Endpoint supports dpop_jkt parameter for DPoP binding of authorization code. GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz\\ &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb\\ &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\\ &code_challenge_method=S256\\ &dpop_jkt=NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs HTTP/1.1 Host: server.example.com For PAR, both ways of binging are supported: Via dpop_jkt Via DPoP header where dpop_jkt is calculated out of DPoP header value", "title": "Authorization Code Binding to DPoP Key"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#using-introspection-endpoint", "text": "Janssen Server introspection endpoint supports the JWK thumbprint confirmation method. Using this, the resource server can introspect an access token and obtain the hash of the public key associated with the access token. Response from the introspection endpoint will share this information in the format recommended in the specificaiton", "title": "Using Introspection Endpoint"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#janssen-server-configuration-for-dpop", "text": "Following properties of the Janssen Server can be used to tailor the behavior concerning DPoP. dpopJtiCacheTime dpopSigningAlgValuesSupported dpopTimeframe dpopUseNonce dpopNonceCacheTime dpopJktForceForAuthorizationCode", "title": "Janssen Server Configuration for DPoP"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/oauth-features/dpop/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/oauth-features/implicit-grant/", "tags": ["administration", "auth-server", "oauth", "feature", "grant", "implicit"], "text": "OAuth 2.0 Implicit Grant # The Implicit Grant : !!! OAuth 2.0 Security Best Current Practice absolutely discourages the use of Implicit flow. Instead, use Authorization code flow with PKCE - OAuth 2.0 for Browser-Based Apps . Further reading Sequence Diagram # sequenceDiagram title Implicit flow autonumber 1 participant Resource owner User Client->>Jans AS:Authorization Request activate Client activate Jans AS Resource owner User ->>Jans AS:User login and consent Jans AS-->>Client:Access Token in the URI fragment deactivate Client deactivate Jans AS Client ->>Jans AS:Validate Access Token activate Client activate Jans AS Jans AS-->>Client:Validate response deactivate Client deactivate Jans AS Client ->>Web - Hosted client resource:Call API with Access Token activate Client activate Jans AS Jans AS-->>Client:Protected resource deactivate Client deactivate Jans AS", "title": "Implicit Grant"}, {"location": "janssen-server/auth-server/oauth-features/implicit-grant/#oauth-20-implicit-grant", "text": "The Implicit Grant : !!! OAuth 2.0 Security Best Current Practice absolutely discourages the use of Implicit flow. Instead, use Authorization code flow with PKCE - OAuth 2.0 for Browser-Based Apps . Further reading", "title": "OAuth 2.0 Implicit Grant"}, {"location": "janssen-server/auth-server/oauth-features/implicit-grant/#sequence-diagram", "text": "sequenceDiagram title Implicit flow autonumber 1 participant Resource owner User Client->>Jans AS:Authorization Request activate Client activate Jans AS Resource owner User ->>Jans AS:User login and consent Jans AS-->>Client:Access Token in the URI fragment deactivate Client deactivate Jans AS Client ->>Jans AS:Validate Access Token activate Client activate Jans AS Jans AS-->>Client:Validate response deactivate Client deactivate Jans AS Client ->>Web - Hosted client resource:Call API with Access Token activate Client activate Jans AS Jans AS-->>Client:Protected resource deactivate Client deactivate Jans AS", "title": "Sequence Diagram"}, {"location": "janssen-server/auth-server/oauth-features/mtls/", "tags": ["administration", "auth-server", "oauth", "feature", "mtls", "mutual TLS"], "text": "mTLS (Mutual Transport Layer Security) # What Is mTLS? # mTLS is a process that establishes an encrypted TLS connection in which both parties use X.509 digital certificates to authenticate each other. mTLS can help mitigate the risk of moving services to the cloud and can help prevent malicious third parties from imitating genuine apps. Where Is mTLS Useful? # Mutual client certificate authentication can be used any time the server needs to ensure the authenticity and validity of either a specific user or a specific device. For example, a client certificate can be issued to a company-owned laptop to identify and authorize it on a corporate network. Alternatively, a client certificate could be issued to an employee and stored on a smart card, which then allows the employee to gain access to applications or restricted areas of a building. In practice, mTLS can identify and authorize the following: Devices onto a corporate network. Users into applications. Content delivery network (CDNs) or cloud security services to back-end web servers. Business-to-business (B2B) data exchanges that use APIs. Internet of Things (IoT) sensors, such as remote traffic cameras. Microservice architectures in which each microservice must ensure that each component it communicates with is valid and not tampered with. mTLS in Jans Auth # Jans Auth supports mTLS , and to configure it we must take these considerations into account: During DCR client registration, the token_endpoint_auth_method field can receive 2 new values: tls_client_auth : indicates that client authentication to the authorization server will occur with mutual TLS utilizing the PKI method of associating a certificate to a client. self_signed_tls_client_auth : Indicates that client authentication to the authorization server will occur using mutual TLS with the client utilizing a self-signed certificate. There is new client property tls_client_auth_subject_dn used to compare Subject DN of the certificate with configured value of client entry when authentication method is set to tls_client_auth (saved in tls_client_auth_subject_dn or oxAttributes on persistence layer). If MTLS Authentication is used then access_token automatically saves certificate S256 hash of certificates which can be validated by RP. If access_token is JWT then x5t#S256 claim is added to payload of the token. Otherwise, token can be introspected. { \"active\": true, \"iss\": \"https://server.example.com\", \"sub\": \"ty.webb@example.com\", \"exp\": 1493726400, \"nbf\": 1493722800, \"cnf\": { \"x5t#S256\": \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" }, ..., ... } Configuring Apache for mTLS # The information below belongs to apache and web client (usually web browser) mutual authentication setup method. This also includes basic checks to be performed for the setup. Is mod_ssl installed: Run below command to confirm if the ssl module is installed. apachectl -M | grep ssl If we get ssl_module related output, then we're good to proceed. The output could look like: root@jans:~# apachectl -M | grep ssl ssl_module (shared) Usually third party or Certbot SSL certs are used for web server ssl connections. In that case no extra configuration is necessary. But if we want to use self-signed certs, then follow on. Self-Signed SSL Certs # Server-Side mTLS setup # Now, we're covering the case if you want to deploy your own CA Cert. 1. Open Terminal. # 2. Create a new directory to generate certificates. # mkdir /etc/certs/mtlscert Change to the directory created. cd /etc/certs/mtlscert 3. Generate Self-Signed CA Cert. # Run below command: openssl req -newkey rsa:2048 -nodes -keyform PEM -keyout example-ca.key -x509 -days 3650 -outform PEM -out example-ca.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -newkey rsa:2048 -nodes -keyform PEM -keyout example-ca.key -x509 -days 3650 -outform PEM -out example-ca.crt Generating a RSA private key .........................................+++++ .........................................+++++ writing new private key to 'example-ca.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Above command will create two files: example-ca.key and example-ca.crt . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key 4. Generate private key. # Run below command: openssl genrsa -out example.key 2048 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl genrsa -out example.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ......................................+++++ ..........................................................................................................+++++ e is 65537 (0x010001) Above command creates: example.key . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.key 5. Generate a server CSR (Certificate Signing Request): # Run below command: openssl req -new -key example.key -out example.csr Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -new -key example.key -out example.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Above command will create the file: example.csr . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.csr example.key 6. Sign the CSR example.csr we just generated. # Run below command: openssl x509 -req -in example.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 100 -days 365 -outform PEM -out example.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl x509 -req -in example.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 100 -days 365 -outform PEM -out example.crt Signature ok subject=C = US, ST = Austin, L = TX, O = Janssen Org., OU = IT, CN = yourdomain.com, emailAddress = youremail@yourdomain.com Getting CA Private Key Above command will create the file: example.crt for 365 days. root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.crt example.csr example.key 7. Configure Apache2. # Add the following lines in the /etc/apache2/sites-available/https_jans.conf file. SSLEngine On SSLCertificateFile /etc/certs/mtlscert/example.crt SSLCertificateKeyFile /etc/certs/mtlscert/example.key SSLCACertificateFile /etc/certs/mtlscert/example-ca.crt It is critical to configure certificates validation on Apache 2 correctly, since actual validation of the certificates is performed by Apache 2. After Apache certificate validation is configured correctly, make sure there is client certificate forward to jans-auth application. jans-auth (AS) expects certificate in X-ClientCert header. <LocationMatch /jans-auth> SSLVerifyClient require SSLVerifyDepth 10 SSLOptions -StdEnvVars +ExportCertData # Forward certificate to destination server (oxauth) RequestHeader set X-ClientCert %{SSL_CLIENT_CERT}s </LocationMatch> Now we must restart the Apache2 server. service apache2 restart To check if SSL cert on apache works: openssl s_client -connect yourdomain.com:443 Client-Side mTLS setup # 1. Generate private key. # Run below command: openssl genrsa -out example-cli.key 2048 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl genrsa -out example-cli.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ...........................................+++++ .............................................+++++ e is 65537 (0x010001) Above command will create the file: example-cli.key . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.key example.crt example.csr example.key 2. Generate a client CSR (Certificate Signing Request). # Run below command: openssl req -new -key example-cli.key -out example-cli.csr Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -new -key example-cli.key -out example-cli.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Client Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Above command will create the file: example-cli.csr . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.csr example-cli.key example.crt example.csr example.key 3. Sign the CSR example-cli.csr we just generated. # Run below command: openssl x509 -req -in example-cli.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 101 -days 365 -outform PEM -out example-cli.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl x509 -req -in example-cli.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 101 -days 365 -outform PEM -out example-cli.crt Signature ok subject=C = US, ST = Austin, L = TX, O = Janssen Client Org., OU = IT, CN = yourdomain.com, emailAddress = youremail@yourdomain.com Getting CA Private Key Above command will create the file: example-cli.crt for 365 days. root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.crt example-cli.csr example-cli.key example.crt example.csr example.key 4. Generate PKCS12 cert # Some browsers need client certs to be in the format pkcs12 . Run below command: openssl pkcs12 -export -inkey example-cli.key -in example-cli.crt -out example-cli.p12 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl pkcs12 -export -inkey example-cli.key -in example-cli.crt -out example-cli.p12 Enter Export Password: Verifying - Enter Export Password: Above command will create the file: example-cli.p12 . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.crt example-cli.csr example-cli.key example-cli.p12 example.crt example.csr example.key mTLS testing # We are going to run an mTLS example where we will perform the following flow: Register new client. Call authorize endpoint. Call token endpoint. Call introspection endpoint. Previously we need to configure the client's certificate in the browser of your choice. Google Chrome Settings # In the search bar go to chrome://settings/certificates . In the Your Certificates section, click on Import button. Select the certificate example-cli.p12 and enter the password you set when generating it. Firefox Settings # In the search bar go to about:preferences#privacy . Click on View Certificates . In the Your Certificates section, click on Import button. Select the certificate example-cli.p12 and enter the password you set when generating it. Solving the curl problem # If you have openssl version 3.x.x , most likely when you are trying to consume the /.well-known/openid-configuration endpoint. curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' You will get the following error: root@jans~# curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' curl: (58) could not parse PKCS12 file, check password, OpenSSL error error:0308010C:digital envelope routines::unsupported To fix this error, edit the file /etc/ssl/openssl.cnf and make sure that these lines are uncommented and if they are not, add them: openssl_conf = openssl_init [openssl_init] providers = provider_sect [provider_sect] default = default_sect legacy = legacy_sect [default_sect] activate = 1 [legacy_sect] activate = 1 Once this change is done, you should be able to consume the /.well-known/openid-configuration endpoint without any problems root@jans~# curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : true, \"issuer\" : \"https://<YOUR_DOMAIN>\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/authorize\", ..., ..., ... } 1. Register new client # Run below command: curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/register' \\ --header 'Content-Type: application/json' \\ --data '{ \"client_name\": \"Test Client mTLS\", \"application_type\": \"web\", \"access_token_as_jwt\": true, \"token_endpoint_auth_method\": \"self_signed_tls_client_auth\", \"jwks\": { \"keys\": [ { \"kid\": \"YOUR_KID\", \"kty\": \"RSA\", \"alg\": \"RS256\", \"use\": \"sig\", \"e\": \"AQAB\", \"n\": \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" } ] }, \"scope\": [ \"openid\", \"profile\", \"email\" ], \"grant_types\": [ \"authorization_code\" ], \"response_types\": [ \"code\", \"token\", \"id_token\" ], \"redirect_uris\": [ https://<YOUR_DOMAIN>/jans-auth-rp/home.htm ] }' Response: { \"allow_spontaneous_scopes\" : false , \"jwks\" : { \"keys\" : [ { \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"kid\" : \"your-kid\" , \"alg\" : \"RS256\" , \"n\" : \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" } ] }, \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/register?client_id=d16994c2-313c-4440-9713-25290fbb89a9\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"93a52334-bf79-4414-bc9a-983b6921597c\" , \"client_id\" : \"d16994c2-313c-4440-9713-25290fbb89a9\" , \"token_endpoint_auth_method\" : \"self_signed_tls_client_auth\" , \"scope\" : \"email openid profile\" , \"client_secret\" : \"e1c9e9df-e542-4225-adb4-d0590f85d97d\" , \"client_id_issued_at\" : 1698114939 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"client_name\" : \"Test Client mTLS\" , \"par_lifetime\" : 600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : true , \"grant_types\" : [ \"implicit\" , \"refresh_token\" , \"authorization_code\" ], \"subject_type\" : \"pairwise\" , \"additional_token_endpoint_auth_methods\" : [], \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris\" : [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1698201339 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" , \"id_token\" , \"token\" ] } NOTE: To obtain the jwks field data, follow the next step. P12 to JWKS # To get the fields from jwks you can use the following command: openssl x509 -in example-cli.p12 -pubkey -noout | pem-jwk | jq '{kid: \"your-kid\", kty: .kty , alg: \"RS256\" , use: \"sig\", e: .e, n: .n }' Make sure you have pem-jwk installed, use the command: npm install -g pem-jwk or yarn global add pem-jwk . Below is a sample run of the command. root@jans:~# openssl x509 -in example-cli.p12 -pubkey -noout | pem-jwk | jq '{kid: \"your-kid\", kty: .kty , alg: \"RS256\" , use: \"sig\", e: .e, n: .n }' Enter pass phrase for PKCS12 import pass phrase: { \"kid\": \"your-kid\", \"kty\": \"RSA\", \"alg\": \"RS256\", \"use\": \"sig\", \"e\": \"AQAB\", \"n\": \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" } 2. Call authorize endpoint # From your browser of choice call the following url: https://<YOUR_DOMAIN>/jans-auth/restv1/authorize?response_type=code&client_id=d16994c2-313c-4440-9713-25290fbb89a9&scope=openid+profil+email&redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm&state=f9bb35cb-3485-4ae4-aa8e-63e9a97b6e5d&nonce=4a2f07cb-521b-465c-8b06-0c17711a96a7 URL parameters: response_type=code client_id=d16994c2-313c-4440-9713-25290fbb89a9 scope=openid+profil+email redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm state=f9bb35cb-3485-4ae4-aa8e-63e9a97b6e5d nonce=4a2f07cb-521b-465c-8b06-0c17711a96a7 The field we need to obtain is the code . 3. Call token endpoint # Previously we have obtained the code field, we will use this value to call the endpoint token . curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/token' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=authorization_code' \\ --data-urlencode 'redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm' \\ --data-urlencode 'client_id=d16994c2-313c-4440-9713-25290fbb89a9' \\ --data-urlencode 'client_secret=<YOUR_CLIENT_SECRET>' \\ --data-urlencode 'code=<YOUR_CODE>' Response: { \"access_token\" : \"eyJraWQiOiJjb25uZWN0X2NmNjBiZWZmLTU1MzUtNDllNS04MWQ5LTM5ZDM4ZmNlMWNhMF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJNSGdqa2hnTktmZWF4ZUVEY0wycEt5c1EwVUQ4RDk1QUd5NFBGXzI2cmlnIiwiY29kZSI6ImE0NWE5ODI5LTFkMDQtNGQxNS05NjllLWRiMjk3Mzk4ZTdjMyIsImlzcyI6Imh0dHBzOi8vbWlsdG9uLWNoLWhhcmR5LW1pdGUuZ2x1dS5pbmZvIiwidG9rZW5fdHlwZSI6IkJlYXJlciIsImNsaWVudF9pZCI6IjVkODM1NDA3LTFlZjMtNDQxZC04YWU2LTZiYmRkNTcyNzZjYyIsImF1ZCI6IjVkODM1NDA3LTFlZjMtNDQxZC04YWU2LTZiYmRkNTcyNzZjYyIsImFjciI6ImJhc2ljIiwieDV0I1MyNTYiOiJPeHRJQXRBMEMwTkwteTR2UmZLeDd6TExFZXhfWG1DelduUWJ4ejZUem5ZIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsImVtYWlsIl0sImF1dGhfdGltZSI6MTY5ODE5NDczNiwiZXhwIjoxNjk4Mjc4MDQzLCJpYXQiOjE2OTgxOTY4MzIsInVzZXJuYW1lIjoiRGVmYXVsdCBBZG1pbiBVc2VyIn0.JpK7JYy6Avui3LNbxTKBYJW9fqjEIqijCXPw9fvqEO1kqO7AUozOEof00hPKzJo1Dh7VgGpY89MiAduDUoU3QCemtFsNSd1DCyExl2s3w5OF2mUm6nMzjaS377ZQQ39DAq91OGFFq_ISt4JIhWRf7_xUEvlLRAttTqxE5qp1ZYvgAYu07jbVJX8WqJvxYz3rZ3J-4kq2FLREunRf5KxYaHO-oKzrmhRVPTc_cj1vqwSfu8vRjLmx4P-eN7SgVNa0XmZ8WClLnmchucGBH6rYq3bXZWsOKixwLhno_2vPe1MmbK3XnNNBu_fm_bL2N5kgAwr9b-upoBJc08IyCje1vA\" , \"refresh_token\" : \"1e58e2c9-4175-4b3f-8170-65544b1a7c48\" , \"id_token\" : \"eyJraWQiOiJjb25uZWN0X2NmNjBiZWZmLTU1MzUtNDllNS04MWQ5LTM5ZDM4ZmNlMWNhMF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoib1NoVDE4YUdRVHdtNXBjT255dkNMUSIsInN1YiI6Ik1IZ2praGdOS2ZlYXhlRURjTDJwS3lzUTBVRDhEOTVBR3k0UEZfMjZyaWciLCJhbXIiOlsiMTAiXSwiaXNzIjoiaHR0cHM6Ly9taWx0b24tY2gtaGFyZHktbWl0ZS5nbHV1LmluZm8iLCJub25jZSI6ImMxNGQ2Y2RlLWQ5NTYtNDM4Zi04Mzk5LTQ3MzdkNWZlOTkyOSIsInNpZCI6IjI2ZTM4YTJmLTEzZTktNGY4Yi05MzdjLTQ3M2ViMjdlNzFkNiIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiNWQ4MzU0MDctMWVmMy00NDFkLThhZTYtNmJiZGQ1NzI3NmNjIiwicmFuZG9tIjoiMjVhZDViMmUtMGNkMi00Mjg3LTg1M2ItZWY3NWRhZjMzNWMwIiwiYWNyIjoiYmFzaWMiLCJjX2hhc2giOiJwM2ZJVHlGT09fd0tRZW9QT1VkWWF3IiwiYXV0aF90aW1lIjoxNjk4MTk0NzM2LCJleHAiOjE2OTgyMDA0MzIsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNjk4MTk2ODMyfQ.GMXkiFGcCy6dXI8gPPuCLd977Gs_rkG1w3FrNx_HlSnmcDUSsEQHvPxpA99Y3L8Z82uLHYCbP5Vga6iCEOmBBHnu9jEsmYgp-TSrB31HV-5g7-o4ZWJG05SdL9KgSP3PyDXRqcE0VFxBJ-uJSyvI-htQ4GUXMIhqVhbJJynPNosXtZvvDVIw1NBThupmqx58cozf5tIdnwaeiuN_Ce2XQrjZBiachI6KWFa-Mstrsdw1E6Ny_4bP-1UmeNgScd6pmIUemGsfclxIAgO0lACqgbGh7wo0PljbhEkGU_i9kP--0KJHkBkUxflULW3aAqdYtG9hEr_JEIddHVxXbi1c_w\" , \"token_type\" : \"Bearer\" , \"expires_in\" : 81210 } Once we have obtained the access_token in jwt(json web token) format, we will do the last step. 4. Call introspection endpoint # Run below command: curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/introspection' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --header 'Authorization: Bearer <ACCESS_TOKEN>' \\ --data-urlencode 'token=<ACCESS_TOKEN>' \\ --data-urlencode 'response_as_jwt=false' Response: { \"sub\" : \"MHgjkhgNKfeaxeEDcL2pKysQ0UD8D95AGy4PF_26rig\" , \"iss\" : \"https://<YOUR_DOMAIN>\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"d16994c2-313c-4440-9713-25290fbb89a9\" , \"aud\" : \"5d835407-1ef3-441d-8ae6-6bbdd57276cc\" , \"acr\" : \"basic\" , \"nbf\" : null , \"scope\" : \"openid profile email\" , \"auth_time\" : 1698194736 , \"cnf\" : { \"x5t#S256\" : \"OxtIAtA0C0NL-y4vRfKx7zLLEex_XmCzWnQbxz6TznY\" }, \"exp\" : 1698278043 , \"iat\" : 1698201265 , \"jti\" : null , \"username\" : \"admin\" } Specification document # For more details of the specification, you can have a look at the following link OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens", "title": "MTLS"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#mtls-mutual-transport-layer-security", "text": "", "title": "mTLS (Mutual Transport Layer Security)"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#what-is-mtls", "text": "mTLS is a process that establishes an encrypted TLS connection in which both parties use X.509 digital certificates to authenticate each other. mTLS can help mitigate the risk of moving services to the cloud and can help prevent malicious third parties from imitating genuine apps.", "title": "What Is mTLS?"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#where-is-mtls-useful", "text": "Mutual client certificate authentication can be used any time the server needs to ensure the authenticity and validity of either a specific user or a specific device. For example, a client certificate can be issued to a company-owned laptop to identify and authorize it on a corporate network. Alternatively, a client certificate could be issued to an employee and stored on a smart card, which then allows the employee to gain access to applications or restricted areas of a building. In practice, mTLS can identify and authorize the following: Devices onto a corporate network. Users into applications. Content delivery network (CDNs) or cloud security services to back-end web servers. Business-to-business (B2B) data exchanges that use APIs. Internet of Things (IoT) sensors, such as remote traffic cameras. Microservice architectures in which each microservice must ensure that each component it communicates with is valid and not tampered with.", "title": "Where Is mTLS Useful?"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#mtls-in-jans-auth", "text": "Jans Auth supports mTLS , and to configure it we must take these considerations into account: During DCR client registration, the token_endpoint_auth_method field can receive 2 new values: tls_client_auth : indicates that client authentication to the authorization server will occur with mutual TLS utilizing the PKI method of associating a certificate to a client. self_signed_tls_client_auth : Indicates that client authentication to the authorization server will occur using mutual TLS with the client utilizing a self-signed certificate. There is new client property tls_client_auth_subject_dn used to compare Subject DN of the certificate with configured value of client entry when authentication method is set to tls_client_auth (saved in tls_client_auth_subject_dn or oxAttributes on persistence layer). If MTLS Authentication is used then access_token automatically saves certificate S256 hash of certificates which can be validated by RP. If access_token is JWT then x5t#S256 claim is added to payload of the token. Otherwise, token can be introspected. { \"active\": true, \"iss\": \"https://server.example.com\", \"sub\": \"ty.webb@example.com\", \"exp\": 1493726400, \"nbf\": 1493722800, \"cnf\": { \"x5t#S256\": \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" }, ..., ... }", "title": "mTLS in Jans Auth"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#configuring-apache-for-mtls", "text": "The information below belongs to apache and web client (usually web browser) mutual authentication setup method. This also includes basic checks to be performed for the setup. Is mod_ssl installed: Run below command to confirm if the ssl module is installed. apachectl -M | grep ssl If we get ssl_module related output, then we're good to proceed. The output could look like: root@jans:~# apachectl -M | grep ssl ssl_module (shared) Usually third party or Certbot SSL certs are used for web server ssl connections. In that case no extra configuration is necessary. But if we want to use self-signed certs, then follow on.", "title": "Configuring Apache for mTLS"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#self-signed-ssl-certs", "text": "", "title": "Self-Signed SSL Certs"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#server-side-mtls-setup", "text": "Now, we're covering the case if you want to deploy your own CA Cert.", "title": "Server-Side mTLS setup"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#1-open-terminal", "text": "", "title": "1. Open Terminal."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#2-create-a-new-directory-to-generate-certificates", "text": "mkdir /etc/certs/mtlscert Change to the directory created. cd /etc/certs/mtlscert", "title": "2. Create a new directory to generate certificates."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#3-generate-self-signed-ca-cert", "text": "Run below command: openssl req -newkey rsa:2048 -nodes -keyform PEM -keyout example-ca.key -x509 -days 3650 -outform PEM -out example-ca.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -newkey rsa:2048 -nodes -keyform PEM -keyout example-ca.key -x509 -days 3650 -outform PEM -out example-ca.crt Generating a RSA private key .........................................+++++ .........................................+++++ writing new private key to 'example-ca.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Above command will create two files: example-ca.key and example-ca.crt . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key", "title": "3. Generate Self-Signed CA Cert."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#4-generate-private-key", "text": "Run below command: openssl genrsa -out example.key 2048 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl genrsa -out example.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ......................................+++++ ..........................................................................................................+++++ e is 65537 (0x010001) Above command creates: example.key . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.key", "title": "4. Generate private key."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#5-generate-a-server-csr-certificate-signing-request", "text": "Run below command: openssl req -new -key example.key -out example.csr Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -new -key example.key -out example.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Above command will create the file: example.csr . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.csr example.key", "title": "5. Generate a server CSR (Certificate Signing Request):"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#6-sign-the-csr-examplecsr-we-just-generated", "text": "Run below command: openssl x509 -req -in example.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 100 -days 365 -outform PEM -out example.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl x509 -req -in example.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 100 -days 365 -outform PEM -out example.crt Signature ok subject=C = US, ST = Austin, L = TX, O = Janssen Org., OU = IT, CN = yourdomain.com, emailAddress = youremail@yourdomain.com Getting CA Private Key Above command will create the file: example.crt for 365 days. root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example.crt example.csr example.key", "title": "6. Sign the CSR example.csr we just generated."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#7-configure-apache2", "text": "Add the following lines in the /etc/apache2/sites-available/https_jans.conf file. SSLEngine On SSLCertificateFile /etc/certs/mtlscert/example.crt SSLCertificateKeyFile /etc/certs/mtlscert/example.key SSLCACertificateFile /etc/certs/mtlscert/example-ca.crt It is critical to configure certificates validation on Apache 2 correctly, since actual validation of the certificates is performed by Apache 2. After Apache certificate validation is configured correctly, make sure there is client certificate forward to jans-auth application. jans-auth (AS) expects certificate in X-ClientCert header. <LocationMatch /jans-auth> SSLVerifyClient require SSLVerifyDepth 10 SSLOptions -StdEnvVars +ExportCertData # Forward certificate to destination server (oxauth) RequestHeader set X-ClientCert %{SSL_CLIENT_CERT}s </LocationMatch> Now we must restart the Apache2 server. service apache2 restart To check if SSL cert on apache works: openssl s_client -connect yourdomain.com:443", "title": "7. Configure Apache2."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#client-side-mtls-setup", "text": "", "title": "Client-Side mTLS setup"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#1-generate-private-key", "text": "Run below command: openssl genrsa -out example-cli.key 2048 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl genrsa -out example-cli.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ...........................................+++++ .............................................+++++ e is 65537 (0x010001) Above command will create the file: example-cli.key . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.key example.crt example.csr example.key", "title": "1. Generate private key."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#2-generate-a-client-csr-certificate-signing-request", "text": "Run below command: openssl req -new -key example-cli.key -out example-cli.csr Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl req -new -key example-cli.key -out example-cli.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Austin Locality Name (eg, city) []:TX Organization Name (eg, company) [Internet Widgits Pty Ltd]:Janssen Client Org. Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com Email Address []:youremail@yourdomain.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Above command will create the file: example-cli.csr . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.csr example-cli.key example.crt example.csr example.key", "title": "2. Generate a client CSR (Certificate Signing Request)."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#3-sign-the-csr-example-clicsr-we-just-generated", "text": "Run below command: openssl x509 -req -in example-cli.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 101 -days 365 -outform PEM -out example-cli.crt Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl x509 -req -in example-cli.csr -CA example-ca.crt -CAkey example-ca.key -set_serial 101 -days 365 -outform PEM -out example-cli.crt Signature ok subject=C = US, ST = Austin, L = TX, O = Janssen Client Org., OU = IT, CN = yourdomain.com, emailAddress = youremail@yourdomain.com Getting CA Private Key Above command will create the file: example-cli.crt for 365 days. root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.crt example-cli.csr example-cli.key example.crt example.csr example.key", "title": "3. Sign the CSR example-cli.csr we just generated."}, {"location": "janssen-server/auth-server/oauth-features/mtls/#4-generate-pkcs12-cert", "text": "Some browsers need client certs to be in the format pkcs12 . Run below command: openssl pkcs12 -export -inkey example-cli.key -in example-cli.crt -out example-cli.p12 Below is a sample run of the command. root@jans:/etc/certs/mtlscert# openssl pkcs12 -export -inkey example-cli.key -in example-cli.crt -out example-cli.p12 Enter Export Password: Verifying - Enter Export Password: Above command will create the file: example-cli.p12 . root@jans:/etc/certs/mtlscert# ls example-ca.crt example-ca.key example-cli.crt example-cli.csr example-cli.key example-cli.p12 example.crt example.csr example.key", "title": "4. Generate PKCS12 cert"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#mtls-testing", "text": "We are going to run an mTLS example where we will perform the following flow: Register new client. Call authorize endpoint. Call token endpoint. Call introspection endpoint. Previously we need to configure the client's certificate in the browser of your choice.", "title": "mTLS testing"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#google-chrome-settings", "text": "In the search bar go to chrome://settings/certificates . In the Your Certificates section, click on Import button. Select the certificate example-cli.p12 and enter the password you set when generating it.", "title": "Google Chrome Settings"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#firefox-settings", "text": "In the search bar go to about:preferences#privacy . Click on View Certificates . In the Your Certificates section, click on Import button. Select the certificate example-cli.p12 and enter the password you set when generating it.", "title": "Firefox Settings"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#solving-the-curl-problem", "text": "If you have openssl version 3.x.x , most likely when you are trying to consume the /.well-known/openid-configuration endpoint. curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' You will get the following error: root@jans~# curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' curl: (58) could not parse PKCS12 file, check password, OpenSSL error error:0308010C:digital envelope routines::unsupported To fix this error, edit the file /etc/ssl/openssl.cnf and make sure that these lines are uncommented and if they are not, add them: openssl_conf = openssl_init [openssl_init] providers = provider_sect [provider_sect] default = default_sect legacy = legacy_sect [default_sect] activate = 1 [legacy_sect] activate = 1 Once this change is done, you should be able to consume the /.well-known/openid-configuration endpoint without any problems root@jans~# curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/.well-known/openid-configuration' { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : true, \"issuer\" : \"https://<YOUR_DOMAIN>\", \"userinfo_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"access_token_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorization_endpoint\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/authorize\", ..., ..., ... }", "title": "Solving the curl problem"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#1-register-new-client", "text": "Run below command: curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/register' \\ --header 'Content-Type: application/json' \\ --data '{ \"client_name\": \"Test Client mTLS\", \"application_type\": \"web\", \"access_token_as_jwt\": true, \"token_endpoint_auth_method\": \"self_signed_tls_client_auth\", \"jwks\": { \"keys\": [ { \"kid\": \"YOUR_KID\", \"kty\": \"RSA\", \"alg\": \"RS256\", \"use\": \"sig\", \"e\": \"AQAB\", \"n\": \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" } ] }, \"scope\": [ \"openid\", \"profile\", \"email\" ], \"grant_types\": [ \"authorization_code\" ], \"response_types\": [ \"code\", \"token\", \"id_token\" ], \"redirect_uris\": [ https://<YOUR_DOMAIN>/jans-auth-rp/home.htm ] }' Response: { \"allow_spontaneous_scopes\" : false , \"jwks\" : { \"keys\" : [ { \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"kid\" : \"your-kid\" , \"alg\" : \"RS256\" , \"n\" : \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" } ] }, \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://<YOUR_DOMAIN>/jans-auth/restv1/register?client_id=d16994c2-313c-4440-9713-25290fbb89a9\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"93a52334-bf79-4414-bc9a-983b6921597c\" , \"client_id\" : \"d16994c2-313c-4440-9713-25290fbb89a9\" , \"token_endpoint_auth_method\" : \"self_signed_tls_client_auth\" , \"scope\" : \"email openid profile\" , \"client_secret\" : \"e1c9e9df-e542-4225-adb4-d0590f85d97d\" , \"client_id_issued_at\" : 1698114939 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"client_name\" : \"Test Client mTLS\" , \"par_lifetime\" : 600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : true , \"grant_types\" : [ \"implicit\" , \"refresh_token\" , \"authorization_code\" ], \"subject_type\" : \"pairwise\" , \"additional_token_endpoint_auth_methods\" : [], \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris\" : [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1698201339 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" , \"id_token\" , \"token\" ] } NOTE: To obtain the jwks field data, follow the next step.", "title": "1. Register new client"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#p12-to-jwks", "text": "To get the fields from jwks you can use the following command: openssl x509 -in example-cli.p12 -pubkey -noout | pem-jwk | jq '{kid: \"your-kid\", kty: .kty , alg: \"RS256\" , use: \"sig\", e: .e, n: .n }' Make sure you have pem-jwk installed, use the command: npm install -g pem-jwk or yarn global add pem-jwk . Below is a sample run of the command. root@jans:~# openssl x509 -in example-cli.p12 -pubkey -noout | pem-jwk | jq '{kid: \"your-kid\", kty: .kty , alg: \"RS256\" , use: \"sig\", e: .e, n: .n }' Enter pass phrase for PKCS12 import pass phrase: { \"kid\": \"your-kid\", \"kty\": \"RSA\", \"alg\": \"RS256\", \"use\": \"sig\", \"e\": \"AQAB\", \"n\": \"5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ\" }", "title": "P12 to JWKS"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#2-call-authorize-endpoint", "text": "From your browser of choice call the following url: https://<YOUR_DOMAIN>/jans-auth/restv1/authorize?response_type=code&client_id=d16994c2-313c-4440-9713-25290fbb89a9&scope=openid+profil+email&redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm&state=f9bb35cb-3485-4ae4-aa8e-63e9a97b6e5d&nonce=4a2f07cb-521b-465c-8b06-0c17711a96a7 URL parameters: response_type=code client_id=d16994c2-313c-4440-9713-25290fbb89a9 scope=openid+profil+email redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm state=f9bb35cb-3485-4ae4-aa8e-63e9a97b6e5d nonce=4a2f07cb-521b-465c-8b06-0c17711a96a7 The field we need to obtain is the code .", "title": "2. Call authorize endpoint"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#3-call-token-endpoint", "text": "Previously we have obtained the code field, we will use this value to call the endpoint token . curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/token' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'grant_type=authorization_code' \\ --data-urlencode 'redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm' \\ --data-urlencode 'client_id=d16994c2-313c-4440-9713-25290fbb89a9' \\ --data-urlencode 'client_secret=<YOUR_CLIENT_SECRET>' \\ --data-urlencode 'code=<YOUR_CODE>' Response: { \"access_token\" : \"eyJraWQiOiJjb25uZWN0X2NmNjBiZWZmLTU1MzUtNDllNS04MWQ5LTM5ZDM4ZmNlMWNhMF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJNSGdqa2hnTktmZWF4ZUVEY0wycEt5c1EwVUQ4RDk1QUd5NFBGXzI2cmlnIiwiY29kZSI6ImE0NWE5ODI5LTFkMDQtNGQxNS05NjllLWRiMjk3Mzk4ZTdjMyIsImlzcyI6Imh0dHBzOi8vbWlsdG9uLWNoLWhhcmR5LW1pdGUuZ2x1dS5pbmZvIiwidG9rZW5fdHlwZSI6IkJlYXJlciIsImNsaWVudF9pZCI6IjVkODM1NDA3LTFlZjMtNDQxZC04YWU2LTZiYmRkNTcyNzZjYyIsImF1ZCI6IjVkODM1NDA3LTFlZjMtNDQxZC04YWU2LTZiYmRkNTcyNzZjYyIsImFjciI6ImJhc2ljIiwieDV0I1MyNTYiOiJPeHRJQXRBMEMwTkwteTR2UmZLeDd6TExFZXhfWG1DelduUWJ4ejZUem5ZIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsImVtYWlsIl0sImF1dGhfdGltZSI6MTY5ODE5NDczNiwiZXhwIjoxNjk4Mjc4MDQzLCJpYXQiOjE2OTgxOTY4MzIsInVzZXJuYW1lIjoiRGVmYXVsdCBBZG1pbiBVc2VyIn0.JpK7JYy6Avui3LNbxTKBYJW9fqjEIqijCXPw9fvqEO1kqO7AUozOEof00hPKzJo1Dh7VgGpY89MiAduDUoU3QCemtFsNSd1DCyExl2s3w5OF2mUm6nMzjaS377ZQQ39DAq91OGFFq_ISt4JIhWRf7_xUEvlLRAttTqxE5qp1ZYvgAYu07jbVJX8WqJvxYz3rZ3J-4kq2FLREunRf5KxYaHO-oKzrmhRVPTc_cj1vqwSfu8vRjLmx4P-eN7SgVNa0XmZ8WClLnmchucGBH6rYq3bXZWsOKixwLhno_2vPe1MmbK3XnNNBu_fm_bL2N5kgAwr9b-upoBJc08IyCje1vA\" , \"refresh_token\" : \"1e58e2c9-4175-4b3f-8170-65544b1a7c48\" , \"id_token\" : \"eyJraWQiOiJjb25uZWN0X2NmNjBiZWZmLTU1MzUtNDllNS04MWQ5LTM5ZDM4ZmNlMWNhMF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoib1NoVDE4YUdRVHdtNXBjT255dkNMUSIsInN1YiI6Ik1IZ2praGdOS2ZlYXhlRURjTDJwS3lzUTBVRDhEOTVBR3k0UEZfMjZyaWciLCJhbXIiOlsiMTAiXSwiaXNzIjoiaHR0cHM6Ly9taWx0b24tY2gtaGFyZHktbWl0ZS5nbHV1LmluZm8iLCJub25jZSI6ImMxNGQ2Y2RlLWQ5NTYtNDM4Zi04Mzk5LTQ3MzdkNWZlOTkyOSIsInNpZCI6IjI2ZTM4YTJmLTEzZTktNGY4Yi05MzdjLTQ3M2ViMjdlNzFkNiIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiNWQ4MzU0MDctMWVmMy00NDFkLThhZTYtNmJiZGQ1NzI3NmNjIiwicmFuZG9tIjoiMjVhZDViMmUtMGNkMi00Mjg3LTg1M2ItZWY3NWRhZjMzNWMwIiwiYWNyIjoiYmFzaWMiLCJjX2hhc2giOiJwM2ZJVHlGT09fd0tRZW9QT1VkWWF3IiwiYXV0aF90aW1lIjoxNjk4MTk0NzM2LCJleHAiOjE2OTgyMDA0MzIsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNjk4MTk2ODMyfQ.GMXkiFGcCy6dXI8gPPuCLd977Gs_rkG1w3FrNx_HlSnmcDUSsEQHvPxpA99Y3L8Z82uLHYCbP5Vga6iCEOmBBHnu9jEsmYgp-TSrB31HV-5g7-o4ZWJG05SdL9KgSP3PyDXRqcE0VFxBJ-uJSyvI-htQ4GUXMIhqVhbJJynPNosXtZvvDVIw1NBThupmqx58cozf5tIdnwaeiuN_Ce2XQrjZBiachI6KWFa-Mstrsdw1E6Ny_4bP-1UmeNgScd6pmIUemGsfclxIAgO0lACqgbGh7wo0PljbhEkGU_i9kP--0KJHkBkUxflULW3aAqdYtG9hEr_JEIddHVxXbi1c_w\" , \"token_type\" : \"Bearer\" , \"expires_in\" : 81210 } Once we have obtained the access_token in jwt(json web token) format, we will do the last step.", "title": "3. Call token endpoint"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#4-call-introspection-endpoint", "text": "Run below command: curl --insecure --cert-type P12 --cert example-cli.p12:<YOUR_PASSWORD> --location 'https://<YOUR_DOMAIN>/jans-auth/restv1/introspection' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --header 'Authorization: Bearer <ACCESS_TOKEN>' \\ --data-urlencode 'token=<ACCESS_TOKEN>' \\ --data-urlencode 'response_as_jwt=false' Response: { \"sub\" : \"MHgjkhgNKfeaxeEDcL2pKysQ0UD8D95AGy4PF_26rig\" , \"iss\" : \"https://<YOUR_DOMAIN>\" , \"active\" : true , \"token_type\" : \"Bearer\" , \"client_id\" : \"d16994c2-313c-4440-9713-25290fbb89a9\" , \"aud\" : \"5d835407-1ef3-441d-8ae6-6bbdd57276cc\" , \"acr\" : \"basic\" , \"nbf\" : null , \"scope\" : \"openid profile email\" , \"auth_time\" : 1698194736 , \"cnf\" : { \"x5t#S256\" : \"OxtIAtA0C0NL-y4vRfKx7zLLEex_XmCzWnQbxz6TznY\" }, \"exp\" : 1698278043 , \"iat\" : 1698201265 , \"jti\" : null , \"username\" : \"admin\" }", "title": "4. Call introspection endpoint"}, {"location": "janssen-server/auth-server/oauth-features/mtls/#specification-document", "text": "For more details of the specification, you can have a look at the following link OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens", "title": "Specification document"}, {"location": "janssen-server/auth-server/oauth-features/par/", "tags": ["administration", "auth-server", "oauth", "feature", "par"], "text": "Pushed Authorization Request (PAR) # Pushed Authorization Request (PAR) allows to push the payload of an OAuth 2.0 authorization request to the authorization server via a direct request and provides back with a request URI that is used as reference to the data in a subsequent call to the authorization endpoint. For more information and implementation details please check PAR Endpoint documentation PAR specification Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "PAR"}, {"location": "janssen-server/auth-server/oauth-features/par/#pushed-authorization-request-par", "text": "Pushed Authorization Request (PAR) allows to push the payload of an OAuth 2.0 authorization request to the authorization server via a direct request and provides back with a request URI that is used as reference to the data in a subsequent call to the authorization endpoint. For more information and implementation details please check PAR Endpoint documentation PAR specification", "title": "Pushed Authorization Request (PAR)"}, {"location": "janssen-server/auth-server/oauth-features/par/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/oauth-features/par/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/oauth-features/password-grant/", "tags": ["administration", "auth-server", "oauth", "feature", "grant", "password"], "text": "Password Grant # Janssen Server supports the password grant. At the same time, inline with OAuth 2.0 security best practices , this password grant should never be used in practice. OAuth 2.1 has removed this grant type. Configuration # A client can use the password grant if it is enabled in the configuration. An administrator can use TUI to enable password grant for a client. Usage # Using the password grant involves sharing user credentials with a third-party application. This third-party app which has registered with Janssen Server as a client, will then use user-id/password credentials from the user to obtain an access token from Janssen Server. Janssen Server also requires the client to authenticate itself based on the client configuration. Since sharing user credentials with a third-party app is a security risk and against the basic purpose of OAuth, this grant type shall not be used. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Password Grant"}, {"location": "janssen-server/auth-server/oauth-features/password-grant/#password-grant", "text": "Janssen Server supports the password grant. At the same time, inline with OAuth 2.0 security best practices , this password grant should never be used in practice. OAuth 2.1 has removed this grant type.", "title": "Password Grant"}, {"location": "janssen-server/auth-server/oauth-features/password-grant/#configuration", "text": "A client can use the password grant if it is enabled in the configuration. An administrator can use TUI to enable password grant for a client.", "title": "Configuration"}, {"location": "janssen-server/auth-server/oauth-features/password-grant/#usage", "text": "Using the password grant involves sharing user credentials with a third-party application. This third-party app which has registered with Janssen Server as a client, will then use user-id/password credentials from the user to obtain an access token from Janssen Server. Janssen Server also requires the client to authenticate itself based on the client configuration. Since sharing user credentials with a third-party app is a security risk and against the basic purpose of OAuth, this grant type shall not be used.", "title": "Usage"}, {"location": "janssen-server/auth-server/oauth-features/password-grant/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/oauth-features/pkce/", "tags": ["administration", "auth-server", "oauth", "feature", "pkce"], "text": "PKCE (Proof Key for Code Exchange) # PKCE(Proof Key for Code Exchange) is an extension to the Authorization on Code flow to prevent CSRF and authorization code injection attacks. Authorization code flow with PKCE is defined in this specification. Public clients ( Single Page Apps (SPA) or Mobile Apps ), have a serious problem obtaining access tokens. In the case of SPA you cannot securely store a secret key, because its source is available in the browser. The same will happen with Mobile Apps , since decompiling the application will reveal the secret keys. This is where PKCE comes in to solve the problem. The authorization code flow with PKCE is considered as best practice when using Single Page Apps (SPA) or Mobile Apps . Let's see in the following diagram how it works: Source PKCE Configuration # For this flow to work, we must make the following configuration in Janssen Server. We need to set the clientAuthenticationFiltersEnabled property to false , it defaults to true . We can use TUI to change this configuration as shown below: Authorization Code Flow + PKCE # In this flow, we will execute the following steps: Generate Code Verifier and Code Challenge Register new client Call authorize endpoint Call token endpoint 1. Generate Code Verifier and Code Challenge # It is necessary to generate these codes for this flow, since this data will be sent in the authorize and token endpoints. Code Verifier # The It is a random string of length N , and is denoted by the field code_verifier . The following command generates a code_verifier of length 128 . tr -dc 'A-Za-z0-9-._' </dev/urandom | head -c 128 ; echo Output example: root@jans:~# tr -dc 'A-Za-z0-9-._' </dev/urandom | head -c 128 ; echo MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr Code Challenge # To generate the code_challenge we need to know what type of method we will be using, so this field is accompanied by the code_challenge_method field. Janssen Server supports two methods of code_challenge_method : plain : When using this method, the code_challenge is the same as the code_verifier . s256 : When using this method, code_challenge must be encoded using the code_verifier with sha256 and * base64Url *. The following command generates the code_challenge using s256 . Note To execute command the command below, you need to have openssl , basenc and tr installed. echo -n \"MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr\" | openssl dgst -binary -sha256 | basenc --base64url | tr -d '=' Output example: root@jans:~# echo -n \"MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr\" | openssl dgst -binary -sha256 | basenc --base64url | tr -d '=' zyI60XbvMetJJuAzyRR_jnxoJkyfxXSqY-mTG4FtBtg 2. Register new client # Request POST <YOUR_DOMAIN>/jans-auth/restv1/register HTTP/1.1 Content-Type: application/json { \"client_name\": \"PKCE Test Client\", \"application_type\": \"web\", \"token_endpoint_auth_method\": \"none\", \"scope\": [ \"openid\", \"profile\", \"email\" ], \"grant_types\": [ \"authorization_code\" ], \"response_types\": [ \"code\", \"token\", \"id_token\" ], \"redirect_uris\": [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ] } Note Notee that the token_endpoint_auth_method field is none . Response HTTP/1.1 201 Created Date: Fri, 17 Nov 2023 22:51:13 GMT Server: Apache/2.4.41 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Expires: Thu, 01 Jan 1970 00:00:00 GMT Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1541 Set-Cookie: X-Correlation-Id=d92eddf5-ab08-4b4f-a8f1-10af67e83dbd; Secure; HttpOnly;HttpOnly Connection: close { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://<YOUR_DOMAIN>/jans-auth/restv1/register?client_id=057c3abf-a1a7-49cc-9e4e-8737e898ac72\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"659ccbf9-ac98-437a-b952-33bfc0366fc2\", \"client_id\": \"f48fbdfa-4c07-49e5-938b-10463980e145\", \"token_endpoint_auth_method\": \"none\", \"scope\": \"email openid profile\", \"client_secret\": \"a656a654-c930-4b52-9edb-68ead50d046e\", \"client_id_issued_at\": 1700261473, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"PKCE Test Client\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"implicit\", \"refresh_token\", \"authorization_code\" ], \"subject_type\": \"pairwise\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1700347873, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"token\", \"id_token\" ] } 3. Call authorize endpoint # From your browser of choice call the following url: Request https://<YOUR_DOMAIN>/jans-auth/restv1/authorize? response_type=code& client_id=f48fbdfa-4c07-49e5-938b-10463980e145& scope=openid+profile+email& redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm& state=bf1af4a1-8713-49c6-b229-537bf4cf712d& nonce=f2265e46-6d93-4d36-850b-8fd990cccd04& code_challenge=<YOUR_CODE_CHALLENGE>& code_challenge_method=<YOUR_CODE_CHALLENGE_METHOD> Note Remember that this endpoint is where you must send the code_challenge and code_challenge_method parameters. The field we need to obtain is the code . 4. Call token endpoint # Previously we have obtained the code field, we will use this value to call the endpoint token . Request POST <YOUR_DOMAIN>/jans-auth/restv1/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded grant_type=authorization_code& redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm& client_id=f48fbdfa-4c07-49e5-938b-10463980e145& code_verifier=<YOUR_CODE_VERIFIER>& code=<YOUR_CODE> Response { \"access_token\" : \"38abc903-9a68-48f9-9ccc-bf1b50fe8152\" , \"refresh_token\" : \"e945e8ab-19c1-4073-b3c1-913bb090459a\" , \"id_token\" : \"eyJraWQiOiJjb25uZWN0XzZmZmJkZTQ3LTU5MDgtNDljMy04MGVkLTFjODNhNGEyNWJmOF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiTndiVXg2NlFaUzFvMG1SMmdyRGxKZyIsInN1YiI6IkcxM2ZtQ3RDQkJ0VDN5TzBMWUY0eng3X1ROUktZeGhGNUd6cGFYOUFiZlkiLCJhbXIiOlsiMTAiXSwiaXNzIjoiaHR0cHM6Ly9taWx0b24tY2gtaGFyZHktbWl0ZS5nbHV1LmluZm8iLCJub25jZSI6IjRlOWVhZjdjLWZlMjUtNDlkMC05OGU1LTM2ZTNjYzJhMWNiZCIsInNpZCI6IjIwZThmNTAzLWZmN2EtNGU3OS05OTY3LTUxMTU5NTk1N2JhYiIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiN2M3OGE0MmUtNTc4YS00OWE2LWExNzAtZTg1N2E0NWYzNTBjIiwicmFuZG9tIjoiZGU0NjE5NDEtNzIzOC00YjZjLWI2NTQtNjg2OTU0MmZlZjc3IiwiYWNyIjoiYmFzaWMiLCJjX2hhc2giOiJ1eFlZWDc5a3c2S2llX0NvaTZERi1RIiwiYXV0aF90aW1lIjoxNzAwMzYxMzA1LCJleHAiOjE3MDAzNjY5MjIsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNzAwMzYzMzIyfQ.IRgf6L4HsTHwgIGY_i3Af1dUnS-fLkMz8ND2r6Fgux-W7lkfQYXrpAqyEn-bUZ-L47PhaNWaLIV2bCl8Bxtbk1RhOS0-Sq8YnATkCgsSTCC5gtcZx42N67oQahoInSA4QuySdz1OAChZhlgUHRWn2bnAm07gCf7jfBdqRwCY11GcJrkR4n714tKcr5olxSDok2MJKmkbTi4VPfQXKfTYb7p-mMoqg3cr7w53IrEvQrOM94tYVJs1sUX_HGLwD99d1kRZN8SW2fMUxDsXw4hcDtnL4ktVp1rzc9tseGeu8tWzbNqQHESodOSPYqsl_SaPhuLip2FNFbStqJDc1vjnlg\" , \"token_type\" : \"Bearer\" , \"expires_in\" : 299 }", "title": "PKCE"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#pkce-proof-key-for-code-exchange", "text": "PKCE(Proof Key for Code Exchange) is an extension to the Authorization on Code flow to prevent CSRF and authorization code injection attacks. Authorization code flow with PKCE is defined in this specification. Public clients ( Single Page Apps (SPA) or Mobile Apps ), have a serious problem obtaining access tokens. In the case of SPA you cannot securely store a secret key, because its source is available in the browser. The same will happen with Mobile Apps , since decompiling the application will reveal the secret keys. This is where PKCE comes in to solve the problem. The authorization code flow with PKCE is considered as best practice when using Single Page Apps (SPA) or Mobile Apps . Let's see in the following diagram how it works: Source", "title": "PKCE (Proof Key for Code Exchange)"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#pkce-configuration", "text": "For this flow to work, we must make the following configuration in Janssen Server. We need to set the clientAuthenticationFiltersEnabled property to false , it defaults to true . We can use TUI to change this configuration as shown below:", "title": "PKCE Configuration"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#authorization-code-flow-pkce", "text": "In this flow, we will execute the following steps: Generate Code Verifier and Code Challenge Register new client Call authorize endpoint Call token endpoint", "title": "Authorization Code Flow + PKCE"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#1-generate-code-verifier-and-code-challenge", "text": "It is necessary to generate these codes for this flow, since this data will be sent in the authorize and token endpoints.", "title": "1. Generate Code Verifier and Code Challenge"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#code-verifier", "text": "The It is a random string of length N , and is denoted by the field code_verifier . The following command generates a code_verifier of length 128 . tr -dc 'A-Za-z0-9-._' </dev/urandom | head -c 128 ; echo Output example: root@jans:~# tr -dc 'A-Za-z0-9-._' </dev/urandom | head -c 128 ; echo MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr", "title": "Code Verifier"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#code-challenge", "text": "To generate the code_challenge we need to know what type of method we will be using, so this field is accompanied by the code_challenge_method field. Janssen Server supports two methods of code_challenge_method : plain : When using this method, the code_challenge is the same as the code_verifier . s256 : When using this method, code_challenge must be encoded using the code_verifier with sha256 and * base64Url *. The following command generates the code_challenge using s256 . Note To execute command the command below, you need to have openssl , basenc and tr installed. echo -n \"MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr\" | openssl dgst -binary -sha256 | basenc --base64url | tr -d '=' Output example: root@jans:~# echo -n \"MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzkear088FJLzq.6tAg10wikJrIqn75HCJ7V1b_p8io_ugkPkkr\" | openssl dgst -binary -sha256 | basenc --base64url | tr -d '=' zyI60XbvMetJJuAzyRR_jnxoJkyfxXSqY-mTG4FtBtg", "title": "Code Challenge"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#2-register-new-client", "text": "Request POST <YOUR_DOMAIN>/jans-auth/restv1/register HTTP/1.1 Content-Type: application/json { \"client_name\": \"PKCE Test Client\", \"application_type\": \"web\", \"token_endpoint_auth_method\": \"none\", \"scope\": [ \"openid\", \"profile\", \"email\" ], \"grant_types\": [ \"authorization_code\" ], \"response_types\": [ \"code\", \"token\", \"id_token\" ], \"redirect_uris\": [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ] } Note Notee that the token_endpoint_auth_method field is none . Response HTTP/1.1 201 Created Date: Fri, 17 Nov 2023 22:51:13 GMT Server: Apache/2.4.41 (Ubuntu) X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains Expires: Thu, 01 Jan 1970 00:00:00 GMT Cache-Control: no-store Content-Type: application/json Pragma: no-cache Content-Length: 1541 Set-Cookie: X-Correlation-Id=d92eddf5-ab08-4b4f-a8f1-10af67e83dbd; Secure; HttpOnly;HttpOnly Connection: close { \"allow_spontaneous_scopes\": false, \"application_type\": \"web\", \"rpt_as_jwt\": false, \"registration_client_uri\": \"https://<YOUR_DOMAIN>/jans-auth/restv1/register?client_id=057c3abf-a1a7-49cc-9e4e-8737e898ac72\", \"tls_client_auth_subject_dn\": \"\", \"run_introspection_script_before_jwt_creation\": false, \"registration_access_token\": \"659ccbf9-ac98-437a-b952-33bfc0366fc2\", \"client_id\": \"f48fbdfa-4c07-49e5-938b-10463980e145\", \"token_endpoint_auth_method\": \"none\", \"scope\": \"email openid profile\", \"client_secret\": \"a656a654-c930-4b52-9edb-68ead50d046e\", \"client_id_issued_at\": 1700261473, \"backchannel_logout_uri\": \"\", \"backchannel_logout_session_required\": false, \"client_name\": \"PKCE Test Client\", \"par_lifetime\": 600, \"spontaneous_scopes\": [], \"id_token_signed_response_alg\": \"RS256\", \"access_token_as_jwt\": false, \"grant_types\": [ \"implicit\", \"refresh_token\", \"authorization_code\" ], \"subject_type\": \"pairwise\", \"additional_token_endpoint_auth_methods\": [], \"keep_client_authorization_after_expiration\": false, \"require_par\": false, \"redirect_uris\": [ \"https://<YOUR_DOMAIN>/jans-auth-rp/home.htm\" ], \"redirect_uris_regex\": \"\", \"additional_audience\": [], \"frontchannel_logout_session_required\": false, \"client_secret_expires_at\": 1700347873, \"access_token_signing_alg\": \"RS256\", \"response_types\": [ \"code\", \"token\", \"id_token\" ] }", "title": "2. Register new client"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#3-call-authorize-endpoint", "text": "From your browser of choice call the following url: Request https://<YOUR_DOMAIN>/jans-auth/restv1/authorize? response_type=code& client_id=f48fbdfa-4c07-49e5-938b-10463980e145& scope=openid+profile+email& redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm& state=bf1af4a1-8713-49c6-b229-537bf4cf712d& nonce=f2265e46-6d93-4d36-850b-8fd990cccd04& code_challenge=<YOUR_CODE_CHALLENGE>& code_challenge_method=<YOUR_CODE_CHALLENGE_METHOD> Note Remember that this endpoint is where you must send the code_challenge and code_challenge_method parameters. The field we need to obtain is the code .", "title": "3. Call authorize endpoint"}, {"location": "janssen-server/auth-server/oauth-features/pkce/#4-call-token-endpoint", "text": "Previously we have obtained the code field, we will use this value to call the endpoint token . Request POST <YOUR_DOMAIN>/jans-auth/restv1/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded grant_type=authorization_code& redirect_uri=https://<YOUR_DOMAIN>/jans-auth-rp/home.htm& client_id=f48fbdfa-4c07-49e5-938b-10463980e145& code_verifier=<YOUR_CODE_VERIFIER>& code=<YOUR_CODE> Response { \"access_token\" : \"38abc903-9a68-48f9-9ccc-bf1b50fe8152\" , \"refresh_token\" : \"e945e8ab-19c1-4073-b3c1-913bb090459a\" , \"id_token\" : \"eyJraWQiOiJjb25uZWN0XzZmZmJkZTQ3LTU5MDgtNDljMy04MGVkLTFjODNhNGEyNWJmOF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiTndiVXg2NlFaUzFvMG1SMmdyRGxKZyIsInN1YiI6IkcxM2ZtQ3RDQkJ0VDN5TzBMWUY0eng3X1ROUktZeGhGNUd6cGFYOUFiZlkiLCJhbXIiOlsiMTAiXSwiaXNzIjoiaHR0cHM6Ly9taWx0b24tY2gtaGFyZHktbWl0ZS5nbHV1LmluZm8iLCJub25jZSI6IjRlOWVhZjdjLWZlMjUtNDlkMC05OGU1LTM2ZTNjYzJhMWNiZCIsInNpZCI6IjIwZThmNTAzLWZmN2EtNGU3OS05OTY3LTUxMTU5NTk1N2JhYiIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiN2M3OGE0MmUtNTc4YS00OWE2LWExNzAtZTg1N2E0NWYzNTBjIiwicmFuZG9tIjoiZGU0NjE5NDEtNzIzOC00YjZjLWI2NTQtNjg2OTU0MmZlZjc3IiwiYWNyIjoiYmFzaWMiLCJjX2hhc2giOiJ1eFlZWDc5a3c2S2llX0NvaTZERi1RIiwiYXV0aF90aW1lIjoxNzAwMzYxMzA1LCJleHAiOjE3MDAzNjY5MjIsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNzAwMzYzMzIyfQ.IRgf6L4HsTHwgIGY_i3Af1dUnS-fLkMz8ND2r6Fgux-W7lkfQYXrpAqyEn-bUZ-L47PhaNWaLIV2bCl8Bxtbk1RhOS0-Sq8YnATkCgsSTCC5gtcZx42N67oQahoInSA4QuySdz1OAChZhlgUHRWn2bnAm07gCf7jfBdqRwCY11GcJrkR4n714tKcr5olxSDok2MJKmkbTi4VPfQXKfTYb7p-mMoqg3cr7w53IrEvQrOM94tYVJs1sUX_HGLwD99d1kRZN8SW2fMUxDsXw4hcDtnL4ktVp1rzc9tseGeu8tWzbNqQHESodOSPYqsl_SaPhuLip2FNFbStqJDc1vjnlg\" , \"token_type\" : \"Bearer\" , \"expires_in\" : 299 }", "title": "4. Call token endpoint"}, {"location": "janssen-server/auth-server/openid-features/acrs/", "tags": ["administration", "auth-server", "openidc", "feature", "acr"], "text": "ACR # ACR(Authentication Context Class Reference) is defined by OpenId Connect Specification . Using ACRs and ACR configuration, the client application can define end-user authentication experience while ensuring required level of security for the application. Supported ACRs # Janssen Server lists supported ACRs in the response from Janssen Server's well-known configuration endpoint given below. Only ACRs that are supported and enabled by configuration will be part of the list. https://janssen.server.host/jans-auth/.well-known/openid-configuration The acr_values_supported claim in the response shows the list of supported and enabled ACRs for particular Janssen Server deployment. ACR categories: # ACRs available in Janssen Server can be broadly put into three categories. These categories are just for ease of understanding. 1. Internal Janssen Server ACR # Janssen server will use internal ACR only if no other authentication method is set or could be invoked. This internal ACR, simple_password_auth , is set to level -1. This means that it has lower priority than any other script. This ACR is always available and enabled on any Janssen Server deployment. This ACR is a simple user-id and password-based authentication mechanism. It authenticates the end-user against the backend datastore. 2. Pre-packaged ACR for authenticating using external LDAP or Active Directory # All Janssen Server deployments have default_ldap_server ACR which can be enabled to perform authentication against a remote LDAP-based IDP (e.g. ActiveDirectory). By default, this ACR is disabled. This ACR can only authenticate against LDAP-based IDP. Use the instructions provided in jans-cli LDAP configuration options documentation to learn how to enable and configure ACRs that use external LDAP as IDP. 3. Script-based ACRs # To offer highly flexible and pluggable authentication flows, Janssen Server uses script-based ACRs. These ACRs are associated with a corresponding person authentication script . To use these ACRs in the authentication flow, the associated script should be enabled . 4. Agama ACRs # Agama acrs starts from agama_ prefix. All of them invoke underlying agama bridge script called agama . General pattern is agama_<flow name> . Configuring ACRs in the JANS AS: # ACRs can be configured on two levels: 1. Client Level ACR # The client can configure a specific ACR that should be used if the authentication request is missing acr_values parameter. This can be configured using Default ACR attribute of the client configuration. Also, the client can restrict ACR values that authentication requests can have as part of acr_values parameter. This can be configured using Allowed ACRs . Using the Janssen Text base UI (TUI) configuration tool, these values can be configured by navigating to Auth Server -> clients -> get clients -> choose a client and press enter -> Advanced Client Prop . On this screen populate ACR values in Default ACR and Allowed ACRs : 2. Server Level ACR # Janssen Server administrator can configure an ACR that should be invoked if ACR for incoming requests can not be determined using client-level configuration. This is the default authentication mechanism exposed to all the clients that send end-users to the Janssen Server for sign-in. To configure this parameter using Janssen Text base UI (TUI) configuration tool, navigate to Auth Server -> Authn -> Default ACR as shown below: ACR Precedence Levels # Each authentication mechanism (script) has a \"Level\" assigned to it which describes how secure and reliable it is. The higher the \"Level\" represents higher reliability. Though several mechanisms(ACRs) can be enabled for the same Janssen server deployment at the same time, for any specific user's session only one of them can be set as the current ACR (and will be returned as acr claim of id_token). After the creation of the initial session, if RP sends a new request with a different ACR, then ACR's \"Level\" will be compared to that of the method associated with the current session. If the requested method's \"Level\" is lower or equal to current ACR's level, nothing is changed and the usual SSO behavior is observed. If the new level is higher (i.e. a more secure method is requested), and it's not possible to serve such a request using the existing session's context, then the user must re-authenticate to continue. If the user succeeds, a new session with a new ACR gets associated. ACR mappings (aliases) # There is acrMappings AS configuration property which allows to specify aliases for acrs. acrMappings contains simple map in key-value form. Lets say RP sends request with acr_values=loginWithOtpCheck . If acrMappings contains mapping \"loginWithOtpCheck\":\"otp\" then AS will map loginWithOtpCheck to otp and will use acr_values=otp for actual processing on server side. It means that custom script must be called otp in this case on AS side and not loginWithOtpCheck (because loginWithOtpCheck is alias to otp ). ACR mappings are published on discovery page GET /.well-known/openid-configuration HTTP/1.1 { ... \"acr_mappings\" :{ \"alias1\" : \"acr1\" , \"loginWithOtpCheck\" : \"otp\" } ... } Flowchart : How the Jans AS derives an ACR value for a user session # flowchart TD A[RP send authentication request] --> B{Request contains <br /><code>acr_values</code> parameter?} B -->|Yes| C[Perform Authentication] B -->|No| D{<code>Default ACR</code> <br />configured for <br />client?} D -->|Yes| C D -->|No| E{<code>Default ACR</code> value <br />configured for <br />Janssen Server?} E --> |Yes| C E --> |No| F[Select <br />internal ACR as<br /> Authentication method] --> C When authentication request is received from a client(RP), the Janssen Server looks for acr_values parameter in the request. This parameter is defined in the OpenId Connect core specification, section 3.1.2.1 . If the acr_values parameter is not received with the request, then Janssen Server uses the value from the Default ACR configuration from the client If Janssen Server doesn't find acr_values request parameter nor does it find the Default ACR configured for the client, then the Janssen Server checks the server configuration property useHighestLevelScriptIfAcrScriptNotFound . If this property is set to true, then Janssen Server invokes the authentication mechanism for which the corresponding person authentication script is enabled. Choosing the script with the highest level . If no script can be invoked or the useHighestLevelScriptIfAcrScriptNotFound property is set to false, then the Janssen Server authenticates using the default ACR for the server . If the default ACR for the server is not configured by the Janssen Server administrator, or it can not be invoked due to any reason, then the Janssen Server uses the internal server ACR to authenticate the end-user. Errors # unmet_authentication_requirements # If authorization request is sent to Authorization Endpoint with acr_values for which AS it not able to find \"Person Authentication\" custom script, it returns \"unmet_authentication_requirements\" with detail log in jans-auth.log . Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "ACRs"}, {"location": "janssen-server/auth-server/openid-features/acrs/#acr", "text": "ACR(Authentication Context Class Reference) is defined by OpenId Connect Specification . Using ACRs and ACR configuration, the client application can define end-user authentication experience while ensuring required level of security for the application.", "title": "ACR"}, {"location": "janssen-server/auth-server/openid-features/acrs/#supported-acrs", "text": "Janssen Server lists supported ACRs in the response from Janssen Server's well-known configuration endpoint given below. Only ACRs that are supported and enabled by configuration will be part of the list. https://janssen.server.host/jans-auth/.well-known/openid-configuration The acr_values_supported claim in the response shows the list of supported and enabled ACRs for particular Janssen Server deployment.", "title": "Supported ACRs"}, {"location": "janssen-server/auth-server/openid-features/acrs/#acr-categories", "text": "ACRs available in Janssen Server can be broadly put into three categories. These categories are just for ease of understanding.", "title": "ACR categories:"}, {"location": "janssen-server/auth-server/openid-features/acrs/#1-internal-janssen-server-acr", "text": "Janssen server will use internal ACR only if no other authentication method is set or could be invoked. This internal ACR, simple_password_auth , is set to level -1. This means that it has lower priority than any other script. This ACR is always available and enabled on any Janssen Server deployment. This ACR is a simple user-id and password-based authentication mechanism. It authenticates the end-user against the backend datastore.", "title": "1. Internal Janssen Server ACR"}, {"location": "janssen-server/auth-server/openid-features/acrs/#2-pre-packaged-acr-for-authenticating-using-external-ldap-or-active-directory", "text": "All Janssen Server deployments have default_ldap_server ACR which can be enabled to perform authentication against a remote LDAP-based IDP (e.g. ActiveDirectory). By default, this ACR is disabled. This ACR can only authenticate against LDAP-based IDP. Use the instructions provided in jans-cli LDAP configuration options documentation to learn how to enable and configure ACRs that use external LDAP as IDP.", "title": "2. Pre-packaged ACR for authenticating using external LDAP or Active Directory"}, {"location": "janssen-server/auth-server/openid-features/acrs/#3-script-based-acrs", "text": "To offer highly flexible and pluggable authentication flows, Janssen Server uses script-based ACRs. These ACRs are associated with a corresponding person authentication script . To use these ACRs in the authentication flow, the associated script should be enabled .", "title": "3. Script-based ACRs"}, {"location": "janssen-server/auth-server/openid-features/acrs/#4-agama-acrs", "text": "Agama acrs starts from agama_ prefix. All of them invoke underlying agama bridge script called agama . General pattern is agama_<flow name> .", "title": "4. Agama ACRs"}, {"location": "janssen-server/auth-server/openid-features/acrs/#configuring-acrs-in-the-jans-as", "text": "ACRs can be configured on two levels:", "title": "Configuring ACRs in the JANS AS:"}, {"location": "janssen-server/auth-server/openid-features/acrs/#1-client-level-acr", "text": "The client can configure a specific ACR that should be used if the authentication request is missing acr_values parameter. This can be configured using Default ACR attribute of the client configuration. Also, the client can restrict ACR values that authentication requests can have as part of acr_values parameter. This can be configured using Allowed ACRs . Using the Janssen Text base UI (TUI) configuration tool, these values can be configured by navigating to Auth Server -> clients -> get clients -> choose a client and press enter -> Advanced Client Prop . On this screen populate ACR values in Default ACR and Allowed ACRs :", "title": "1. Client Level ACR"}, {"location": "janssen-server/auth-server/openid-features/acrs/#2-server-level-acr", "text": "Janssen Server administrator can configure an ACR that should be invoked if ACR for incoming requests can not be determined using client-level configuration. This is the default authentication mechanism exposed to all the clients that send end-users to the Janssen Server for sign-in. To configure this parameter using Janssen Text base UI (TUI) configuration tool, navigate to Auth Server -> Authn -> Default ACR as shown below:", "title": "2. Server Level ACR"}, {"location": "janssen-server/auth-server/openid-features/acrs/#acr-precedence-levels", "text": "Each authentication mechanism (script) has a \"Level\" assigned to it which describes how secure and reliable it is. The higher the \"Level\" represents higher reliability. Though several mechanisms(ACRs) can be enabled for the same Janssen server deployment at the same time, for any specific user's session only one of them can be set as the current ACR (and will be returned as acr claim of id_token). After the creation of the initial session, if RP sends a new request with a different ACR, then ACR's \"Level\" will be compared to that of the method associated with the current session. If the requested method's \"Level\" is lower or equal to current ACR's level, nothing is changed and the usual SSO behavior is observed. If the new level is higher (i.e. a more secure method is requested), and it's not possible to serve such a request using the existing session's context, then the user must re-authenticate to continue. If the user succeeds, a new session with a new ACR gets associated.", "title": "ACR Precedence Levels"}, {"location": "janssen-server/auth-server/openid-features/acrs/#acr-mappings-aliases", "text": "There is acrMappings AS configuration property which allows to specify aliases for acrs. acrMappings contains simple map in key-value form. Lets say RP sends request with acr_values=loginWithOtpCheck . If acrMappings contains mapping \"loginWithOtpCheck\":\"otp\" then AS will map loginWithOtpCheck to otp and will use acr_values=otp for actual processing on server side. It means that custom script must be called otp in this case on AS side and not loginWithOtpCheck (because loginWithOtpCheck is alias to otp ). ACR mappings are published on discovery page GET /.well-known/openid-configuration HTTP/1.1 { ... \"acr_mappings\" :{ \"alias1\" : \"acr1\" , \"loginWithOtpCheck\" : \"otp\" } ... }", "title": "ACR mappings (aliases)"}, {"location": "janssen-server/auth-server/openid-features/acrs/#flowchart-how-the-jans-as-derives-an-acr-value-for-a-user-session", "text": "flowchart TD A[RP send authentication request] --> B{Request contains <br /><code>acr_values</code> parameter?} B -->|Yes| C[Perform Authentication] B -->|No| D{<code>Default ACR</code> <br />configured for <br />client?} D -->|Yes| C D -->|No| E{<code>Default ACR</code> value <br />configured for <br />Janssen Server?} E --> |Yes| C E --> |No| F[Select <br />internal ACR as<br /> Authentication method] --> C When authentication request is received from a client(RP), the Janssen Server looks for acr_values parameter in the request. This parameter is defined in the OpenId Connect core specification, section 3.1.2.1 . If the acr_values parameter is not received with the request, then Janssen Server uses the value from the Default ACR configuration from the client If Janssen Server doesn't find acr_values request parameter nor does it find the Default ACR configured for the client, then the Janssen Server checks the server configuration property useHighestLevelScriptIfAcrScriptNotFound . If this property is set to true, then Janssen Server invokes the authentication mechanism for which the corresponding person authentication script is enabled. Choosing the script with the highest level . If no script can be invoked or the useHighestLevelScriptIfAcrScriptNotFound property is set to false, then the Janssen Server authenticates using the default ACR for the server . If the default ACR for the server is not configured by the Janssen Server administrator, or it can not be invoked due to any reason, then the Janssen Server uses the internal server ACR to authenticate the end-user.", "title": "Flowchart : How the Jans AS derives an ACR value for a user session"}, {"location": "janssen-server/auth-server/openid-features/acrs/#errors", "text": "", "title": "Errors"}, {"location": "janssen-server/auth-server/openid-features/acrs/#unmet_authentication_requirements", "text": "If authorization request is sent to Authorization Endpoint with acr_values for which AS it not able to find \"Person Authentication\" custom script, it returns \"unmet_authentication_requirements\" with detail log in jans-auth.log .", "title": "unmet_authentication_requirements"}, {"location": "janssen-server/auth-server/openid-features/acrs/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/ciba/", "tags": ["administration", "auth-server", "openidc", "feature"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "CIBA"}, {"location": "janssen-server/auth-server/openid-features/ciba/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/ciba/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/ciba/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/id-token/", "tags": ["administration", "auth-server", "openidc", "feature", "ID Token"], "text": "ID Token # Janssen Server is an OpenID Connect Provider(OP). OpenID Connect extends OAuth 2.0 and adds user authentication capabilities using ID token. To add end-user authentication capabilities to an OAuth flow, it is important to use openid scope in the request as specified here . In absence of openid scope, the Janssen Server will not treat the incoming request as OpenID Connect request. For further information on how to configure and customize OpenID Connect using ID Token read here Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "id_token"}, {"location": "janssen-server/auth-server/openid-features/id-token/#id-token", "text": "Janssen Server is an OpenID Connect Provider(OP). OpenID Connect extends OAuth 2.0 and adds user authentication capabilities using ID token. To add end-user authentication capabilities to an OAuth flow, it is important to use openid scope in the request as specified here . In absence of openid scope, the Janssen Server will not treat the incoming request as OpenID Connect request. For further information on how to configure and customize OpenID Connect using ID Token read here", "title": "ID Token"}, {"location": "janssen-server/auth-server/openid-features/id-token/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/jarm/", "tags": ["administration", "auth-server", "openidc", "feature"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "JARM"}, {"location": "janssen-server/auth-server/openid-features/jarm/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/jarm/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/jarm/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/native-sso/", "tags": ["administration", "auth-server", "openidc", "feature", "native sso", "mobile", "single sign-on"], "text": "Native Single Sign-On # An increasing number of mobile phone users are using multiple mobile applications from the same software vendor. For instance, it is fairly common to see people using multiple mobile apps from software vendors like Google and Microsoft, etc. Software vendors need a way to allow users to sign-in to one of the apps provided by the software vendor and users should be able to use all other apps from the same vendor without having to sign-in again. In short, single sign-on for applications belonging to the same vendor. Janssen Server supports OpenID Connect native SSO mechanism to enable SSO for mobile applications. Scope Support # Janssen Server supports the device_sso scope as defined by the specification. Software vendor wanting to leverage native SSO feature should build the apps so during initial user authentication, the app would send device_sso scope in the authorization request. The presence of the device_sso scope in the authorization request would enable AS to return device_secret in the token response from the token endpoint. Device Secret # device_secret is an opaque value returned to the application from the token endpoint as a response to a token exchange request. Janssen Server will return device_secret only if the code provided by the application in token exchange request has device_sso scope. Janssen Server also checks if the client has the token exchange grant type enabled. To enable the grant type, use Janssen Text-based UI(TUI) and enable token exchange grant ( urn:ietf:params:oauth:grant-type:token-exchange ). The device_token claim in the returned token response contains the device secret. Janssen Server stores the device secretes issued to a client in the corresponding session-id. Processing Token Exchange Request # Janssen Server carries out the processing of token requests as per rules and checks defined in the specification . Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Native SSO"}, {"location": "janssen-server/auth-server/openid-features/native-sso/#native-single-sign-on", "text": "An increasing number of mobile phone users are using multiple mobile applications from the same software vendor. For instance, it is fairly common to see people using multiple mobile apps from software vendors like Google and Microsoft, etc. Software vendors need a way to allow users to sign-in to one of the apps provided by the software vendor and users should be able to use all other apps from the same vendor without having to sign-in again. In short, single sign-on for applications belonging to the same vendor. Janssen Server supports OpenID Connect native SSO mechanism to enable SSO for mobile applications.", "title": "Native Single Sign-On"}, {"location": "janssen-server/auth-server/openid-features/native-sso/#scope-support", "text": "Janssen Server supports the device_sso scope as defined by the specification. Software vendor wanting to leverage native SSO feature should build the apps so during initial user authentication, the app would send device_sso scope in the authorization request. The presence of the device_sso scope in the authorization request would enable AS to return device_secret in the token response from the token endpoint.", "title": "Scope Support"}, {"location": "janssen-server/auth-server/openid-features/native-sso/#device-secret", "text": "device_secret is an opaque value returned to the application from the token endpoint as a response to a token exchange request. Janssen Server will return device_secret only if the code provided by the application in token exchange request has device_sso scope. Janssen Server also checks if the client has the token exchange grant type enabled. To enable the grant type, use Janssen Text-based UI(TUI) and enable token exchange grant ( urn:ietf:params:oauth:grant-type:token-exchange ). The device_token claim in the returned token response contains the device secret. Janssen Server stores the device secretes issued to a client in the corresponding session-id.", "title": "Device Secret"}, {"location": "janssen-server/auth-server/openid-features/native-sso/#processing-token-exchange-request", "text": "Janssen Server carries out the processing of token requests as per rules and checks defined in the specification .", "title": "Processing Token Exchange Request"}, {"location": "janssen-server/auth-server/openid-features/native-sso/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/prompt-parameter/", "tags": ["administration", "auth-server", "openidc", "feature", "prompt"], "text": "Prompt CREATE # prompt=create value indicates to the AS that the client desires that the user be shown the account creation page rather than the login flow. It is enabled by default. However prompt=create can be entirely disabled if set AS configuration property disablePromptCreate to true . By default for prompt=create createUser page is shown which allows to enter basic information: - display name - email - login - password On \"Create User\" button click user is created and redirected Authorization Endpoint of AS. If more or custom fields has to be shown then custom page should be added and \"CreateUser\" custom script should redirect to that custom page. public String getCreateUserPage ( Object context ) { return \"/customCreateUser\" ; } \"CreateUser\" custom script Prompt NONE # The OpenID Connect protocol supports a prompt=none parameter on the authentication request that allows applications to indicate that the authorization server must not display any user interaction (such as authentication, consent, or MFA). Janssen will either return the requested response back to the application, or return an error if the user is not already authenticated or if some type of consent or prompt is required before proceeding. Initiate Silent Authentication requests To initiate a silent authentication request, add the prompt=none parameter when you redirect a user to the /authorize endpoint of Janssen authentication API. (The individual parameters on the authentication request will vary depending on the specific needs of your app.) For example: GET https://YOUR_DOMAIN//authorize? response_type={response_type}& client_id={client_id}& scope={scope}& state={state}& ui_locales=& claims_locales=& acr_values=& redirect_uri={redirect_uri}& prompt=none Basic credential user The prompt=none parameter causes Jannsen to immediately send a result to the specified redirect_uri (callback URL) using the specified response_mode with one of two possible responses: success or error. Note: Any applicable rules will be executed as part of the silent authentication process. Successful authentication responses If the user was already logged in to Janssen and no other interactive prompts are required, Janssen will respond exactly as if the user had authenticated manually through the login page. This response is indistinguishable from a login performed directly without the prompt=none parameter. Example 1: Prompt None (Without credentials in Header) title Prompt None (Without credentials in Header) participant Browser participant IDP participant Identity participant SessionIdService participant AuthorizeRestWebServiceValidator participant AuthenticationFilterService Browser->IDP: /authorize?\\nresponse_type=... &\\nclient_id=... &\\nscope=... &\\nstate=... &\\nui_locales=... &\\nclaims_locales=... &\\nacr_values=... &\\nredirect_uri=... &\\n**prompt=none** IDP->Identity: getSessionId() Identity->IDP: return: null IDP->SessionIdService: getUser(): from sessionId SessionIdService->IDP: return: null group Client validation IDP->AuthorizeRestWebServiceValidator: validateClient(): if it's par, disabled or not found? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException end group User is null IDP->IDP: ifUserIsNull() IDP->AuthenticationFilterService: processAuthenticationFilters() AuthenticationFilterService->Browser: WebApplicationException (LOGIN_REQUIRED) end Example 2: Prompt None (Without credentials in Header) title Prompt None (With credentials in Header) participant Browser participant Janssen participant Identity participant SessionIdService participant AuthorizeRestWebServiceValidator participant ScopeChecker participant ExternalPostAuthnService participant ResponseParameters participant ExternalUpdateTokenService participant ClientService Browser->Janssen: /authorize?\\nresponse_type=... &\\nclient_id=... &\\nscope=... &\\nstate=... &\\nui_locales=... &\\nclaims_locales=... &\\nacr_values=... &\\nredirect_uri=... &\\n**prompt=none**\\n\\n**Basic credentials (user)** in Headers Janssen->Identity: getSessionId() Identity->Janssen: return: sessionId Janssen->SessionIdService: getUser(): from sessionId SessionIdService->Janssen: return: User group Update Session For ROPC: If exists session attribute grant_type ROPC Janssen->Janssen: updateSessionForROPC() Janssen->SessionIdService: updateSessionId() SessionIdService->Janssen: session attributes updated end group Client validation Janssen->AuthorizeRestWebServiceValidator: validateClient(): if it's par, disabled or not found? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException (INVALID_REQUEST, UNAUTHORIZED_CLIENT, DISABLED_CLIENT) end group ACR validation Janssen->AuthorizeRestWebServiceValidator: validateAcrs(): If the request acr list does not exist in the session attribute? or\\n Acr Changed? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException (INVALID_REQUEST) end group Max Age Validation Janssen->Janssen: validateMaxAge() Janssen->AuthorizeRestWebServiceValidator: isAuthnMaxAgeValid() AuthorizeRestWebServiceValidator->Janssen: throw new WebApplicationException(): redirectToAuthorizationPage(): if it's not valid end Janssen->ScopeChecker: checkScopesPolicy() ScopeChecker->Janssen: return: scopes group Post Authn Custom Script Janssen->ExternalPostAuthnService: checkForceReAuthentication() Janssen->ExternalPostAuthnService: checkForceAuthorization() end group if ResponseType CODE Janssen->ResponseParameters: put code end group if ResponseType TOKEN Janssen->ResponseParameters: put access_token, token_type and expires_in Janssen->ExternalUpdateTokenService: modifyAccessToken() ExternalUpdateTokenService->Janssen: return true or false end group if ResponseType ID_TOKEN Janssen->ResponseParameters: put id_token Janssen->ExternalUpdateTokenService: modifyIdToken() ExternalUpdateTokenService->Janssen: return true or false end Janssen->SessionIdService: generateAuthenticatedSessionId(): if exists sessionId SessionIdService->Janssen: return: newSessionUser Janssen->ResponseParameters: addRespnseParameterSessionId(): if enabled appConfiguration.getSessionIdRequestParameterEnabled() Janssen->ResponseParameters: addResponseParameterSid(): if enabled appConfiguration.getIncludeSidInResponse() Janssen->ResponseParameters: put session_state and state Janssen->ClientService: updateAccessTime() Janssen->Browser: /redirect_uri?with_param=...", "title": "Prompt Parameter"}, {"location": "janssen-server/auth-server/openid-features/prompt-parameter/#prompt-create", "text": "prompt=create value indicates to the AS that the client desires that the user be shown the account creation page rather than the login flow. It is enabled by default. However prompt=create can be entirely disabled if set AS configuration property disablePromptCreate to true . By default for prompt=create createUser page is shown which allows to enter basic information: - display name - email - login - password On \"Create User\" button click user is created and redirected Authorization Endpoint of AS. If more or custom fields has to be shown then custom page should be added and \"CreateUser\" custom script should redirect to that custom page. public String getCreateUserPage ( Object context ) { return \"/customCreateUser\" ; } \"CreateUser\" custom script", "title": "Prompt CREATE"}, {"location": "janssen-server/auth-server/openid-features/prompt-parameter/#prompt-none", "text": "The OpenID Connect protocol supports a prompt=none parameter on the authentication request that allows applications to indicate that the authorization server must not display any user interaction (such as authentication, consent, or MFA). Janssen will either return the requested response back to the application, or return an error if the user is not already authenticated or if some type of consent or prompt is required before proceeding. Initiate Silent Authentication requests To initiate a silent authentication request, add the prompt=none parameter when you redirect a user to the /authorize endpoint of Janssen authentication API. (The individual parameters on the authentication request will vary depending on the specific needs of your app.) For example: GET https://YOUR_DOMAIN//authorize? response_type={response_type}& client_id={client_id}& scope={scope}& state={state}& ui_locales=& claims_locales=& acr_values=& redirect_uri={redirect_uri}& prompt=none Basic credential user The prompt=none parameter causes Jannsen to immediately send a result to the specified redirect_uri (callback URL) using the specified response_mode with one of two possible responses: success or error. Note: Any applicable rules will be executed as part of the silent authentication process. Successful authentication responses If the user was already logged in to Janssen and no other interactive prompts are required, Janssen will respond exactly as if the user had authenticated manually through the login page. This response is indistinguishable from a login performed directly without the prompt=none parameter. Example 1: Prompt None (Without credentials in Header) title Prompt None (Without credentials in Header) participant Browser participant IDP participant Identity participant SessionIdService participant AuthorizeRestWebServiceValidator participant AuthenticationFilterService Browser->IDP: /authorize?\\nresponse_type=... &\\nclient_id=... &\\nscope=... &\\nstate=... &\\nui_locales=... &\\nclaims_locales=... &\\nacr_values=... &\\nredirect_uri=... &\\n**prompt=none** IDP->Identity: getSessionId() Identity->IDP: return: null IDP->SessionIdService: getUser(): from sessionId SessionIdService->IDP: return: null group Client validation IDP->AuthorizeRestWebServiceValidator: validateClient(): if it's par, disabled or not found? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException end group User is null IDP->IDP: ifUserIsNull() IDP->AuthenticationFilterService: processAuthenticationFilters() AuthenticationFilterService->Browser: WebApplicationException (LOGIN_REQUIRED) end Example 2: Prompt None (Without credentials in Header) title Prompt None (With credentials in Header) participant Browser participant Janssen participant Identity participant SessionIdService participant AuthorizeRestWebServiceValidator participant ScopeChecker participant ExternalPostAuthnService participant ResponseParameters participant ExternalUpdateTokenService participant ClientService Browser->Janssen: /authorize?\\nresponse_type=... &\\nclient_id=... &\\nscope=... &\\nstate=... &\\nui_locales=... &\\nclaims_locales=... &\\nacr_values=... &\\nredirect_uri=... &\\n**prompt=none**\\n\\n**Basic credentials (user)** in Headers Janssen->Identity: getSessionId() Identity->Janssen: return: sessionId Janssen->SessionIdService: getUser(): from sessionId SessionIdService->Janssen: return: User group Update Session For ROPC: If exists session attribute grant_type ROPC Janssen->Janssen: updateSessionForROPC() Janssen->SessionIdService: updateSessionId() SessionIdService->Janssen: session attributes updated end group Client validation Janssen->AuthorizeRestWebServiceValidator: validateClient(): if it's par, disabled or not found? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException (INVALID_REQUEST, UNAUTHORIZED_CLIENT, DISABLED_CLIENT) end group ACR validation Janssen->AuthorizeRestWebServiceValidator: validateAcrs(): If the request acr list does not exist in the session attribute? or\\n Acr Changed? AuthorizeRestWebServiceValidator->Browser: throw WebApplicationException (INVALID_REQUEST) end group Max Age Validation Janssen->Janssen: validateMaxAge() Janssen->AuthorizeRestWebServiceValidator: isAuthnMaxAgeValid() AuthorizeRestWebServiceValidator->Janssen: throw new WebApplicationException(): redirectToAuthorizationPage(): if it's not valid end Janssen->ScopeChecker: checkScopesPolicy() ScopeChecker->Janssen: return: scopes group Post Authn Custom Script Janssen->ExternalPostAuthnService: checkForceReAuthentication() Janssen->ExternalPostAuthnService: checkForceAuthorization() end group if ResponseType CODE Janssen->ResponseParameters: put code end group if ResponseType TOKEN Janssen->ResponseParameters: put access_token, token_type and expires_in Janssen->ExternalUpdateTokenService: modifyAccessToken() ExternalUpdateTokenService->Janssen: return true or false end group if ResponseType ID_TOKEN Janssen->ResponseParameters: put id_token Janssen->ExternalUpdateTokenService: modifyIdToken() ExternalUpdateTokenService->Janssen: return true or false end Janssen->SessionIdService: generateAuthenticatedSessionId(): if exists sessionId SessionIdService->Janssen: return: newSessionUser Janssen->ResponseParameters: addRespnseParameterSessionId(): if enabled appConfiguration.getSessionIdRequestParameterEnabled() Janssen->ResponseParameters: addResponseParameterSid(): if enabled appConfiguration.getIncludeSidInResponse() Janssen->ResponseParameters: put session_state and state Janssen->ClientService: updateAccessTime() Janssen->Browser: /redirect_uri?with_param=...", "title": "Prompt NONE"}, {"location": "janssen-server/auth-server/openid-features/request-objects/", "tags": ["administration", "auth-server", "openidc", "feature"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Request Objects"}, {"location": "janssen-server/auth-server/openid-features/request-objects/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/request-objects/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/request-objects/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/", "tags": ["administration", "auth-server", "openidc", "feature", "subject identifier"], "text": "Subject identifiers # Subject identifiers(defined in OpenID Connect Core SPEC ) are unique identifiers generated by Janssen Server(i.e. OpenId Provider) for an end-user. Subject identifiers are unique per Janssen Server instance and it is shared with the client (or clients) via ID token or access token. Whether the same subject identifier is used for the same end-user across multiple clients depends on the kind of subject identifier configured for a particular client. Types of Subject Identifiers # Janssen Server supports both subject identifier types, public and pairwise , as specified in OpenID Connect specification. For a particular Janssen Server deployment, the supported types are listed in the response of Janssen Server's well-known configuration endpoint is given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration The subject_types_supported claim in the response specifies the list of all the supported types. More details about both types are given in this section of specification. Public Subject Identifiers # Public subject identifiers are identifiers that the server generates and assigns to each subject. These identifiers are unique for each server deployment. All the clients that are configured to use a public type subject identifier will be supplied this same identifier for a given subject by the Janssen Server. Sharing common subject identifiers across multiple clients may enable clients to correlate data about a particular subject. If this is an unwanted situation, then the client should use pairwise subject identifiers. By default, the Janssen Server uses the subject attribute inum as the subject identifier. Customizing Subject Identifier Attribute # At the server level, the administrator specifies which subject attribute should be used as subject identifiers. This can be done by updating the value of openidSubAttribute Janssen Server property. At the client level, this can be further customized. If a client uses public type subject identifier, the client can configure the subject attribute that should be used as a subject identifier. This should be done at the client registration time. To enable client level customization, the Janssen Server property publicSubjectIdentifierPerClientEnabled should be set to true and also the desired attribute should be part of the list defined by the Janssen Server property subjectIdentifiersPerClientSupported . Both these properties can be set by the administrator using TUI . Pairwise Subject Identifiers # When a client chooses to use pairwise subject identifier, the Janssen Server generates and attaches a new identifier to all the subjects requested by the client. This identifier is consistently used for the subject-client pair and never used for any other clients configured on the Janssen Server. If multiple clients are using pairwise type subject identifiers, then the same subject will have different identifiers for each subject. Since every client has a different identifier for the same subject, the clients can't match identifiers and correlate information about a subject out of the band. Pairwise Identifier Generation # Janssen Server uses host name string from redirect URI or sector identifier, local user ID, and a salt string as initial inputs to generate pairwise identifiers. This input is then signed with the HS256 signing algorithm to generate a pairwise identifier. Sector identifier configuration influences how pairwise identifiers are calculated. See this document for more details. Properties # Janssen Server allows customization concerning subject identifiers using the properties below: subjectTypesSupported defaultSubjectType shareSubjectIdBetweenClientsWithSameSectorId openidSubAttribute publicSubjectIdentifierPerClientEnabled subjectIdentifiersPerClientSupported skipAuthorizationForOpenIdScopeAndPairwiseId pairwiseCalculationKey pairwiseCalculationSalt pairwiseIdType Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Pairwise/Public Subject Identifiers"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#subject-identifiers", "text": "Subject identifiers(defined in OpenID Connect Core SPEC ) are unique identifiers generated by Janssen Server(i.e. OpenId Provider) for an end-user. Subject identifiers are unique per Janssen Server instance and it is shared with the client (or clients) via ID token or access token. Whether the same subject identifier is used for the same end-user across multiple clients depends on the kind of subject identifier configured for a particular client.", "title": "Subject identifiers"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#types-of-subject-identifiers", "text": "Janssen Server supports both subject identifier types, public and pairwise , as specified in OpenID Connect specification. For a particular Janssen Server deployment, the supported types are listed in the response of Janssen Server's well-known configuration endpoint is given below. https://janssen.server.host/jans-auth/.well-known/openid-configuration The subject_types_supported claim in the response specifies the list of all the supported types. More details about both types are given in this section of specification.", "title": "Types of Subject Identifiers"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#public-subject-identifiers", "text": "Public subject identifiers are identifiers that the server generates and assigns to each subject. These identifiers are unique for each server deployment. All the clients that are configured to use a public type subject identifier will be supplied this same identifier for a given subject by the Janssen Server. Sharing common subject identifiers across multiple clients may enable clients to correlate data about a particular subject. If this is an unwanted situation, then the client should use pairwise subject identifiers. By default, the Janssen Server uses the subject attribute inum as the subject identifier.", "title": "Public Subject Identifiers"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#customizing-subject-identifier-attribute", "text": "At the server level, the administrator specifies which subject attribute should be used as subject identifiers. This can be done by updating the value of openidSubAttribute Janssen Server property. At the client level, this can be further customized. If a client uses public type subject identifier, the client can configure the subject attribute that should be used as a subject identifier. This should be done at the client registration time. To enable client level customization, the Janssen Server property publicSubjectIdentifierPerClientEnabled should be set to true and also the desired attribute should be part of the list defined by the Janssen Server property subjectIdentifiersPerClientSupported . Both these properties can be set by the administrator using TUI .", "title": "Customizing Subject Identifier Attribute"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#pairwise-subject-identifiers", "text": "When a client chooses to use pairwise subject identifier, the Janssen Server generates and attaches a new identifier to all the subjects requested by the client. This identifier is consistently used for the subject-client pair and never used for any other clients configured on the Janssen Server. If multiple clients are using pairwise type subject identifiers, then the same subject will have different identifiers for each subject. Since every client has a different identifier for the same subject, the clients can't match identifiers and correlate information about a subject out of the band.", "title": "Pairwise Subject Identifiers"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#pairwise-identifier-generation", "text": "Janssen Server uses host name string from redirect URI or sector identifier, local user ID, and a salt string as initial inputs to generate pairwise identifiers. This input is then signed with the HS256 signing algorithm to generate a pairwise identifier. Sector identifier configuration influences how pairwise identifiers are calculated. See this document for more details.", "title": "Pairwise Identifier Generation"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#properties", "text": "Janssen Server allows customization concerning subject identifiers using the properties below: subjectTypesSupported defaultSubjectType shareSubjectIdBetweenClientsWithSameSectorId openidSubAttribute publicSubjectIdentifierPerClientEnabled subjectIdentifiersPerClientSupported skipAuthorizationForOpenIdScopeAndPairwiseId pairwiseCalculationKey pairwiseCalculationSalt pairwiseIdType", "title": "Properties"}, {"location": "janssen-server/auth-server/openid-features/subject-identifiers/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/consent/customize/", "tags": ["administration", "auth-server", "openidc", "feature", "consent"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Customize"}, {"location": "janssen-server/auth-server/openid-features/consent/customize/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/consent/customize/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/consent/customize/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/consent/list-delete/", "tags": ["administration", "auth-server", "openidc", "feature", "consent"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "List/Delete Consent"}, {"location": "janssen-server/auth-server/openid-features/consent/list-delete/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/consent/list-delete/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/consent/list-delete/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/logout/back-channel/", "tags": ["administration", "auth-server", "openidc", "feature", "logout"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Back Channel"}, {"location": "janssen-server/auth-server/openid-features/logout/back-channel/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/logout/back-channel/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/logout/back-channel/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/logout/customizing-logout/", "tags": ["administration", "auth-server", "openidc", "feature", "logout"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Customizing Logout"}, {"location": "janssen-server/auth-server/openid-features/logout/customizing-logout/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/logout/customizing-logout/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/logout/customizing-logout/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/logout/forcing-logout/", "tags": ["administration", "auth-server", "openidc", "feature", "logout"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Forcing Logout on Browser Exit"}, {"location": "janssen-server/auth-server/openid-features/logout/forcing-logout/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/logout/forcing-logout/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/logout/forcing-logout/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/logout/front-channel/", "tags": ["administration", "auth-server", "openidc", "feature", "logout"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Front Channel"}, {"location": "janssen-server/auth-server/openid-features/logout/front-channel/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/openid-features/logout/front-channel/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/openid-features/logout/front-channel/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/openid-features/user-claims/built-in-claims/", "tags": ["administration", "auth-server", "openidc", "feature", "claims", "built-in-claims"], "text": "Built-in Claims # The Janssen Server includes all standard claims defined in OpenID Connect specifications . Built-in claims defines a standard set of pre-defined claims available to use after installation for sharing of user attributes between identity providers and relying parties. The built-in user claims in Janssen are listed in below table Display Name Claim Name Description Username user_name Username of user Password user_password Password of user First Name given_name First name of user Middle Name middle_name Middle name of user Last Name family_name Last name of user Display Name name Display name of user Email email Email address of user Nickname nickname Nickname used for user CIBA Device Registration Token jans_backchannel_device_registration_tkn CIBA Device Registration Token CIBA User code jans_backchannel_usr_code CIBA User code Locale locale End-User's locale, represented as a BCP47 (RFC5646) language tag Website URL website URL of the End-User's Web page or blog IMAP Data imap_data IMAP data jansAdminUIRole jansAdminUIRole Gluu Flex Admin UI role Enrollment code jans_enrollment_code Enrollment code User Permission user_permission User permission Preferred Language preferred_language Preferred language Profile URL profile Profile URL Secret Question secret_question Secret question used to verify user identity Email Verified email_verified Is user's email verified? Birthdate birthdate Baithdate of user Time zone info zoneinfo The End-User's time zone Phone Number verified phone_number_verified Is user's phone number verified? Preferred Username preferred_username A domain issued and managed identifier for the person TransientId transient_id ... PersistentId persistent_id ... Country country User's country Secret Answer secret_answer Secret answer used to verify user identity OpenID Connect JSON formatted address address End-User's preferred postal address. The value of the address member is a JSON structure containing some or all of the members defined in OpenID Connect 1.0 Core Standard Section 5.1.1 User certificate user_certificate User certificate Organization o Organization Picture URL picture User's picture url", "title": "Built-in Claims"}, {"location": "janssen-server/auth-server/openid-features/user-claims/built-in-claims/#built-in-claims", "text": "The Janssen Server includes all standard claims defined in OpenID Connect specifications . Built-in claims defines a standard set of pre-defined claims available to use after installation for sharing of user attributes between identity providers and relying parties. The built-in user claims in Janssen are listed in below table Display Name Claim Name Description Username user_name Username of user Password user_password Password of user First Name given_name First name of user Middle Name middle_name Middle name of user Last Name family_name Last name of user Display Name name Display name of user Email email Email address of user Nickname nickname Nickname used for user CIBA Device Registration Token jans_backchannel_device_registration_tkn CIBA Device Registration Token CIBA User code jans_backchannel_usr_code CIBA User code Locale locale End-User's locale, represented as a BCP47 (RFC5646) language tag Website URL website URL of the End-User's Web page or blog IMAP Data imap_data IMAP data jansAdminUIRole jansAdminUIRole Gluu Flex Admin UI role Enrollment code jans_enrollment_code Enrollment code User Permission user_permission User permission Preferred Language preferred_language Preferred language Profile URL profile Profile URL Secret Question secret_question Secret question used to verify user identity Email Verified email_verified Is user's email verified? Birthdate birthdate Baithdate of user Time zone info zoneinfo The End-User's time zone Phone Number verified phone_number_verified Is user's phone number verified? Preferred Username preferred_username A domain issued and managed identifier for the person TransientId transient_id ... PersistentId persistent_id ... Country country User's country Secret Answer secret_answer Secret answer used to verify user identity OpenID Connect JSON formatted address address End-User's preferred postal address. The value of the address member is a JSON structure containing some or all of the members defined in OpenID Connect 1.0 Core Standard Section 5.1.1 User certificate user_certificate User certificate Organization o Organization Picture URL picture User's picture url", "title": "Built-in Claims"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/", "tags": ["administration", "auth-server", "openidc", "feature", "claims", "custom-claims"], "text": "Custom Claims # Custom claims provide the flexibility to include application-specific or user-specific information in the authentication process.Custom claims serve to enrich the information available to the relying party (RP), which is the application or service that relies on the identity provided by the OIDC provider. While standard claims provide basic user information, custom claims allow for the inclusion of domain-specific attributes or application-specific data that might be required for user personalization, authorization, or other business logic. User claims should be unique and non-null or empty. Adding a new custom user claim # MySQL persistence # Step 1: Create a custom attribute # Create a new custom attribute using Test User Interface or CURL commands , superb tools provided in Janssen. The attribute-name should be the claim-name. Step 2: Make entry of the claim in MySQL Schema # Add a column to table jansPerson in MySQL. Command will be ALTER TABLE jansPerson ADD COLUMN <claimName> <dataType> ; Example mysql> ALTER TABLE jansPerson ADD COLUMN newClaim VARCHAR(100); Choose dataType according to the following table TUI dataType SQL dataType Text VARCHAR() string value to be kept, SIZE is an integer for max string size Numeric INT Boolean SMALLINT Binary BINARY Certificate TEXT Date DATETIME(3) Numeric INT Multivalued JSON Warning If the attribute is Multivalued, dataType should be JSON regardless of what you will choose for Type in Janssen TUI. The above steps will create the custom user claim in the MySQL persistence. Once the user claim is added, it can be used in user management.", "title": "Adding Custom Claims"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/#custom-claims", "text": "Custom claims provide the flexibility to include application-specific or user-specific information in the authentication process.Custom claims serve to enrich the information available to the relying party (RP), which is the application or service that relies on the identity provided by the OIDC provider. While standard claims provide basic user information, custom claims allow for the inclusion of domain-specific attributes or application-specific data that might be required for user personalization, authorization, or other business logic. User claims should be unique and non-null or empty.", "title": "Custom Claims"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/#adding-a-new-custom-user-claim", "text": "", "title": "Adding a new custom user claim"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/#mysql-persistence", "text": "", "title": "MySQL persistence"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/#step-1-create-a-custom-attribute", "text": "Create a new custom attribute using Test User Interface or CURL commands , superb tools provided in Janssen. The attribute-name should be the claim-name.", "title": "Step 1: Create a custom attribute"}, {"location": "janssen-server/auth-server/openid-features/user-claims/custom-claims/#step-2-make-entry-of-the-claim-in-mysql-schema", "text": "Add a column to table jansPerson in MySQL. Command will be ALTER TABLE jansPerson ADD COLUMN <claimName> <dataType> ; Example mysql> ALTER TABLE jansPerson ADD COLUMN newClaim VARCHAR(100); Choose dataType according to the following table TUI dataType SQL dataType Text VARCHAR() string value to be kept, SIZE is an integer for max string size Numeric INT Boolean SMALLINT Binary BINARY Certificate TEXT Date DATETIME(3) Numeric INT Multivalued JSON Warning If the attribute is Multivalued, dataType should be JSON regardless of what you will choose for Type in Janssen TUI. The above steps will create the custom user claim in the MySQL persistence. Once the user claim is added, it can be used in user management.", "title": "Step 2: Make entry of the claim in MySQL Schema"}, {"location": "janssen-server/auth-server/session-management/idp-v-rp/", "tags": ["administration", "auth-server", "session"], "text": "IDP versus RP session # Applications generally have their own session cookie (the \"RP Session\"). This makes sense, because the RP only redirects to the IDP for authentication if it cannot find its own local cookie. If a user has a session with many RP's, achieving simultaneous logout across all sites is a challenge--something which your business leaders may not appreciate. While OpenID proposes several solutions to logout, none are ideal. Fundamentally, logout is an asynchronous challenge. A given RP may be disconnected from the network. Thus logout messages sent to RP's that are not received must be replayed. The IETF Sec Events Workgroup has been working on standards to handle logout (and other asynchronous requirements). But adoption of this architecture is not common. Another challenge of RP sessions is that they may have a different timeout for inactivity. See the Janssen Planning Guide page on Timeout Management for more details.", "title": "IDP v RP Sessions"}, {"location": "janssen-server/auth-server/session-management/idp-v-rp/#idp-versus-rp-session", "text": "Applications generally have their own session cookie (the \"RP Session\"). This makes sense, because the RP only redirects to the IDP for authentication if it cannot find its own local cookie. If a user has a session with many RP's, achieving simultaneous logout across all sites is a challenge--something which your business leaders may not appreciate. While OpenID proposes several solutions to logout, none are ideal. Fundamentally, logout is an asynchronous challenge. A given RP may be disconnected from the network. Thus logout messages sent to RP's that are not received must be replayed. The IETF Sec Events Workgroup has been working on standards to handle logout (and other asynchronous requirements). But adoption of this architecture is not common. Another challenge of RP sessions is that they may have a different timeout for inactivity. See the Janssen Planning Guide page on Timeout Management for more details.", "title": "IDP versus RP session"}, {"location": "janssen-server/auth-server/session-management/multiple-sessions-one-browser/", "tags": ["administration", "auth-server", "session", "Account Chooser"], "text": "Select Account # A person may have several accounts on a single Jans Auth Server instance. For example, it is common to have several Gmail accounts. Jans Auth Server uses two cookies to track which accounts are associated with a browser: session_id and current_sessions . Below is an example or a person with two authenticated sessions: session_id: de510ab6-b06c-4393-86d8-12a7c501aafe current_sessions: [\"de510ab6-b06c-4393-86d8-12a7c501aafe\", \"c691e83d-eb1b-41f0-b453-fab905681b5b\"] An RP can trigger Auth Server's built in Account Chooser feature by sending an OpenID Authentication Request with the parameter prompt=select_account . In this case, Auth Server renders the default page: /opt/jans/jetty/jans-auth/custom/pages/selectAccount.xhtml This page iterates current_sessions and enables the person to login as a different account, for example: You can override this page if you place a selectAccount.xhtml in custom/pages .", "title": "Multiple Sessions in One Browser"}, {"location": "janssen-server/auth-server/session-management/multiple-sessions-one-browser/#select-account", "text": "A person may have several accounts on a single Jans Auth Server instance. For example, it is common to have several Gmail accounts. Jans Auth Server uses two cookies to track which accounts are associated with a browser: session_id and current_sessions . Below is an example or a person with two authenticated sessions: session_id: de510ab6-b06c-4393-86d8-12a7c501aafe current_sessions: [\"de510ab6-b06c-4393-86d8-12a7c501aafe\", \"c691e83d-eb1b-41f0-b453-fab905681b5b\"] An RP can trigger Auth Server's built in Account Chooser feature by sending an OpenID Authentication Request with the parameter prompt=select_account . In this case, Auth Server renders the default page: /opt/jans/jetty/jans-auth/custom/pages/selectAccount.xhtml This page iterates current_sessions and enables the person to login as a different account, for example: You can override this page if you place a selectAccount.xhtml in custom/pages .", "title": "Select Account"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/", "tags": ["administration", "auth-server", "oauth", "access-token"], "text": "OAuth Access Tokens # Background # When a software client calls an OAuth protected API, an access token is presented in the HTTP Authorization header of the request. Following is an example of a bearer token: Authorization: Bearer 8pkjyj0gxhwh6ux2 OAuth access tokens come in two main types: bearer tokens and MAC tokens. Bearer tokens are the most commonly used type of access token. They are simply a string that is included in the Authorization header of an HTTP request. The client presents the token to the resource server, which can trust the token, by validating it was issued by a trusted authorization server. Bearer tokens can be sent either by value or reference. A value token is a JWT, signed by the authorization server. By calling Auth Server's [introspection endpoint], the client can trade the reference token for the plain JSON object. MAC tokens, are cryptographically signed tokens that include a nonce, timestamp, and other information to prevent replay attacks. They are typically used in situations where the client and the resource server are not able to securely share a secret. They are not commonly used and Janssen Auth Server does not support MAC tokens. There are several security considerations that both mobile developers and API developers should be aware of when working with OAuth access tokens. For mobile developers, it is important to ensure that the access token is stored securely on the device, and that it is not exposed to other apps or processes. API developers should ensure that their API is only accessible to clients that have a valid access token, and that the API properly validates the token before allowing access to the protected resource. Scopes are used in OAuth access tokens to limit the extent of access of a token, i.e. the specific resources and actions that the token is valid for. Scopes are typically defined by the API developer, and the client can request a specific scope when requesting an access token from the authorization server. This allows the API developer to fine-tune the level of access that different clients have to the API. Other security considerations for OAuth access tokens include the need to protect against replay attacks by including a nonce and timestamp in the token and using TLS for all communication between the client, the authorization server and the resource server. It is also important to rotate the access token. This can be done by using short lived tokens and refresh tokens which will allow the client to obtain a new access token without re-prompting the user for their credentials. By default, Jans Auth Server access tokens expire after 5 minutes. Access Token Schema # claim Description active true or false . iss The URI of the issuer authorization server aud The audience, used by the client to verify it is the correct recipient. During registration, the client can specify additional_audience values iat When the client was issued, in seconds, e.g. 1514797822 exp When the token expires, in seconds, e.g. 1514797942 scope A space delimited list of scopes client_id Recipient of the token nbf Not before, which insures the token is only valid within a certain time window cnf Confirmation, used for TLS client certificate bound tokens It is possible to add additional claims to an access token via the Auth Server interception scripts. The preferred script is the update token script . You can also use the introspection script . Access Token Crypto (JWT) # JWT access tokens are signed by Jans Auth Server using algorithms specified in the access_token_signing_alg_values_supported claim of the OpenID configuration endpoint response. Access tokens are signed with the standard OpenID signing key. Jans Auth Server supports TLS client certificate bound access tokens. After a successful mutual TLS client authentication, Jans Auth Server encodes the client certificate thumbprint (hash) in x5t#S256 confirmation method of the JWT or introspection JSON. Assuming the client uses the same certificate to establish a mutual TLS session with the API, the thumbprint in the access token can verify that this is the same client that obtained the access token. This feature is typically used in high security environments, as the operational cost of mutual TLS is material. Decoded JWT example { \"iss\" : \"https://server.example.com\" , \"sub\" : \"ty.webb@example.com\" , \"exp\" : 1493726400 , \"nbf\" : 1493722800 , \"cnf\" :{ \"x5t#S256\" : \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" } } Sample introspection response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"active\" : true , \"iss\" : \"https://server.example.com\" , \"sub\" : \"ty.webb@example.com\" , \"exp\" : 1493726400 , \"nbf\" : 1493722800 , \"cnf\" :{ \"x5t#S256\" : \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" } } Server and Client configurations # Access token lifetime is configurable at the server level via the accessTokenLifetime property. However, a client can override this value during client registration with the access_token_lifetime request parameter. Revoke Access Token # Access token can be revoked via Revoke Endpoint", "title": "OAuth Access Tokens"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#oauth-access-tokens", "text": "", "title": "OAuth Access Tokens"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#background", "text": "When a software client calls an OAuth protected API, an access token is presented in the HTTP Authorization header of the request. Following is an example of a bearer token: Authorization: Bearer 8pkjyj0gxhwh6ux2 OAuth access tokens come in two main types: bearer tokens and MAC tokens. Bearer tokens are the most commonly used type of access token. They are simply a string that is included in the Authorization header of an HTTP request. The client presents the token to the resource server, which can trust the token, by validating it was issued by a trusted authorization server. Bearer tokens can be sent either by value or reference. A value token is a JWT, signed by the authorization server. By calling Auth Server's [introspection endpoint], the client can trade the reference token for the plain JSON object. MAC tokens, are cryptographically signed tokens that include a nonce, timestamp, and other information to prevent replay attacks. They are typically used in situations where the client and the resource server are not able to securely share a secret. They are not commonly used and Janssen Auth Server does not support MAC tokens. There are several security considerations that both mobile developers and API developers should be aware of when working with OAuth access tokens. For mobile developers, it is important to ensure that the access token is stored securely on the device, and that it is not exposed to other apps or processes. API developers should ensure that their API is only accessible to clients that have a valid access token, and that the API properly validates the token before allowing access to the protected resource. Scopes are used in OAuth access tokens to limit the extent of access of a token, i.e. the specific resources and actions that the token is valid for. Scopes are typically defined by the API developer, and the client can request a specific scope when requesting an access token from the authorization server. This allows the API developer to fine-tune the level of access that different clients have to the API. Other security considerations for OAuth access tokens include the need to protect against replay attacks by including a nonce and timestamp in the token and using TLS for all communication between the client, the authorization server and the resource server. It is also important to rotate the access token. This can be done by using short lived tokens and refresh tokens which will allow the client to obtain a new access token without re-prompting the user for their credentials. By default, Jans Auth Server access tokens expire after 5 minutes.", "title": "Background"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#access-token-schema", "text": "claim Description active true or false . iss The URI of the issuer authorization server aud The audience, used by the client to verify it is the correct recipient. During registration, the client can specify additional_audience values iat When the client was issued, in seconds, e.g. 1514797822 exp When the token expires, in seconds, e.g. 1514797942 scope A space delimited list of scopes client_id Recipient of the token nbf Not before, which insures the token is only valid within a certain time window cnf Confirmation, used for TLS client certificate bound tokens It is possible to add additional claims to an access token via the Auth Server interception scripts. The preferred script is the update token script . You can also use the introspection script .", "title": "Access Token Schema"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#access-token-crypto-jwt", "text": "JWT access tokens are signed by Jans Auth Server using algorithms specified in the access_token_signing_alg_values_supported claim of the OpenID configuration endpoint response. Access tokens are signed with the standard OpenID signing key. Jans Auth Server supports TLS client certificate bound access tokens. After a successful mutual TLS client authentication, Jans Auth Server encodes the client certificate thumbprint (hash) in x5t#S256 confirmation method of the JWT or introspection JSON. Assuming the client uses the same certificate to establish a mutual TLS session with the API, the thumbprint in the access token can verify that this is the same client that obtained the access token. This feature is typically used in high security environments, as the operational cost of mutual TLS is material. Decoded JWT example { \"iss\" : \"https://server.example.com\" , \"sub\" : \"ty.webb@example.com\" , \"exp\" : 1493726400 , \"nbf\" : 1493722800 , \"cnf\" :{ \"x5t#S256\" : \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" } } Sample introspection response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"active\" : true , \"iss\" : \"https://server.example.com\" , \"sub\" : \"ty.webb@example.com\" , \"exp\" : 1493726400 , \"nbf\" : 1493722800 , \"cnf\" :{ \"x5t#S256\" : \"bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2\" } }", "title": "Access Token Crypto (JWT)"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#server-and-client-configurations", "text": "Access token lifetime is configurable at the server level via the accessTokenLifetime property. However, a client can override this value during client registration with the access_token_lifetime request parameter.", "title": "Server and Client configurations"}, {"location": "janssen-server/auth-server/tokens/oauth-access-tokens/#revoke-access-token", "text": "Access token can be revoked via Revoke Endpoint", "title": "Revoke Access Token"}, {"location": "janssen-server/auth-server/tokens/oauth-refresh-tokens/", "tags": ["administration", "auth-server", "oauth", "refresh-token"], "text": "Background # Refresh tokens are an optimization that allows a client to renew an access token without having to re-authenticate. You should not issue a refresh token to untrusted clients, i.e. public clients. Server properties. # refreshTokenLifetime : Default: 14400 minutes - With this property, you can specify a longer lifetime then 5 days. Using the Jans Config API, you can set a client-specific refresh token lifetime. forceOfflineAccessScopeToEnableRefreshToken : Default: True - A good practice is for Auth Server to explicitly ask the subject to consent to the use of refresh tokens. To encourage this practice, by default, Auth Server requires that the client have the offline_access scope to issue a refresh token. persistRefreshToken : Default: True - Otherwise they are written to the cache clientRegDefaultToCodeFlowWithRefresh : Default: True - Set to False if you don't want web clients to get a refresh token. removeRefreshTokensForClientOnLogout : Default: True - Boolean value specifying whether to remove Refresh Tokens on logout. However if intention is to leave Refresh Token after logout, it's required to set it to false . skipRefreshTokenDuringRefreshing : Default: False - Boolean value specifying whether to skip refreshing tokens on refreshing. By default AS always creates new Refresh Token on refresh call to Token Endpoint. This property allows to avoid (skip) new Refresh Token creation. refreshTokenExtendLifetimeOnRotation : Default: False - Boolean value specifying whether to extend refresh tokens on rotation. By default lifetime is not extended, expiration date is set to date of previous Refresh Token. With this property it's possible to have all further Refresh Token have fixed (extended in relation to previuos Refresh Token) lifetime. checkUserPresenceOnRefreshToken : Default: False - Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check. Refresh Token Management # To revoke a token, a client can do so via the revocation endpoint (including revocation of all tokens by client_id ). online_access scope # If online_access scope is present then refresh token expires when the session ends (for example via front channel logout).", "title": "OAuth Refresh Tokens"}, {"location": "janssen-server/auth-server/tokens/oauth-refresh-tokens/#background", "text": "Refresh tokens are an optimization that allows a client to renew an access token without having to re-authenticate. You should not issue a refresh token to untrusted clients, i.e. public clients.", "title": "Background"}, {"location": "janssen-server/auth-server/tokens/oauth-refresh-tokens/#server-properties", "text": "refreshTokenLifetime : Default: 14400 minutes - With this property, you can specify a longer lifetime then 5 days. Using the Jans Config API, you can set a client-specific refresh token lifetime. forceOfflineAccessScopeToEnableRefreshToken : Default: True - A good practice is for Auth Server to explicitly ask the subject to consent to the use of refresh tokens. To encourage this practice, by default, Auth Server requires that the client have the offline_access scope to issue a refresh token. persistRefreshToken : Default: True - Otherwise they are written to the cache clientRegDefaultToCodeFlowWithRefresh : Default: True - Set to False if you don't want web clients to get a refresh token. removeRefreshTokensForClientOnLogout : Default: True - Boolean value specifying whether to remove Refresh Tokens on logout. However if intention is to leave Refresh Token after logout, it's required to set it to false . skipRefreshTokenDuringRefreshing : Default: False - Boolean value specifying whether to skip refreshing tokens on refreshing. By default AS always creates new Refresh Token on refresh call to Token Endpoint. This property allows to avoid (skip) new Refresh Token creation. refreshTokenExtendLifetimeOnRotation : Default: False - Boolean value specifying whether to extend refresh tokens on rotation. By default lifetime is not extended, expiration date is set to date of previous Refresh Token. With this property it's possible to have all further Refresh Token have fixed (extended in relation to previuos Refresh Token) lifetime. checkUserPresenceOnRefreshToken : Default: False - Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check.", "title": "Server properties."}, {"location": "janssen-server/auth-server/tokens/oauth-refresh-tokens/#refresh-token-management", "text": "To revoke a token, a client can do so via the revocation endpoint (including revocation of all tokens by client_id ).", "title": "Refresh Token Management"}, {"location": "janssen-server/auth-server/tokens/oauth-refresh-tokens/#online_access-scope", "text": "If online_access scope is present then refresh token expires when the session ends (for example via front channel logout).", "title": "online_access scope"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/", "tags": ["administration", "auth-server", "oauth", "access-token", "tx-token"], "text": "OAuth Transaction Tokens # Background # Transaction Tokens (Txn-Tokens) enable workloads in a trusted domain to ensure that user identity and authorization context of an external programmatic request, such as an API invocation, are preserved and available to all workloads that are invoked as part of processing such a request. Txn-Tokens also enable workloads within the trusted domain to optionally immutably assert to downstream workloads that they were invoked in the call chain of the request. Txn-Tokens are short-lived, signed JWTs that assert the identity of a user or a workload and assert an authorization context. The authorization context provides information expected to remain constant during the execution of a call as it passes through multiple workloads. Transaction Tokens spec Transaction Token JWT # Sample header { \"typ\" : \"N_A\" , \"alg\" : \"RS256\" , \"kid\" : \"identifier-to-key\" } Sample payload iss - a URN [RFC8141] that uniquely identifies the workload or the Txn-Token Service that created the Txn-Token. iat - the time at which the Txn-Token was created. aud - a URN [RFC8141] that uniquely identifies the audience of the Txn-Token. This MUST identify the trust domain in which the Txn-Token is used. exp - the time at which the Txn-Token expires. txn - the unique transaction identifier as defined in Section 2.2 of [RFC8417]. When used in the transaction token, it identifies the entire call chain. purp - a string defining the purpose or intent of this transaction sub - the unique identifier of the user or workload on whose behalf the call chain is being executed. The format of this claim MAY be a Subject Identifier. azd - a JSON object that contains values that remain constant in the call chain. rctx - a JSON object that describes the environmental context of the requested transaction. { \"aud\" : [ \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" , \"http://trusted.com\" ], \"rctx\" : { \"req_ip\" : \"69.151.72.123\" }, \"purp\" : \"tx_token\" , \"sub\" : \"3245675432\" , \"iss\" : \"https://yuriyz-adjusted-coyote.gluu.info\" , \"azd\" : { \"client_id\" : \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" }, \"txn\" : \"080c8f19-d9ee-4a26-852d-32e4fdc6ff6c\" , \"exp\" : 1705054542 , \"iat\" : 1705054362 } Transaction Token Obtain/Replace # Transaction Tokens can be obtained at Token Endpoint Sample request POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-adjusted-coyote.gluu.info Content-Type: application/x-www-form-urlencoded grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange&audience=http%3A%2F%2Ftrusted.com&subject_token=5fb696ac-638a-4dbf-81cd-27daeb61caf9&subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aaccess_token&requested_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Atxn_token&rctx=%7B%22req_ip%22%3A%2269.151.72.123%22%7D Sample response HTTP/ 1.1 200 Cache - Co ntr ol : n o - s t ore Co nne c t io n : Keep - Alive Co ntent - Le n g t h : 980 Co ntent - Type : applica t io n /jso n Da te : Fri , 12 Ja n 2024 10 : 12 : 40 GMT Keep - Alive : t imeou t = 5 , max= 100 Pragma : n o - cache Se t - Cookie : X - Correla t io n - Id=a 348 acce - d 9 c 1-424 a - a f 83-e4 d 75 f 7 f 3368 ; Secure; H tt pO nl y;H tt pO nl y S tr ic t - Tra ns por t - Securi t y : max - age= 31536000 ; i n cludeSubDomai ns X - Co ntent - Type - Op t io ns : n os n i ff X - Xss - Pro te c t io n : 1 ; mode=block { \"access_token\" : \"eyJraWQiOiJjb25uZWN0XzBlZGMxOTIyLTk1MjAtNDFkNi1iZGMyLTk3ZjdmYWMwMzRkMl9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOlsiZDYwZjIxYjctYjZkZC00MTQwLWIyMjgtZTZiZTA5OWJjM2NlIiwiaHR0cDovL3RydXN0ZWQuY29tIl0sInJlcV9jdHgiOnsicmVxX2lwIjoiNjkuMTUxLjcyLjEyMyJ9LCJzdWJfaWQiOiIiLCJpc3MiOiJodHRwczovL3l1cml5ei1hZGp1c3RlZC1jb3lvdGUuZ2x1dS5pbmZvIiwiYXpkIjp7ImNsaWVudF9pZCI6ImQ2MGYyMWI3LWI2ZGQtNDE0MC1iMjI4LWU2YmUwOTliYzNjZSJ9LCJ0eG4iOiIwODBjOGYxOS1kOWVlLTRhMjYtODUyZC0zMmU0ZmRjNmZmNmMiLCJleHAiOjE3MDUwNTQ1NDIsImlhdCI6MTcwNTA1NDM2Mn0.fpPFZpzxitbLw71RgO3O8uSOHJARp16H2THO4YAimJKWiczSE8-DvUAqulEW2nCNN3PRdojXWCe4ipxPSr_0ugLSFWhFKdpLmQqec_udhcV-UWiuGPLfq0XeKte60ESSvj5jgpaBNaaGS2vmFeSLdGrAx1CY2EH06OYrttOrgFFGqMhLJJ1Cpacqa0vmXnHi9gbrS-FIf2_4nNkQKMitQ-m-ec-0J02RjgkEL9zrzFwYNAoE1HEIZNFBhh7GqBejH0cXnR2tBOOz66z83SLqMTAZ-WyaMxmITHGLGLmHZOGyHdiIYME1rLXalrK58XHesMFtB-gae10Ey6w1OIgiAg\" , \"issued_token_type\" : \"urn:ietf:params:oauth:token-type:txn_token\" , \"token_type\" : \"N_A\" } Decoded transaction token JWT { \"aud\" : [ \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" , \"http://trusted.com\" ], \"rctx\" : { \"req_ip\" : \"69.151.72.123\" }, \"purp\" : \"tx_token\" , \"sub_id\" : \"\" , \"iss\" : \"https://yuriyz-adjusted-coyote.gluu.info\" , \"azd\" : { \"client_id\" : \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" }, \"txn\" : \"080c8f19-d9ee-4a26-852d-32e4fdc6ff6c\" , \"exp\" : 1705054542 , \"iat\" : 1705054362 } Replacement looks exactly the same with one different that subject_token must have previously obtained transaction token (not regular access_token ). View full obtain execution log here View full replace execution log here References # Transaction Tokens spec", "title": "OAuth Transaction Tokens"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/#oauth-transaction-tokens", "text": "", "title": "OAuth Transaction Tokens"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/#background", "text": "Transaction Tokens (Txn-Tokens) enable workloads in a trusted domain to ensure that user identity and authorization context of an external programmatic request, such as an API invocation, are preserved and available to all workloads that are invoked as part of processing such a request. Txn-Tokens also enable workloads within the trusted domain to optionally immutably assert to downstream workloads that they were invoked in the call chain of the request. Txn-Tokens are short-lived, signed JWTs that assert the identity of a user or a workload and assert an authorization context. The authorization context provides information expected to remain constant during the execution of a call as it passes through multiple workloads. Transaction Tokens spec", "title": "Background"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/#transaction-token-jwt", "text": "Sample header { \"typ\" : \"N_A\" , \"alg\" : \"RS256\" , \"kid\" : \"identifier-to-key\" } Sample payload iss - a URN [RFC8141] that uniquely identifies the workload or the Txn-Token Service that created the Txn-Token. iat - the time at which the Txn-Token was created. aud - a URN [RFC8141] that uniquely identifies the audience of the Txn-Token. This MUST identify the trust domain in which the Txn-Token is used. exp - the time at which the Txn-Token expires. txn - the unique transaction identifier as defined in Section 2.2 of [RFC8417]. When used in the transaction token, it identifies the entire call chain. purp - a string defining the purpose or intent of this transaction sub - the unique identifier of the user or workload on whose behalf the call chain is being executed. The format of this claim MAY be a Subject Identifier. azd - a JSON object that contains values that remain constant in the call chain. rctx - a JSON object that describes the environmental context of the requested transaction. { \"aud\" : [ \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" , \"http://trusted.com\" ], \"rctx\" : { \"req_ip\" : \"69.151.72.123\" }, \"purp\" : \"tx_token\" , \"sub\" : \"3245675432\" , \"iss\" : \"https://yuriyz-adjusted-coyote.gluu.info\" , \"azd\" : { \"client_id\" : \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" }, \"txn\" : \"080c8f19-d9ee-4a26-852d-32e4fdc6ff6c\" , \"exp\" : 1705054542 , \"iat\" : 1705054362 }", "title": "Transaction Token JWT"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/#transaction-token-obtainreplace", "text": "Transaction Tokens can be obtained at Token Endpoint Sample request POST /jans-auth/restv1/token HTTP/1.1 Host: yuriyz-adjusted-coyote.gluu.info Content-Type: application/x-www-form-urlencoded grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange&audience=http%3A%2F%2Ftrusted.com&subject_token=5fb696ac-638a-4dbf-81cd-27daeb61caf9&subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aaccess_token&requested_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Atxn_token&rctx=%7B%22req_ip%22%3A%2269.151.72.123%22%7D Sample response HTTP/ 1.1 200 Cache - Co ntr ol : n o - s t ore Co nne c t io n : Keep - Alive Co ntent - Le n g t h : 980 Co ntent - Type : applica t io n /jso n Da te : Fri , 12 Ja n 2024 10 : 12 : 40 GMT Keep - Alive : t imeou t = 5 , max= 100 Pragma : n o - cache Se t - Cookie : X - Correla t io n - Id=a 348 acce - d 9 c 1-424 a - a f 83-e4 d 75 f 7 f 3368 ; Secure; H tt pO nl y;H tt pO nl y S tr ic t - Tra ns por t - Securi t y : max - age= 31536000 ; i n cludeSubDomai ns X - Co ntent - Type - Op t io ns : n os n i ff X - Xss - Pro te c t io n : 1 ; mode=block { \"access_token\" : \"eyJraWQiOiJjb25uZWN0XzBlZGMxOTIyLTk1MjAtNDFkNi1iZGMyLTk3ZjdmYWMwMzRkMl9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOlsiZDYwZjIxYjctYjZkZC00MTQwLWIyMjgtZTZiZTA5OWJjM2NlIiwiaHR0cDovL3RydXN0ZWQuY29tIl0sInJlcV9jdHgiOnsicmVxX2lwIjoiNjkuMTUxLjcyLjEyMyJ9LCJzdWJfaWQiOiIiLCJpc3MiOiJodHRwczovL3l1cml5ei1hZGp1c3RlZC1jb3lvdGUuZ2x1dS5pbmZvIiwiYXpkIjp7ImNsaWVudF9pZCI6ImQ2MGYyMWI3LWI2ZGQtNDE0MC1iMjI4LWU2YmUwOTliYzNjZSJ9LCJ0eG4iOiIwODBjOGYxOS1kOWVlLTRhMjYtODUyZC0zMmU0ZmRjNmZmNmMiLCJleHAiOjE3MDUwNTQ1NDIsImlhdCI6MTcwNTA1NDM2Mn0.fpPFZpzxitbLw71RgO3O8uSOHJARp16H2THO4YAimJKWiczSE8-DvUAqulEW2nCNN3PRdojXWCe4ipxPSr_0ugLSFWhFKdpLmQqec_udhcV-UWiuGPLfq0XeKte60ESSvj5jgpaBNaaGS2vmFeSLdGrAx1CY2EH06OYrttOrgFFGqMhLJJ1Cpacqa0vmXnHi9gbrS-FIf2_4nNkQKMitQ-m-ec-0J02RjgkEL9zrzFwYNAoE1HEIZNFBhh7GqBejH0cXnR2tBOOz66z83SLqMTAZ-WyaMxmITHGLGLmHZOGyHdiIYME1rLXalrK58XHesMFtB-gae10Ey6w1OIgiAg\" , \"issued_token_type\" : \"urn:ietf:params:oauth:token-type:txn_token\" , \"token_type\" : \"N_A\" } Decoded transaction token JWT { \"aud\" : [ \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" , \"http://trusted.com\" ], \"rctx\" : { \"req_ip\" : \"69.151.72.123\" }, \"purp\" : \"tx_token\" , \"sub_id\" : \"\" , \"iss\" : \"https://yuriyz-adjusted-coyote.gluu.info\" , \"azd\" : { \"client_id\" : \"d60f21b7-b6dd-4140-b228-e6be099bc3ce\" }, \"txn\" : \"080c8f19-d9ee-4a26-852d-32e4fdc6ff6c\" , \"exp\" : 1705054542 , \"iat\" : 1705054362 } Replacement looks exactly the same with one different that subject_token must have previously obtained transaction token (not regular access_token ). View full obtain execution log here View full replace execution log here", "title": "Transaction Token Obtain/Replace"}, {"location": "janssen-server/auth-server/tokens/oauth-tx-tokens/#references", "text": "Transaction Tokens spec", "title": "References"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/", "tags": ["administration", "auth-server", "token", "id token", "customize id_token"], "text": "OpenID Connect ID Token # Defined in Section 2 of OpenID Connect Core 1.0 : The primary extension that OpenID Connect makes to OAuth 2.0 to enable End-Users to be Authenticated is the ID Token data structure. The ID Token is a security token that contains Claims about the Authentication of an End-User by an Authorization Server when using a Client, and potentially other requested Claims. The ID Token is represented as a JSON Web Token (JWT) [JWT]. The ID Token is similar to a SAML 2.0 Assertion, which must contain an Authentication statement, and may optionally contain an Attribute statement, defined in the spec as: Authentication statements: These are created by the party that successfully authenticated a user. At a minimum, they describe the particular means used to authenticate the user and the specific time at which the authentication took place. Attribute statements: These contain specific identifying attributes about the subject (for example, that user \u201cJohn Doe\u201d has \u201cGold\u201d card status). The ID Token is a standard JWT, and can use signing and encryption depending on the configuration preferences of the client. A sample payload for a Jans Auth Server id_token is below: { \"iss\": \"https://idp.example.tld\", <-- OP hostname \"aud\": \"bd0469f7-f80a-4595-bd52-df9826f0a2f4\", <-- client_id \"sub\": \"0a9ca356-6130-4032-91c6-a2dfe4e19804\", <-- in this case, a pairwise identifer \"iat\": 1672373703, <-- issued at \"auth_time\": 1672373700, <-- when user authenticated \"acr\": \"basic\", <-- how user authenticated \"amr\": [\"10\"], <-- Extra authn details \"nonce\": \"1u0y3ii\", <-- client should verify \"sid\": \"5f01565c-f2dc-4b4b-af8a-ab1578a5dbe3\", <-- session id handle \"jansOpenIDConnectVersion\": \"openidconnect-1.0\" <-- OpenID version } A great tool if you want to decode a JWT is Auth0's https://jwt.io/ . Notice that a basic ID Token, like the one above, contains details about the authentication event, not user claims. You can configure the client to \"include claims in id_token\", or you can set a Auth Server configuration property, legacyIdTokenClaims to True to set the behavior for all clients. Obtaining an ID Token # The client may obtain an ID Token in the authorization response, from the token endpoint, or both. Note, if you intend to use the Code Flow, and you don't intend to validate the c_hash or s_hash values in the ID Token returned from the authorization endpoint, don't check id_token in the response_type for the authorization endpoint, as it will waste compute and storage generating a token you don't need. Validating an ID Token # At a minimum, client developers should always validate the following: Signature of the ID token iss make sure the ID Token was issued by the OP you trust aud make sure the ID Token was issued to your client_id exp make sure the token is not expired nonce make sure the id_token correlates to your original authn request Using the ID Token as an access token for API's # Don't do this. The ID Token is an identity assertion, not an access token. It may be passed in the payload to an API, but it should not be used in lieu of an OAuth access token! Fundamentally, the id_token details how a person was authenticated, not which API's a client is authorized to call. Also, OAuth access tokens are short lived, while the expiration of an identity assertion is much longer. Customizing claims in an id_token # The UpdateTokenType can be used in the following scenarios: In addition to the default claims in an ID token ( iss , aud , exp etc), additional custom claims can be added to an ID token. You can also change the default value of a claim", "title": "OpenID id_token"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/#openid-connect-id-token", "text": "Defined in Section 2 of OpenID Connect Core 1.0 : The primary extension that OpenID Connect makes to OAuth 2.0 to enable End-Users to be Authenticated is the ID Token data structure. The ID Token is a security token that contains Claims about the Authentication of an End-User by an Authorization Server when using a Client, and potentially other requested Claims. The ID Token is represented as a JSON Web Token (JWT) [JWT]. The ID Token is similar to a SAML 2.0 Assertion, which must contain an Authentication statement, and may optionally contain an Attribute statement, defined in the spec as: Authentication statements: These are created by the party that successfully authenticated a user. At a minimum, they describe the particular means used to authenticate the user and the specific time at which the authentication took place. Attribute statements: These contain specific identifying attributes about the subject (for example, that user \u201cJohn Doe\u201d has \u201cGold\u201d card status). The ID Token is a standard JWT, and can use signing and encryption depending on the configuration preferences of the client. A sample payload for a Jans Auth Server id_token is below: { \"iss\": \"https://idp.example.tld\", <-- OP hostname \"aud\": \"bd0469f7-f80a-4595-bd52-df9826f0a2f4\", <-- client_id \"sub\": \"0a9ca356-6130-4032-91c6-a2dfe4e19804\", <-- in this case, a pairwise identifer \"iat\": 1672373703, <-- issued at \"auth_time\": 1672373700, <-- when user authenticated \"acr\": \"basic\", <-- how user authenticated \"amr\": [\"10\"], <-- Extra authn details \"nonce\": \"1u0y3ii\", <-- client should verify \"sid\": \"5f01565c-f2dc-4b4b-af8a-ab1578a5dbe3\", <-- session id handle \"jansOpenIDConnectVersion\": \"openidconnect-1.0\" <-- OpenID version } A great tool if you want to decode a JWT is Auth0's https://jwt.io/ . Notice that a basic ID Token, like the one above, contains details about the authentication event, not user claims. You can configure the client to \"include claims in id_token\", or you can set a Auth Server configuration property, legacyIdTokenClaims to True to set the behavior for all clients.", "title": "OpenID Connect ID Token"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/#obtaining-an-id-token", "text": "The client may obtain an ID Token in the authorization response, from the token endpoint, or both. Note, if you intend to use the Code Flow, and you don't intend to validate the c_hash or s_hash values in the ID Token returned from the authorization endpoint, don't check id_token in the response_type for the authorization endpoint, as it will waste compute and storage generating a token you don't need.", "title": "Obtaining an ID Token"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/#validating-an-id-token", "text": "At a minimum, client developers should always validate the following: Signature of the ID token iss make sure the ID Token was issued by the OP you trust aud make sure the ID Token was issued to your client_id exp make sure the token is not expired nonce make sure the id_token correlates to your original authn request", "title": "Validating an ID Token"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/#using-the-id-token-as-an-access-token-for-apis", "text": "Don't do this. The ID Token is an identity assertion, not an access token. It may be passed in the payload to an API, but it should not be used in lieu of an OAuth access token! Fundamentally, the id_token details how a person was authenticated, not which API's a client is authorized to call. Also, OAuth access tokens are short lived, while the expiration of an identity assertion is much longer.", "title": "Using the ID Token as an access token for API's"}, {"location": "janssen-server/auth-server/tokens/openid-id-token/#customizing-claims-in-an-id_token", "text": "The UpdateTokenType can be used in the following scenarios: In addition to the default claims in an ID token ( iss , aud , exp etc), additional custom claims can be added to an ID token. You can also change the default value of a claim", "title": "Customizing claims in an id_token"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/", "tags": ["administration", "auth-server", "token", "userinfo-token"], "text": "Userinfo JWT # An OpenID Connect client, after obtaining an access token, can present it at the Userinfo endpoint to obtain the Userinfo JWT token. The Userinfo response is is described in OpenID Core 5.4.3 , and directs the developer to: Verify that the OP that responded was the intended OP through a TLS server certificate check If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. If the response was signed, the Client SHOULD validate the signature. Below is an example of the Userinfo claims for the default Jans Admin user: { \"sub\": \"e25c4146-ce9d-465e-9b59-b9d959bdfe3a\", \"email\": \"admin@issuer.tld\", \"given_name\": \"Admin\", \"family_name\": \"User\", \"name\": \"Default Admin User\", \"middle_name\": \"Admin\", \"nickname\": \"Admin\", \"email_verified\": true, \"inum\": \"e25c4146-ce9d-465e-9b59-b9d959bdfe3a\", \"jansAdminUIRole\": [\"api-admin\"] } Selective disclosure # Domains can limit the claims released to a client from the Userinfo endpoint by associating only the OpenID scopes required by that client. You can also define new scopes, and associate any user claims with them. Note, clients still must request the scopes they need for an access token. For example, a client may be authorize Requesting individual claims # If you want to use the claims parameter, you will have to first enable this feature in the Auth Server properties: set claimsParameterSupported=True . This is not a recommended configuration, because the claims parameter bypasses the privacy protection of the OpenID scopes construct. Dynamic Scopes / Interception Script # If you need to call an API to render scopes or scope values on the fly, you should see the Dynamic Scopes interception script. Userinfo formatter # There is a configuration property dateFormatterPatterns which can be used for format date claims. Example: {'dateFormatterPatterns': {'userinfo':'yyyy-MM-dd'}} . Language support # The default value for the configuration parameter claimsLocalesSupported is ['en'] . Currently, only the name and description supports localization. You will also need to make a proper request and provide the associated values for the claim in the database.", "title": "OpenID Userinfo Token"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#userinfo-jwt", "text": "An OpenID Connect client, after obtaining an access token, can present it at the Userinfo endpoint to obtain the Userinfo JWT token. The Userinfo response is is described in OpenID Core 5.4.3 , and directs the developer to: Verify that the OP that responded was the intended OP through a TLS server certificate check If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. If the response was signed, the Client SHOULD validate the signature. Below is an example of the Userinfo claims for the default Jans Admin user: { \"sub\": \"e25c4146-ce9d-465e-9b59-b9d959bdfe3a\", \"email\": \"admin@issuer.tld\", \"given_name\": \"Admin\", \"family_name\": \"User\", \"name\": \"Default Admin User\", \"middle_name\": \"Admin\", \"nickname\": \"Admin\", \"email_verified\": true, \"inum\": \"e25c4146-ce9d-465e-9b59-b9d959bdfe3a\", \"jansAdminUIRole\": [\"api-admin\"] }", "title": "Userinfo JWT"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#selective-disclosure", "text": "Domains can limit the claims released to a client from the Userinfo endpoint by associating only the OpenID scopes required by that client. You can also define new scopes, and associate any user claims with them. Note, clients still must request the scopes they need for an access token. For example, a client may be authorize", "title": "Selective disclosure"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#requesting-individual-claims", "text": "If you want to use the claims parameter, you will have to first enable this feature in the Auth Server properties: set claimsParameterSupported=True . This is not a recommended configuration, because the claims parameter bypasses the privacy protection of the OpenID scopes construct.", "title": "Requesting individual claims"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#dynamic-scopes-interception-script", "text": "If you need to call an API to render scopes or scope values on the fly, you should see the Dynamic Scopes interception script.", "title": "Dynamic Scopes / Interception Script"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#userinfo-formatter", "text": "There is a configuration property dateFormatterPatterns which can be used for format date claims. Example: {'dateFormatterPatterns': {'userinfo':'yyyy-MM-dd'}} .", "title": "Userinfo formatter"}, {"location": "janssen-server/auth-server/tokens/openid-userinfo-token/#language-support", "text": "The default value for the configuration parameter claimsLocalesSupported is ['en'] . Currently, only the name and description supports localization. You will also need to make a proper request and provide the associated values for the claim in the database.", "title": "Language support"}, {"location": "janssen-server/auth-server/tokens/uma-rpt-token/", "tags": ["administration", "auth-server", "token", "rpt-token"], "text": "Background # The UMA requesting party token (RPT) is an OAuth access token associated with the UMA grant. An RPT is unique to a requesting party, client, authorization server, resource server, and resource owner. The client uses the RPT in the Authorization header of an API request. The RPT bearer token conveys that UMA policy evaluation was successful on Auth Server. The Client may also present the RPT token while making a request to Auth Server for a new RPT, for example to up-scope or down-scope a token. For more information on UMA, see the specifications: * User-Managed Access (UMA) 2.0 Grant for OAuth 2.0 Authorization * Federated Authorization for User-Managed Access (UMA) 2.0 Server properties # umaRptAsJwt Default: False - : Reference token is the default umaRptLifetime Default: 3600 seconds - : 60 minutes introspectionAccessTokenMustHaveUmaProtectionScope Default: False - : umaGrantAccessIfNoPolicies Default: False - : umaTicketLifetime Default: 3600 seconds - : 60 minutes - Returned by the Resource Server to the Client for presentation at the UMA token endpoint. The ticket is the equivalent of the code in the OAuth code flow. umaAddScopesAutomatically Default: True - : umaPctLifetime Default: 1728000 seconds - : The PCT is a pushed claim token that references a previous claims gathering flow, so you don't have to bother the subject again for this information. umaValidateClaimToken Default: False - : umaRestrictResourceToAssociatedClient Default: False - :", "title": "UMA RPT Token"}, {"location": "janssen-server/auth-server/tokens/uma-rpt-token/#background", "text": "The UMA requesting party token (RPT) is an OAuth access token associated with the UMA grant. An RPT is unique to a requesting party, client, authorization server, resource server, and resource owner. The client uses the RPT in the Authorization header of an API request. The RPT bearer token conveys that UMA policy evaluation was successful on Auth Server. The Client may also present the RPT token while making a request to Auth Server for a new RPT, for example to up-scope or down-scope a token. For more information on UMA, see the specifications: * User-Managed Access (UMA) 2.0 Grant for OAuth 2.0 Authorization * Federated Authorization for User-Managed Access (UMA) 2.0", "title": "Background"}, {"location": "janssen-server/auth-server/tokens/uma-rpt-token/#server-properties", "text": "umaRptAsJwt Default: False - : Reference token is the default umaRptLifetime Default: 3600 seconds - : 60 minutes introspectionAccessTokenMustHaveUmaProtectionScope Default: False - : umaGrantAccessIfNoPolicies Default: False - : umaTicketLifetime Default: 3600 seconds - : 60 minutes - Returned by the Resource Server to the Client for presentation at the UMA token endpoint. The ticket is the equivalent of the code in the OAuth code flow. umaAddScopesAutomatically Default: True - : umaPctLifetime Default: 1728000 seconds - : The PCT is a pushed claim token that references a previous claims gathering flow, so you don't have to bother the subject again for this information. umaValidateClaimToken Default: False - : umaRestrictResourceToAssociatedClient Default: False - :", "title": "Server properties"}, {"location": "janssen-server/auth-server/uma-features/claims-gathering-endpoint/", "tags": ["administration", "auth-server", "uma", "feature", "endpoint"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Claims Gathering Endpoint"}, {"location": "janssen-server/auth-server/uma-features/claims-gathering-endpoint/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/uma-features/claims-gathering-endpoint/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/uma-features/claims-gathering-endpoint/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/auth-server/uma-features/rpt-endpoint/", "tags": ["administration", "auth-server", "uma", "feature", "endpoint"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "RPT Endpoint"}, {"location": "janssen-server/auth-server/uma-features/rpt-endpoint/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/auth-server/uma-features/rpt-endpoint/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/auth-server/uma-features/rpt-endpoint/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/config-guide/custom-assets-configuration/", "tags": ["administration", "configuration", "custom assets"], "text": "Custom Assets Configuration # The Janssen Server provides multiple configuration tools to configure custom assets. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using The Command Line # In the Janssen Server, you can deploy custom assets using the command line. To get the details of Janssen command line operations relevant to the custom assets, check the operations under the JansAssets task using the command below. Command jans cli --info JansAssets Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 Operation ID: get-asset-by-inum Description: Gets an asset by inum - unique identifier Parameters: inum: Asset Inum [string] Operation ID: delete-asset Description: Delete an asset Parameters: inum: Asset identifier [string] Operation ID: get-asset-by-name Description: Fetch asset by name. Parameters: name: Asset Name [string] Operation ID: get-all-assets Description: Gets all Jans assets. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for searching [string] Operation ID: get-asset-services Description: Gets asset services Operation ID: get-asset-types Description: Get valid asset types Operation ID: put-asset Description: Update existing asset Schema: AssetForm Operation ID: post-new-asset Description: Upload new asset Schema: AssetForm To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample AssetForm Get All Current Custom Assets # Use the operation ID get-all-assets to get all the currently configured custom assets on the Janssen Server. Command jans cli --operation-id get-all-assets Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 { \"start\" : 0 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 3 , \"entries\" : [ { \"dn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" , \"inum\" : \"61edc29d-45f8-4ab9-8c9a-7b39e4cbe440\" , \"fileName\" : \"p2.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:36:08\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" }, { \"dn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" , \"inum\" : \"835c7a68-57b1-4e39-8d2a-2a3963f2a92f\" , \"fileName\" : \"p1.properties\" , \"description\" : \"updated thrice Valid text description\" , \"document\" : \"cHJvcGVydGllcwo=\\r\\n\" , \"jansService\" : [ \"jans-auth\" ], \"jansEnabled\" : false , \"baseDn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" }, { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" } ] } Get Custom Asset By inum # With get-asset-by-inum operation-id, we can get any specific asset matched with inum . If we know the inum , we can simply use the below command: Command jans cli --operation-id get-asset-by-inum \\ --url-suffix inum:61edc29d-45f8-4ab9-8c9a-7b39e4cbe440 It returns the details as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" , \"inum\" : \"61edc29d-45f8-4ab9-8c9a-7b39e4cbe440\" , \"fileName\" : \"p2.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:36:08\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" } Get Custom Asset By Name # With get-asset-by-name operation-id, we can get any specific asset matched with name . If we know the name , we can simply use the below command: Command jans cli --operation-id get-asset-by-name \\ --url-suffix name:p1.properties It returns the details as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" , \"inum\" : \"835c7a68-57b1-4e39-8d2a-2a3963f2a92f\" , \"fileName\" : \"p1.properties\" , \"description\" : \"updated thrice Valid text description\" , \"document\" : \"cHJvcGVydGllcwo=\\r\\n\" , \"jansService\" : [ \"jans-auth\" ], \"jansEnabled\" : false , \"baseDn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" } ] } Get Services # Get the list of Janssen Server services that support custom assets by performing get-asset-services operation. Command jans cli --operation-id get-asset-services Sample Output 1 2 3 4 5 6 7 8 9 10 [ \"jans-auth\", \"jans-casa\", \"jans-config-api\", \"jans-fido2\", \"jans-link\", \"jans-lock\", \"jans-scim\", \"jans-keycloak-link\" ] Get Valid Asset Types # Get the asset types of your Janssen Server by performing get-asset-types operation. Command jans cli --operation-id get-asset-types Sample Output 1 2 3 4 5 6 7 8 9 10 11 [ \"properties\", \"jar\", \"xhtml\", \"js\", \"css\", \"png\", \"gif\", \"jpg\", \"jpeg\" ] Add New Custom Asset # To create a new asset, we can use post-new-asset operation id. As shown in the output for --info command, the post-new-asset operation requires data to be sent according to AssetForm schema. To see the schema, use the command below: Command jans cli --schema AssetForm For better understanding, the Janssen Server also provides a sample of data to be sent to the server. This sample conforms to the schema above. Use the command below to get the sample. Command jans cli --schema-sample AssetForm Using the schema and the example above, we have added below data to the file /tmp/add-asset.json . Example below will load p3.properties file as a custom asset to the jans-auth service. Input 1 2 3 4 5 6 7 8 9 10 11 12 { \"document\" : { \"fileName\" : \"p3.properties\" , \"description\" : \"text description\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 144 , \"jansEnabled\" : true }, \"assetFile\" : \"/tmp/p3.properties\" } Now let's post this Assert to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-new-asset \\ --data /tmp/add-asset.json Update Existing Custom Assets # Use the put-asset operation to update an existing asset. This operation uses same schema as add new asset operation. For example, assuming that there is an existing asset as show below: Existing Asset 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" } Note assetFile attribute is optional for update operation as there may be scenario where only metadata of an asset is to be updated. Now to update level of this asset to 6, create a text file with following content in it. Let's name this text file as /tmp/update-asset.json Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"document\" : { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 6 , \"jansEnabled\" : true , }, \"assetFile\" : \"/tmp/p.properties\" } Now use the command below to update the asset with new value for level. Sample Command jans cli --operation-id put-asset \\ --data /tmp/update-asset.json Upon successful execution, this command will return with updated asset values. Return values 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 6 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" } Delete Custom Asset # You can delete any custom asset by its inum value. Command jans cli --operation-id delete-asset \\ --url-suffix inum:61edc29d-45f8-4ab9-8c9a-7b39e4cbe440 Using Text-based UI # In Janssen, You can deploy custom asset using the Text-Based UI also. You can start TUI using the command below: Command jans tui Asset Screen # Navigate to Assets tab to open the Assets screen as shown in the image below. To get the list of currently added Assets, bring the control to the Search box (using the tab key), and press Enter. Type the search string to search for Asset with matching inum , or File Name or Description Use the Add Asset button to create a new asset. From the screen below, select the custom asset that needs to be uploaded and select the Janssen Server service to which the asset will be uploaded. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the custom assets. Endpoint details are published in the Swagger document .", "title": "Custom Assets Configuration"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#custom-assets-configuration", "text": "The Janssen Server provides multiple configuration tools to configure custom assets. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Custom Assets Configuration"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#using-the-command-line", "text": "In the Janssen Server, you can deploy custom assets using the command line. To get the details of Janssen command line operations relevant to the custom assets, check the operations under the JansAssets task using the command below. Command jans cli --info JansAssets Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 Operation ID: get-asset-by-inum Description: Gets an asset by inum - unique identifier Parameters: inum: Asset Inum [string] Operation ID: delete-asset Description: Delete an asset Parameters: inum: Asset identifier [string] Operation ID: get-asset-by-name Description: Fetch asset by name. Parameters: name: Asset Name [string] Operation ID: get-all-assets Description: Gets all Jans assets. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for searching [string] Operation ID: get-asset-services Description: Gets asset services Operation ID: get-asset-types Description: Get valid asset types Operation ID: put-asset Description: Update existing asset Schema: AssetForm Operation ID: post-new-asset Description: Upload new asset Schema: AssetForm To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample AssetForm", "title": "Using The Command Line"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#get-all-current-custom-assets", "text": "Use the operation ID get-all-assets to get all the currently configured custom assets on the Janssen Server. Command jans cli --operation-id get-all-assets Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 { \"start\" : 0 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 3 , \"entries\" : [ { \"dn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" , \"inum\" : \"61edc29d-45f8-4ab9-8c9a-7b39e4cbe440\" , \"fileName\" : \"p2.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:36:08\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" }, { \"dn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" , \"inum\" : \"835c7a68-57b1-4e39-8d2a-2a3963f2a92f\" , \"fileName\" : \"p1.properties\" , \"description\" : \"updated thrice Valid text description\" , \"document\" : \"cHJvcGVydGllcwo=\\r\\n\" , \"jansService\" : [ \"jans-auth\" ], \"jansEnabled\" : false , \"baseDn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" }, { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" } ] }", "title": "Get All Current Custom Assets"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#get-custom-asset-by-inum", "text": "With get-asset-by-inum operation-id, we can get any specific asset matched with inum . If we know the inum , we can simply use the below command: Command jans cli --operation-id get-asset-by-inum \\ --url-suffix inum:61edc29d-45f8-4ab9-8c9a-7b39e4cbe440 It returns the details as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" , \"inum\" : \"61edc29d-45f8-4ab9-8c9a-7b39e4cbe440\" , \"fileName\" : \"p2.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:36:08\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=61edc29d-45f8-4ab9-8c9a-7b39e4cbe440,ou=document,o=jans\" }", "title": "Get Custom Asset By inum"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#get-custom-asset-by-name", "text": "With get-asset-by-name operation-id, we can get any specific asset matched with name . If we know the name , we can simply use the below command: Command jans cli --operation-id get-asset-by-name \\ --url-suffix name:p1.properties It returns the details as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" , \"inum\" : \"835c7a68-57b1-4e39-8d2a-2a3963f2a92f\" , \"fileName\" : \"p1.properties\" , \"description\" : \"updated thrice Valid text description\" , \"document\" : \"cHJvcGVydGllcwo=\\r\\n\" , \"jansService\" : [ \"jans-auth\" ], \"jansEnabled\" : false , \"baseDn\" : \"inum=835c7a68-57b1-4e39-8d2a-2a3963f2a92f,ou=document,o=jans\" } ] }", "title": "Get Custom Asset By Name"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#get-services", "text": "Get the list of Janssen Server services that support custom assets by performing get-asset-services operation. Command jans cli --operation-id get-asset-services Sample Output 1 2 3 4 5 6 7 8 9 10 [ \"jans-auth\", \"jans-casa\", \"jans-config-api\", \"jans-fido2\", \"jans-link\", \"jans-lock\", \"jans-scim\", \"jans-keycloak-link\" ]", "title": "Get Services"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#get-valid-asset-types", "text": "Get the asset types of your Janssen Server by performing get-asset-types operation. Command jans cli --operation-id get-asset-types Sample Output 1 2 3 4 5 6 7 8 9 10 11 [ \"properties\", \"jar\", \"xhtml\", \"js\", \"css\", \"png\", \"gif\", \"jpg\", \"jpeg\" ]", "title": "Get Valid Asset Types"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#add-new-custom-asset", "text": "To create a new asset, we can use post-new-asset operation id. As shown in the output for --info command, the post-new-asset operation requires data to be sent according to AssetForm schema. To see the schema, use the command below: Command jans cli --schema AssetForm For better understanding, the Janssen Server also provides a sample of data to be sent to the server. This sample conforms to the schema above. Use the command below to get the sample. Command jans cli --schema-sample AssetForm Using the schema and the example above, we have added below data to the file /tmp/add-asset.json . Example below will load p3.properties file as a custom asset to the jans-auth service. Input 1 2 3 4 5 6 7 8 9 10 11 12 { \"document\" : { \"fileName\" : \"p3.properties\" , \"description\" : \"text description\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 144 , \"jansEnabled\" : true }, \"assetFile\" : \"/tmp/p3.properties\" } Now let's post this Assert to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-new-asset \\ --data /tmp/add-asset.json", "title": "Add New Custom Asset"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#update-existing-custom-assets", "text": "Use the put-asset operation to update an existing asset. This operation uses same schema as add new asset operation. For example, assuming that there is an existing asset as show below: Existing Asset 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 142 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" } Note assetFile attribute is optional for update operation as there may be scenario where only metadata of an asset is to be updated. Now to update level of this asset to 6, create a text file with following content in it. Let's name this text file as /tmp/update-asset.json Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"document\" : { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 6 , \"jansEnabled\" : true , }, \"assetFile\" : \"/tmp/p.properties\" } Now use the command below to update the asset with new value for level. Sample Command jans cli --operation-id put-asset \\ --data /tmp/update-asset.json Upon successful execution, this command will return with updated asset values. Return values 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { \"dn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" , \"inum\" : \"fd67d07b-c874-4bc1-a9f0-860fc4f7a091\" , \"fileName\" : \"p.properties\" , \"description\" : \"Valid text description\" , \"document\" : \"cHJvcGVydGllcyBoZXJlLiAK\\r\\n\" , \"creationDate\" : \"2024-07-31T07:40:03\" , \"jansService\" : [ \"jans-auth\" ], \"jansLevel\" : 6 , \"jansEnabled\" : true , \"baseDn\" : \"inum=fd67d07b-c874-4bc1-a9f0-860fc4f7a091,ou=document,o=jans\" }", "title": "Update Existing Custom Assets"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#delete-custom-asset", "text": "You can delete any custom asset by its inum value. Command jans cli --operation-id delete-asset \\ --url-suffix inum:61edc29d-45f8-4ab9-8c9a-7b39e4cbe440", "title": "Delete Custom Asset"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#using-text-based-ui", "text": "In Janssen, You can deploy custom asset using the Text-Based UI also. You can start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#asset-screen", "text": "Navigate to Assets tab to open the Assets screen as shown in the image below. To get the list of currently added Assets, bring the control to the Search box (using the tab key), and press Enter. Type the search string to search for Asset with matching inum , or File Name or Description Use the Add Asset button to create a new asset. From the screen below, select the custom asset that needs to be uploaded and select the Janssen Server service to which the asset will be uploaded.", "title": "Asset Screen"}, {"location": "janssen-server/config-guide/custom-assets-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the custom assets. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/custom-scripts-config/", "tags": ["administration", "configuration", "custom-scripts"], "text": "Custom Scripts # Prerequisite: Know how to use the Janssen CLI in command-line mode Interception scripts can be used to implement custom business logic for authentication, authorization, and more in a way that is upgrade-proof and doesn't require forking the Gluu Server code. Using Janssen CLI, we can manage custom scripts as well. Let's get the task information using below command: jans cli --info CustomScripts In return we gets each of the sub-task details: Operation ID: get-config-scripts Description: Gets a list of custom scripts. Operation ID: post-config-scripts Description: Adds a new custom script. Schema: /components/schemas/CustomScript Operation ID: put-config-scripts Description: Updates a custom script. Schema: /components/schemas/CustomScript Operation ID: get-config-scripts-by-type Description: Gets list of scripts by type. url-suffix: type Operation ID: get-config-scripts-by-inum Description: Gets a script by Inum. url-suffix: inum Operation ID: delete-config-scripts-by-inum Description: Deletes a custom script. url-suffix: inum To get sample schema type jans cli --schema <schma>, for example jans cli --schema CustomScript Let's perform each of this operation. Find list of Custom scripts # get-config-scripts operation id can be used to get a list of custom scripts of the Janssen Server. The command line is: jans cli --operation-id get-config-scripts It returns all the custom scripts of the Janssen Server. Adds a New Custom Script # If we look at the description of this operation we see it supports schema: Operation ID: post-config-scripts Description: Adds a new custom script. Schema: /components/schemas/CustomScript So, let's get the schema first: jans cli CustomScript > /tmp/cs.json { \"dn\": null, \"inum\": null, \"name\": \"string\", \"aliases\": [], \"description\": null, \"script\": \"_file /root/script.py\", \"scriptType\": \"INTROSPECTION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": { \"value1\": null, \"value2\": null, \"description\": null, \"hide\": true }, \"level\": \"integer\", \"revision\": 0, \"enabled\": false, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } We need to fill some of these properties with valid data to add this new script. { \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"_file /root/client_registration.py\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [{ \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" }], \"configurationProperties\": null, \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } We can remove dn , inum . As because these two items are auto generated with random value. Also we see aliases , moduleproperties and configurationProperties are the array type keys . So we need to put data into [] otherwise it will raise an error. We can also use null value if we need to skip any of them. For scriptType we can choose only selected type of script from the below list. Name of the type of scripts # PERSON_AUTHENTICATION, INTROSPECTION, RESOURCE_OWNER_PASSWORD_CREDENTIALS, APPLICATION_SESSION, CACHE_REFRESH, CLIENT_REGISTRATION, ID_GENERATOR, UMA_RPT_POLICY, UMA_RPT_CLAIMS, UMA_CLAIMS_GATHERING, CONSENT_GATHERING, DYNAMIC_SCOPE, SPONTANEOUS_SCOPE, END_SESSION, POST_AUTHN, SCIM, CIBA_END_USER_NOTIFICATION, PERSISTENCE_EXTENSION, IDP, UPDATE_TOKEN Programming Language # Two types of programming language available there. Those are Python and JavaScript . We can choose any of them regarding the script we need to add. Alright, let's add the script using the command line we have: jans cli --operation-id post-config-scripts --data /tmp/cs.json Getting access token for scope https://jans.io/oauth/config/scripts.write Server Response: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": null, \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } Update an existing Custom Script # put-config-scripts operation-id can be used to update any existing script on the Janssen server. Operation ID: put-config-scripts Description: Updates a custom script. Schema: /components/schemas/CustomScript As we created a custom script in the above , let's update that one. So we know the dn:inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans and inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 here. In this case, I have modified as below: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"_file /root/client_registrationj.py\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [{ \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" }], \"configurationProperties\": [{ \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true }], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } You can see, I have added configurationProperties for testing purpose only. In case you need to change the script, you can do that by changing the script path as well. jans cli --operation-id put-config-scripts --data /tmp/cs.json Getting access token for scope https://jans.io/oauth/config/scripts.write Server Response: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": [ { \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true } ], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } Get Custom Script by type # With this operation-id, we can find a specific type of scripts. It uses url-suffix to get the list of a single type scripts. Operation ID: get-config-scripts-by-type Description: Gets list of scripts by type. url-suffix: type The command line is: jans cli --operation-id get-config-scripts-by-type --url-suffix type:script-type-name For an example, let's find all the scripts of CLIENT_REGISTRATION type. So, the command line is: jans cli --operation-id get-config-scripts-by-type --url-suffix type:CLIENT_REGISTRATION It returns all the custom scripts that are related to the CLIENT_REGISTRATION type available in the Janssen Server. You will find the name of all the types here Get Custom Scripts by it's inum # In case we need to find out details configuration of any custom script, we can search by its unique inum value. Operation ID: get-config-scripts-by-inum Description: Gets a script by Inum. url-suffix: inum command line: jans cli --operation-id get-config-scripts-by-inum --url-suffix inum:inum_value For example, we can show details here that we already added in the Janssen Server and we know it's inum value is 61aef81b-b22d-42c0-89d5-b098c976a2b7 . In our case, the command line is: jans cli --operation-id get-config-scripts-by-inum --url-suffix inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 It returns the configuration of the custom script matched with the given inum value. Getting access token for scope https://jans.io/oauth/config/scripts.readonly { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": [ { \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true } ], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } How to delete Custom Script? # Well, we can delete any custom script also in deed. In that case, we need to remember the inum value of the custom script we want to delete. In the above we added , updated a custom script. We know the inum value, so let's delete this one. Command line: jans cli --operation-id delete-config-scripts-by-inum --url-suffix inum:inum_value For example, in our case; the command line is: jans cli --operation-id delete-config-scripts-by-inum --url-suffix inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 That's all for Custom Script management with CLI feature. Note If a custom script that is set as Default authentication method is disabled or deleted then the default authentication value will be removed.", "title": "Custom Scripts"}, {"location": "janssen-server/config-guide/custom-scripts-config/#custom-scripts", "text": "Prerequisite: Know how to use the Janssen CLI in command-line mode Interception scripts can be used to implement custom business logic for authentication, authorization, and more in a way that is upgrade-proof and doesn't require forking the Gluu Server code. Using Janssen CLI, we can manage custom scripts as well. Let's get the task information using below command: jans cli --info CustomScripts In return we gets each of the sub-task details: Operation ID: get-config-scripts Description: Gets a list of custom scripts. Operation ID: post-config-scripts Description: Adds a new custom script. Schema: /components/schemas/CustomScript Operation ID: put-config-scripts Description: Updates a custom script. Schema: /components/schemas/CustomScript Operation ID: get-config-scripts-by-type Description: Gets list of scripts by type. url-suffix: type Operation ID: get-config-scripts-by-inum Description: Gets a script by Inum. url-suffix: inum Operation ID: delete-config-scripts-by-inum Description: Deletes a custom script. url-suffix: inum To get sample schema type jans cli --schema <schma>, for example jans cli --schema CustomScript Let's perform each of this operation.", "title": "Custom Scripts"}, {"location": "janssen-server/config-guide/custom-scripts-config/#find-list-of-custom-scripts", "text": "get-config-scripts operation id can be used to get a list of custom scripts of the Janssen Server. The command line is: jans cli --operation-id get-config-scripts It returns all the custom scripts of the Janssen Server.", "title": "Find list of Custom scripts"}, {"location": "janssen-server/config-guide/custom-scripts-config/#adds-a-new-custom-script", "text": "If we look at the description of this operation we see it supports schema: Operation ID: post-config-scripts Description: Adds a new custom script. Schema: /components/schemas/CustomScript So, let's get the schema first: jans cli CustomScript > /tmp/cs.json { \"dn\": null, \"inum\": null, \"name\": \"string\", \"aliases\": [], \"description\": null, \"script\": \"_file /root/script.py\", \"scriptType\": \"INTROSPECTION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": { \"value1\": null, \"value2\": null, \"description\": null, \"hide\": true }, \"level\": \"integer\", \"revision\": 0, \"enabled\": false, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } We need to fill some of these properties with valid data to add this new script. { \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"_file /root/client_registration.py\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [{ \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" }], \"configurationProperties\": null, \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } We can remove dn , inum . As because these two items are auto generated with random value. Also we see aliases , moduleproperties and configurationProperties are the array type keys . So we need to put data into [] otherwise it will raise an error. We can also use null value if we need to skip any of them. For scriptType we can choose only selected type of script from the below list.", "title": "Adds a New Custom Script"}, {"location": "janssen-server/config-guide/custom-scripts-config/#name-of-the-type-of-scripts", "text": "PERSON_AUTHENTICATION, INTROSPECTION, RESOURCE_OWNER_PASSWORD_CREDENTIALS, APPLICATION_SESSION, CACHE_REFRESH, CLIENT_REGISTRATION, ID_GENERATOR, UMA_RPT_POLICY, UMA_RPT_CLAIMS, UMA_CLAIMS_GATHERING, CONSENT_GATHERING, DYNAMIC_SCOPE, SPONTANEOUS_SCOPE, END_SESSION, POST_AUTHN, SCIM, CIBA_END_USER_NOTIFICATION, PERSISTENCE_EXTENSION, IDP, UPDATE_TOKEN", "title": "Name of the type of scripts"}, {"location": "janssen-server/config-guide/custom-scripts-config/#programming-language", "text": "Two types of programming language available there. Those are Python and JavaScript . We can choose any of them regarding the script we need to add. Alright, let's add the script using the command line we have: jans cli --operation-id post-config-scripts --data /tmp/cs.json Getting access token for scope https://jans.io/oauth/config/scripts.write Server Response: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": null, \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false }", "title": "Programming Language"}, {"location": "janssen-server/config-guide/custom-scripts-config/#update-an-existing-custom-script", "text": "put-config-scripts operation-id can be used to update any existing script on the Janssen server. Operation ID: put-config-scripts Description: Updates a custom script. Schema: /components/schemas/CustomScript As we created a custom script in the above , let's update that one. So we know the dn:inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans and inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 here. In this case, I have modified as below: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"_file /root/client_registrationj.py\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [{ \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" }], \"configurationProperties\": [{ \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true }], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false } You can see, I have added configurationProperties for testing purpose only. In case you need to change the script, you can do that by changing the script path as well. jans cli --operation-id put-config-scripts --data /tmp/cs.json Getting access token for scope https://jans.io/oauth/config/scripts.write Server Response: { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": [ { \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true } ], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false }", "title": "Update an existing Custom Script"}, {"location": "janssen-server/config-guide/custom-scripts-config/#get-custom-script-by-type", "text": "With this operation-id, we can find a specific type of scripts. It uses url-suffix to get the list of a single type scripts. Operation ID: get-config-scripts-by-type Description: Gets list of scripts by type. url-suffix: type The command line is: jans cli --operation-id get-config-scripts-by-type --url-suffix type:script-type-name For an example, let's find all the scripts of CLIENT_REGISTRATION type. So, the command line is: jans cli --operation-id get-config-scripts-by-type --url-suffix type:CLIENT_REGISTRATION It returns all the custom scripts that are related to the CLIENT_REGISTRATION type available in the Janssen Server. You will find the name of all the types here", "title": "Get Custom Script by type"}, {"location": "janssen-server/config-guide/custom-scripts-config/#get-custom-scripts-by-its-inum", "text": "In case we need to find out details configuration of any custom script, we can search by its unique inum value. Operation ID: get-config-scripts-by-inum Description: Gets a script by Inum. url-suffix: inum command line: jans cli --operation-id get-config-scripts-by-inum --url-suffix inum:inum_value For example, we can show details here that we already added in the Janssen Server and we know it's inum value is 61aef81b-b22d-42c0-89d5-b098c976a2b7 . In our case, the command line is: jans cli --operation-id get-config-scripts-by-inum --url-suffix inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 It returns the configuration of the custom script matched with the given inum value. Getting access token for scope https://jans.io/oauth/config/scripts.readonly { \"dn\": \"inum=61aef81b-b22d-42c0-89d5-b098c976a2b7,ou=scripts,o=jans\", \"inum\": \"61aef81b-b22d-42c0-89d5-b098c976a2b7\", \"name\": \"custom_script_client\", \"aliases\": null, \"description\": \"Testing custom script addition\", \"script\": \"...\", \"scriptType\": \"CLIENT_REGISTRATION\", \"programmingLanguage\": \"PYTHON\", \"moduleProperties\": [ { \"value1\": \"myvalue1\", \"value2\": \"myvalue2\", \"description\": \"description for this property\" } ], \"configurationProperties\": [ { \"value1\": \"testconfigvalue1\", \"value2\": \"testconfigvalue2\", \"description\": \"description for configuration property\", \"hide\": true } ], \"level\": 100, \"revision\": 0, \"enabled\": false, \"scriptError\": null, \"modified\": false, \"internal\": false }", "title": "Get Custom Scripts by it's inum"}, {"location": "janssen-server/config-guide/custom-scripts-config/#how-to-delete-custom-script", "text": "Well, we can delete any custom script also in deed. In that case, we need to remember the inum value of the custom script we want to delete. In the above we added , updated a custom script. We know the inum value, so let's delete this one. Command line: jans cli --operation-id delete-config-scripts-by-inum --url-suffix inum:inum_value For example, in our case; the command line is: jans cli --operation-id delete-config-scripts-by-inum --url-suffix inum:61aef81b-b22d-42c0-89d5-b098c976a2b7 That's all for Custom Script management with CLI feature. Note If a custom script that is set as Default authentication method is disabled or deleted then the default authentication value will be removed.", "title": "How to delete Custom Script?"}, {"location": "janssen-server/config-guide/link-configuration/", "tags": ["administration", "configuration", "link"], "text": "Jans Link Configuration # Details of how to configure Jans Link have been covered under Jans Link section .", "title": "Link Configuration"}, {"location": "janssen-server/config-guide/link-configuration/#jans-link-configuration", "text": "Details of how to configure Jans Link have been covered under Jans Link section .", "title": "Jans Link Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/", "tags": ["administration", "configuration", "smtp"], "text": "SMTP Configuration # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and customize the SMTP using the command line. To get the details of Janssen command line operations relevant to SMTP Configuration, you can check the operations under ConfigurationSmtp task using the command below: Command jans cli --info ConfigurationSmtp Sample Output Operation ID: get-config-smtp Description: Returns SMTP server configuration Operation ID: put-config-smtp Description: Updates SMTP server configuration Schema: SmtpConfiguration Operation ID: post-config-smtp Description: Adds SMTP server configuration Schema: SmtpConfiguration Operation ID: delete-config-smtp Description: Deletes SMTP server configuration Operation ID: test-config-smtp Description: Signing Test SMTP server configuration Schema: SmtpTest Find SMTP Server Configuration # To view the current SMTP server configuration, run the following command line: Command jans cli --operation-id get-config-smtp It will show the SMTP server configuration as below: Sample Output 1 2 3 4 5 6 7 8 9 10 { \"valid\" : false , \"port\" : 0 , \"trust_host\" : false , \"requires_authentication\" : false , \"key_store\" : \"/etc/certs/smtp-keys.pkcs12\" , \"key_store_password\" : \"kb5JITTrmCyX1LNEp8uorA==\" , \"key_store_alias\" : \"smtp_sig_ec256\" , \"signing_algorithm\" : \"SHA256withECDSA\" } Setup New SMTP Server Configuration # To add a new SMTP Server, we can use post-config-smtp operation id. As shown in the output for --info command, the post-config-smtp operation requires data to be sent according to the SmtpConfiguration schema. To see the schema, use the command below: Command jans cli --schema SmtpConfiguration The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample SmtpConfiguration Using the schema and the example above, we have added below data to the file /tmp/smtp.json . Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"valid\" : true , \"host\" : \"string\" , \"port\" : 5 , \"connect_protection\" : \"StartTls\" , \"trust_host\" : false , \"from_name\" : \"jans\" , \"from_email_address\" : \"string\" , \"requires_authentication\" : false , \"smtp_authentication_account_username\" : \"string\" , \"smtp_authentication_account_password\" : \"string\" , \"key_store\" : \"string\" , \"key_store_password\" : \"string\" , \"key_store_alias\" : \"string\" , \"signing_algorithm\" : \"string\" } To setup a new SMTP server configuration, run the following command: Command jans cli --operation-id post-config-smtp \\ --data /tmp/smtp.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"valid\" : true , \"host\" : \"string\" , \"port\" : 5 , \"connect_protection\" : \"StartTls\" , \"trust_host\" : false , \"from_name\" : \"jans\" , \"from_email_address\" : \"string\" , \"requires_authentication\" : false , \"smtp_authentication_account_username\" : \"string\" , \"smtp_authentication_account_password\" : \"CGmVqM6v4Hs=\" , \"key_store\" : \"string\" , \"key_store_password\" : \"CGmVqM6v4Hs=\" , \"key_store_alias\" : \"string\" , \"signing_algorithm\" : \"string\" } Update SMTP Server Configuration # To update the SMTP server, we can use the put-config-smtp operation id. simply change any information on /tmp/smtp.json file and run the following command: In that file, update the value false to true of the trust_host field. Command jans cli --operation-id put-config-smtp \\ --data /tmp/smtp.json It will update the information. Delete SMTP Sever Configuration # To delete the SMTP Sever, we can use the delete-config-smtp operation id. run the following command Command jans cli --operation-id delete-config-smtp Test SMTP Server Configuration # Testing SMTP Server configuration token with https://jans.io/oauth/config/smtp.write scope is required. To test the SMTP server configuration update, change any information on the /tmp/smtp.json file with test data and run the following command: Command jans cli --operation-id test-config-smtp \\ --data /tmp/smtp.json This will return status code 200 with a response as true or false based on the SMTP test result. Note: SMTP Password should be an App password and not a web login password. Using Text-based UI # Start TUI using the command below: Command jans tui SMPT Screen # Navigate to Auth Server -> SMPT to open the SMPT screen as shown in the image below. This screen shows the current SMTP server configuration. After changing the SMPT data, update the SMPT server using the Save button. Test the SMPTS server using the Test button, and the result will be displayed. The test result image is shown below. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the SMTP. Endpoint details are published in the Swagger document .", "title": "SMTP Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#smtp-configuration", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "SMTP Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the SMTP using the command line. To get the details of Janssen command line operations relevant to SMTP Configuration, you can check the operations under ConfigurationSmtp task using the command below: Command jans cli --info ConfigurationSmtp Sample Output Operation ID: get-config-smtp Description: Returns SMTP server configuration Operation ID: put-config-smtp Description: Updates SMTP server configuration Schema: SmtpConfiguration Operation ID: post-config-smtp Description: Adds SMTP server configuration Schema: SmtpConfiguration Operation ID: delete-config-smtp Description: Deletes SMTP server configuration Operation ID: test-config-smtp Description: Signing Test SMTP server configuration Schema: SmtpTest", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/smtp-configuration/#find-smtp-server-configuration", "text": "To view the current SMTP server configuration, run the following command line: Command jans cli --operation-id get-config-smtp It will show the SMTP server configuration as below: Sample Output 1 2 3 4 5 6 7 8 9 10 { \"valid\" : false , \"port\" : 0 , \"trust_host\" : false , \"requires_authentication\" : false , \"key_store\" : \"/etc/certs/smtp-keys.pkcs12\" , \"key_store_password\" : \"kb5JITTrmCyX1LNEp8uorA==\" , \"key_store_alias\" : \"smtp_sig_ec256\" , \"signing_algorithm\" : \"SHA256withECDSA\" }", "title": "Find SMTP Server Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#setup-new-smtp-server-configuration", "text": "To add a new SMTP Server, we can use post-config-smtp operation id. As shown in the output for --info command, the post-config-smtp operation requires data to be sent according to the SmtpConfiguration schema. To see the schema, use the command below: Command jans cli --schema SmtpConfiguration The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample SmtpConfiguration Using the schema and the example above, we have added below data to the file /tmp/smtp.json . Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"valid\" : true , \"host\" : \"string\" , \"port\" : 5 , \"connect_protection\" : \"StartTls\" , \"trust_host\" : false , \"from_name\" : \"jans\" , \"from_email_address\" : \"string\" , \"requires_authentication\" : false , \"smtp_authentication_account_username\" : \"string\" , \"smtp_authentication_account_password\" : \"string\" , \"key_store\" : \"string\" , \"key_store_password\" : \"string\" , \"key_store_alias\" : \"string\" , \"signing_algorithm\" : \"string\" } To setup a new SMTP server configuration, run the following command: Command jans cli --operation-id post-config-smtp \\ --data /tmp/smtp.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"valid\" : true , \"host\" : \"string\" , \"port\" : 5 , \"connect_protection\" : \"StartTls\" , \"trust_host\" : false , \"from_name\" : \"jans\" , \"from_email_address\" : \"string\" , \"requires_authentication\" : false , \"smtp_authentication_account_username\" : \"string\" , \"smtp_authentication_account_password\" : \"CGmVqM6v4Hs=\" , \"key_store\" : \"string\" , \"key_store_password\" : \"CGmVqM6v4Hs=\" , \"key_store_alias\" : \"string\" , \"signing_algorithm\" : \"string\" }", "title": "Setup New SMTP Server Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#update-smtp-server-configuration", "text": "To update the SMTP server, we can use the put-config-smtp operation id. simply change any information on /tmp/smtp.json file and run the following command: In that file, update the value false to true of the trust_host field. Command jans cli --operation-id put-config-smtp \\ --data /tmp/smtp.json It will update the information.", "title": "Update SMTP Server Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#delete-smtp-sever-configuration", "text": "To delete the SMTP Sever, we can use the delete-config-smtp operation id. run the following command Command jans cli --operation-id delete-config-smtp", "title": "Delete SMTP Sever Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#test-smtp-server-configuration", "text": "Testing SMTP Server configuration token with https://jans.io/oauth/config/smtp.write scope is required. To test the SMTP server configuration update, change any information on the /tmp/smtp.json file with test data and run the following command: Command jans cli --operation-id test-config-smtp \\ --data /tmp/smtp.json This will return status code 200 with a response as true or false based on the SMTP test result. Note: SMTP Password should be an App password and not a web login password.", "title": "Test SMTP Server Configuration"}, {"location": "janssen-server/config-guide/smtp-configuration/#using-text-based-ui", "text": "Start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/smtp-configuration/#smpt-screen", "text": "Navigate to Auth Server -> SMPT to open the SMPT screen as shown in the image below. This screen shows the current SMTP server configuration. After changing the SMPT data, update the SMPT server using the Save button. Test the SMPTS server using the Test button, and the result will be displayed. The test result image is shown below.", "title": "SMPT Screen"}, {"location": "janssen-server/config-guide/smtp-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the SMTP. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/", "tags": ["administration", "configuration", "agama project"], "text": "Agama project configuration # Agama project configuration involves adding and removing Agama projects to Janssen Server along with configuring and troubleshooting these project deployments. The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the configuration steps Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the configuration steps Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the configuration steps Using Command Line # In the Janssen Server, you can deploy and customize the Agama project using the command line. To get the details of Janssen command line operations relevant to Agama projects, you can check the operations under Agama task using the command below: Command jans cli --info Agama It will show the details of the available operation-ids for Agama. Operation ID: get-agama-prj-by-name Description: Fetches deployed the Agama project based on the name. Parameters: name: Agama project name [string] Operation ID: post-agama-prj Description: Deploy an Agama project. Parameters: name: Agama project name [string] Operation ID: delete-agama-prj Description: Delete a deployed Agama project. Parameters: name: Agama project name [string] Operation ID: get-agama-prj-configs Description: Retrieve the list of configs based on name. Parameters: name: Agama project name [string] Operation ID: put-agama-prj Description: Update an Agama project. Parameters: name: Agama project name [string] Parameters: type: Description not found for this property additionalProperties: Description not found for this property Operation ID: get-agama-prj Description: Retrieve the list of projects deployed currently. Parameters: start: No description is provided for this parameter [integer] count: No description is provided for this parameter [integer] In the sections below, we will see how to configure and manage Agama projects via the command line using the above operations. List Deployed Projects # Use the get-agama-prj operation to retrieve the list of deployed Agama projects: Command jans cli --operation-id get-agama-prj The output will list Agama projects that are added to this Janssen Server deployment. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=46546e9a-fed6-34d0-ba63-b615233b2115,ou=deployments,ou=agama,o=jans\" , \"id\" : \"46546e9a-fed6-34d0-ba63-b615233b2115\" , \"createdAt\" : \"2023-08-13T14:45:27\" , \"taskActive\" : false , \"finishedAt\" : \"2023-08-13T14:45:43\" , \"details\" : { \"error\" : \"There were problems processing one or more flows\" , \"flowsError\" : { \"mmrraju.np.test.me\" : null , \"mmrraju.test2.agama\" : null , \"mmrraju.u2f.me\" : \"Syntax error: mismatched input '<EOF>' expecting {'|', 'Log', 'Trigger', 'Call', 'RRF', 'When', 'Repeat', 'Iterate over', 'Match', 'Finish', 'RFAC', ALPHANUM, QNAME, DOTEXPR, DOTIDXEXPR, WS}\\nSymbol: [@9,43:42='<EOF>',<-1>,2:23]\\nLine: 2\\nColumn: 24\" }, \"projectMetadata\" : { \"projectName\" : \"user_pass_auth\" , \"author\" : \"mmrraju\" , \"type\" : \"community\" , \"description\" : \"This is password based authentication\" , \"version\" : \"1.0.34\" , \"configs\" : null } }, \"baseDn\" : \"jansId=46546e9a-fed6-34d0-ba63-b615233b2115,ou=deployments,ou=agama,o=jans\" } ] } Endpoint Arguments # Endpoint arguments are parameters passed to an API or function to specify how and what data to retrieve or process. There are two endpoint arguments available to the get-agama-prj operation. start : Should be an integer value. It's an index value of the starting point of the list. count : Should be an integer value. Total entries number you want to display. For example, to fetch details of the project at index 1 only, use the command below. Command jans cli --operation-id get-agama-prj --endpoint-args start:1,count:1 Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 { \"start\" : 1 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" , \"id\" : \"3a0e91a4-b79b-37c2-9df7-122247e8ed9c\" , \"createdAt\" : \"2023-08-15T05:56:19\" , \"taskActive\" : false , \"finishedAt\" : \"2023-08-15T05:56:42\" , \"details\" : { \"error\" : \"Archive missing web and/or code subdirectories\" , \"flowsError\" : null , \"projectMetadata\" : { \"projectName\" : \"testAuth\" , \"configs\" : null } }, \"baseDn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" } ] } View Agama Project By Name # You can get the details of an Agama project deployed in the Janssen Server by the project name. The command line for this operation is as below: Sample Command jans cli --operation-id get-agama-prj-by-name --url-suffix = \"agama-project-name\" Example: Sample Command jans cli --operation-id get-agama-prj-by-name --url-suffix = \"testAuth\" Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 { \"dn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" , \"id\" : \"3a0e91a4-b79b-37c2-9df7-122247e8ed9c\" , \"createdAt\" : 1687247278717 , \"taskActive\" : false , \"finishedAt\" : 1687247288646 , \"assets\" : null , \"details\" : { \"folders\" : null , \"libs\" : [], \"flowsError\" : { \"imShakil.co.basicAuth\" : null }, \"error\" : null , \"projectMetadata\" : { \"projectName\" : \"testAuth\" , \"author\" : \"imShakil\" , \"type\" : \"community\" , \"description\" : \"testing authentication with janssen server\" , \"version\" : \"1.0.0\" , \"configs\" : null } }, \"baseDn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" } Post Agama Project in Janssen # You can deploy the Agama project in the Janssen Server through the command line using the post-agama-prj operation. Here the agama-project-file is an archive file that holds the bundled Agama project and follows the .gama specification. Sample Command jans cli --operation-id post-agama-prj \\ --url-suffix = \"name:project-name\" --data agama-project-file Example: Let's upload a test project Zip file. This zip file contains the artifacts of an Agama project and follows the .gama specification. Assuming that the zip file has been downloaded in the folder at path /tmp/journey.zip , the command below will upload a new Agama project with specified name in the Janssen Server. Sample Command jans cli --operation-id = post-agama-prj \\ --url-suffix = \"name:Agama Lab Journey\" --data /tmp/journey.zip Sample Output { \"message\" : \"A deployment task for project Agama Lab Journey has been queued. Use the GET endpoint to poll status\" } Now the project should be available in the list of deployed projects . Retrieve Agama Project Configuration # To retrieve the Agama project configuration, use the get-agama-prj-configs operation. Sample Command jans cli --operation-id get-agama-prj-configs \\ --url-suffix = \"name:agama-project-name\" Update Agama Project # Let's update the configuration for project that we uploaded in the section above : Take the sample project configuration and keep it under /tmp/journey-configs.json . Make a few test changes to the configuration and run the command below to update the configuration: Command jans cli --operation-id = put-agama-prj \\ --url-suffix \"name:Agama Lab Journey\" --data /tmp/journey-configs.json Sample Output 1 2 3 4 5 6 7 8 { \"io.jans.agamaLab.registration\" : true , \"io.jans.agamaLab.main\" : true , \"io.jans.agamaLab.credsEnrollment.otp\" : true , \"io.jans.agamaLab.authenticator.super_gluu\" : true , \"io.jans.agamaLab.credsEnrollment.super_gluu\" : true , \"io.jans.agamaLab.githubAuthn\" : true } Delete Agama Project # To delete an Agama project by its name, use the delete-agama-prj operation. Sample Command jans cli --operation-id delete-agama-prj --url-suffix = \"agama-project-name\" Agama Flow Configuration # AgamaConfiguration task groups operations that help understand the correctness of the deployed Agama project configuration. Command jans cli --info AgamaConfiguration Sample Output 1 2 3 4 Operation ID: agama-syntax-check Description: Determine if the text passed is valid Agama code Parameters: qname: Agama Flow name [string] Agama Flow DSL Syntax # To check if a deployed Agama project is running into Agama DSL related errors, use the agama-syntax-check operation as below: Sample Command jans cli --operation-id agama-syntax-check \\ --url-suffix qname: \"fully-qualified-flow-name\" Example : Command jans cli --operation-id agama-syntax-check --url-suffix qname: \"imShakil.co.test\" Sample Output 1 2 3 4 5 6 7 { \"error\" : \"mismatched input 'newline' expecting 'Flow'\" , \"symbol\" : \"[@0,0:-1='newline',<9>,1:0]\" , \"line\" : 1 , \"column\" : 0 , \"message\" : \"Syntax error: mismatched input 'newline' expecting 'Flow'\\nSymbol: [@0,0:-1='newline',<9>,1:0]\\nLine: 1\\nColumn: 1\" } Using Text-based UI # In Janssen, You can deploy and customize an Agama project using the Text-Based UI also. You can start TUI using the command below: Command jans tui Agama Project Screen # Navigate to Auth Server -> Agama to open the Agama projects screen as shown in the image below. To get the list of currently added projects, bring the control to Search box (using the tab key), and press Enter . Type the search string to search for projects with matching names. Add a new project using Add a New Project button. It will open a dialogue where you can either deploy a local project or deploy an Agama Lab community project as shown in the image below. If you select the first option, it'll open the explore dialogue. Using this dialogue, navigate the file system and select the .gama archive for the new project. If you select the second option, it'ill collect a list of Agama Lab community projects from GitHub and display a selection list as shown in the image below. Agama Project Help Menu # TUI provides key-press commands to open various dialogues that help manage and configure Agama projects. All the key-press commands are listed in the help menu. Press F1 to bring up the help menu as shown in the screen below. Agama Project Detail Screen # Use the appropriate key-press command from help screen to bring up the project detail screen which is shown in the image below. The project details screen shows important details about the Agama project. In case the project deployment is facing an error, this screen also shows these errors and the corresponding flows. All the flows in the project are also listed by their fully qualified names. Fully qualified names are useful when invoking flows. The project details screen also shows the JSON configuration by navigating to and pressing the View Configuration button. Agama Project Configuration Screen # Use the appropriate key-press command from help screen to bring up the Agama project configuration screen which is shown in the image below. The screen allows the export and import of the configuration. The sample configuration can serve as a template. Export it into a file, then make the necessary changes to it and import it back to correctly configure the project. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring Agama projects. Endpoint details are published in the Swagger document .", "title": "Agama Project Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-project-configuration", "text": "Agama project configuration involves adding and removing Agama projects to Janssen Server along with configuring and troubleshooting these project deployments. The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the configuration steps Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the configuration steps Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the configuration steps", "title": "Agama project configuration"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the Agama project using the command line. To get the details of Janssen command line operations relevant to Agama projects, you can check the operations under Agama task using the command below: Command jans cli --info Agama It will show the details of the available operation-ids for Agama. Operation ID: get-agama-prj-by-name Description: Fetches deployed the Agama project based on the name. Parameters: name: Agama project name [string] Operation ID: post-agama-prj Description: Deploy an Agama project. Parameters: name: Agama project name [string] Operation ID: delete-agama-prj Description: Delete a deployed Agama project. Parameters: name: Agama project name [string] Operation ID: get-agama-prj-configs Description: Retrieve the list of configs based on name. Parameters: name: Agama project name [string] Operation ID: put-agama-prj Description: Update an Agama project. Parameters: name: Agama project name [string] Parameters: type: Description not found for this property additionalProperties: Description not found for this property Operation ID: get-agama-prj Description: Retrieve the list of projects deployed currently. Parameters: start: No description is provided for this parameter [integer] count: No description is provided for this parameter [integer] In the sections below, we will see how to configure and manage Agama projects via the command line using the above operations.", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#list-deployed-projects", "text": "Use the get-agama-prj operation to retrieve the list of deployed Agama projects: Command jans cli --operation-id get-agama-prj The output will list Agama projects that are added to this Janssen Server deployment. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=46546e9a-fed6-34d0-ba63-b615233b2115,ou=deployments,ou=agama,o=jans\" , \"id\" : \"46546e9a-fed6-34d0-ba63-b615233b2115\" , \"createdAt\" : \"2023-08-13T14:45:27\" , \"taskActive\" : false , \"finishedAt\" : \"2023-08-13T14:45:43\" , \"details\" : { \"error\" : \"There were problems processing one or more flows\" , \"flowsError\" : { \"mmrraju.np.test.me\" : null , \"mmrraju.test2.agama\" : null , \"mmrraju.u2f.me\" : \"Syntax error: mismatched input '<EOF>' expecting {'|', 'Log', 'Trigger', 'Call', 'RRF', 'When', 'Repeat', 'Iterate over', 'Match', 'Finish', 'RFAC', ALPHANUM, QNAME, DOTEXPR, DOTIDXEXPR, WS}\\nSymbol: [@9,43:42='<EOF>',<-1>,2:23]\\nLine: 2\\nColumn: 24\" }, \"projectMetadata\" : { \"projectName\" : \"user_pass_auth\" , \"author\" : \"mmrraju\" , \"type\" : \"community\" , \"description\" : \"This is password based authentication\" , \"version\" : \"1.0.34\" , \"configs\" : null } }, \"baseDn\" : \"jansId=46546e9a-fed6-34d0-ba63-b615233b2115,ou=deployments,ou=agama,o=jans\" } ] }", "title": "List Deployed Projects"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#endpoint-arguments", "text": "Endpoint arguments are parameters passed to an API or function to specify how and what data to retrieve or process. There are two endpoint arguments available to the get-agama-prj operation. start : Should be an integer value. It's an index value of the starting point of the list. count : Should be an integer value. Total entries number you want to display. For example, to fetch details of the project at index 1 only, use the command below. Command jans cli --operation-id get-agama-prj --endpoint-args start:1,count:1 Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 { \"start\" : 1 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" , \"id\" : \"3a0e91a4-b79b-37c2-9df7-122247e8ed9c\" , \"createdAt\" : \"2023-08-15T05:56:19\" , \"taskActive\" : false , \"finishedAt\" : \"2023-08-15T05:56:42\" , \"details\" : { \"error\" : \"Archive missing web and/or code subdirectories\" , \"flowsError\" : null , \"projectMetadata\" : { \"projectName\" : \"testAuth\" , \"configs\" : null } }, \"baseDn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" } ] }", "title": "Endpoint Arguments"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#view-agama-project-by-name", "text": "You can get the details of an Agama project deployed in the Janssen Server by the project name. The command line for this operation is as below: Sample Command jans cli --operation-id get-agama-prj-by-name --url-suffix = \"agama-project-name\" Example: Sample Command jans cli --operation-id get-agama-prj-by-name --url-suffix = \"testAuth\" Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 { \"dn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" , \"id\" : \"3a0e91a4-b79b-37c2-9df7-122247e8ed9c\" , \"createdAt\" : 1687247278717 , \"taskActive\" : false , \"finishedAt\" : 1687247288646 , \"assets\" : null , \"details\" : { \"folders\" : null , \"libs\" : [], \"flowsError\" : { \"imShakil.co.basicAuth\" : null }, \"error\" : null , \"projectMetadata\" : { \"projectName\" : \"testAuth\" , \"author\" : \"imShakil\" , \"type\" : \"community\" , \"description\" : \"testing authentication with janssen server\" , \"version\" : \"1.0.0\" , \"configs\" : null } }, \"baseDn\" : \"jansId=3a0e91a4-b79b-37c2-9df7-122247e8ed9c,ou=deployments,ou=agama,o=jans\" }", "title": "View Agama Project By Name"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#post-agama-project-in-janssen", "text": "You can deploy the Agama project in the Janssen Server through the command line using the post-agama-prj operation. Here the agama-project-file is an archive file that holds the bundled Agama project and follows the .gama specification. Sample Command jans cli --operation-id post-agama-prj \\ --url-suffix = \"name:project-name\" --data agama-project-file Example: Let's upload a test project Zip file. This zip file contains the artifacts of an Agama project and follows the .gama specification. Assuming that the zip file has been downloaded in the folder at path /tmp/journey.zip , the command below will upload a new Agama project with specified name in the Janssen Server. Sample Command jans cli --operation-id = post-agama-prj \\ --url-suffix = \"name:Agama Lab Journey\" --data /tmp/journey.zip Sample Output { \"message\" : \"A deployment task for project Agama Lab Journey has been queued. Use the GET endpoint to poll status\" } Now the project should be available in the list of deployed projects .", "title": "Post Agama Project in Janssen"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#retrieve-agama-project-configuration", "text": "To retrieve the Agama project configuration, use the get-agama-prj-configs operation. Sample Command jans cli --operation-id get-agama-prj-configs \\ --url-suffix = \"name:agama-project-name\"", "title": "Retrieve Agama Project Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#update-agama-project", "text": "Let's update the configuration for project that we uploaded in the section above : Take the sample project configuration and keep it under /tmp/journey-configs.json . Make a few test changes to the configuration and run the command below to update the configuration: Command jans cli --operation-id = put-agama-prj \\ --url-suffix \"name:Agama Lab Journey\" --data /tmp/journey-configs.json Sample Output 1 2 3 4 5 6 7 8 { \"io.jans.agamaLab.registration\" : true , \"io.jans.agamaLab.main\" : true , \"io.jans.agamaLab.credsEnrollment.otp\" : true , \"io.jans.agamaLab.authenticator.super_gluu\" : true , \"io.jans.agamaLab.credsEnrollment.super_gluu\" : true , \"io.jans.agamaLab.githubAuthn\" : true }", "title": "Update Agama Project"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#delete-agama-project", "text": "To delete an Agama project by its name, use the delete-agama-prj operation. Sample Command jans cli --operation-id delete-agama-prj --url-suffix = \"agama-project-name\"", "title": "Delete Agama Project"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-flow-configuration", "text": "AgamaConfiguration task groups operations that help understand the correctness of the deployed Agama project configuration. Command jans cli --info AgamaConfiguration Sample Output 1 2 3 4 Operation ID: agama-syntax-check Description: Determine if the text passed is valid Agama code Parameters: qname: Agama Flow name [string]", "title": "Agama Flow Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-flow-dsl-syntax", "text": "To check if a deployed Agama project is running into Agama DSL related errors, use the agama-syntax-check operation as below: Sample Command jans cli --operation-id agama-syntax-check \\ --url-suffix qname: \"fully-qualified-flow-name\" Example : Command jans cli --operation-id agama-syntax-check --url-suffix qname: \"imShakil.co.test\" Sample Output 1 2 3 4 5 6 7 { \"error\" : \"mismatched input 'newline' expecting 'Flow'\" , \"symbol\" : \"[@0,0:-1='newline',<9>,1:0]\" , \"line\" : 1 , \"column\" : 0 , \"message\" : \"Syntax error: mismatched input 'newline' expecting 'Flow'\\nSymbol: [@0,0:-1='newline',<9>,1:0]\\nLine: 1\\nColumn: 1\" }", "title": "Agama Flow DSL Syntax"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#using-text-based-ui", "text": "In Janssen, You can deploy and customize an Agama project using the Text-Based UI also. You can start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-project-screen", "text": "Navigate to Auth Server -> Agama to open the Agama projects screen as shown in the image below. To get the list of currently added projects, bring the control to Search box (using the tab key), and press Enter . Type the search string to search for projects with matching names. Add a new project using Add a New Project button. It will open a dialogue where you can either deploy a local project or deploy an Agama Lab community project as shown in the image below. If you select the first option, it'll open the explore dialogue. Using this dialogue, navigate the file system and select the .gama archive for the new project. If you select the second option, it'ill collect a list of Agama Lab community projects from GitHub and display a selection list as shown in the image below.", "title": "Agama Project Screen"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-project-help-menu", "text": "TUI provides key-press commands to open various dialogues that help manage and configure Agama projects. All the key-press commands are listed in the help menu. Press F1 to bring up the help menu as shown in the screen below.", "title": "Agama Project Help Menu"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-project-detail-screen", "text": "Use the appropriate key-press command from help screen to bring up the project detail screen which is shown in the image below. The project details screen shows important details about the Agama project. In case the project deployment is facing an error, this screen also shows these errors and the corresponding flows. All the flows in the project are also listed by their fully qualified names. Fully qualified names are useful when invoking flows. The project details screen also shows the JSON configuration by navigating to and pressing the View Configuration button.", "title": "Agama Project Detail Screen"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#agama-project-configuration-screen", "text": "Use the appropriate key-press command from help screen to bring up the Agama project configuration screen which is shown in the image below. The screen allows the export and import of the configuration. The sample configuration can serve as a template. Export it into a file, then make the necessary changes to it and import it back to correctly configure the project.", "title": "Agama Project Configuration Screen"}, {"location": "janssen-server/config-guide/auth-server-config/agama-project-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring Agama projects. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/", "tags": ["administration", "configuration", "attributes"], "text": "Attribute # First thing, let's get the information for Attribute : jans cli --info Attribute In return, we get a list of Operations ID as below: Operation ID: get-attributes Description: Gets a list of Gluu attributes. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-attributes Description: Updates an existing attribute Schema: JansAttribute Operation ID: post-attributes Description: Adds a new attribute Schema: JansAttribute Operation ID: get-attributes-by-inum Description: Gets an attribute based on inum Parameters: inum: Attribute Id [string] Operation ID: delete-attributes-by-inum Description: Deletes an attribute based on inum Parameters: inum: Attribute Id [string] Operation ID: patch-attributes-by-inum Description: Partially modify a JansAttribute Parameters: inum: Attribute Id [string] Schema: Array of PatchRequest To get sample schema type jans cli --schema <schma>, for example jans cli --schema PatchRequest We have discussed here about each of this operations ID with few examples to understand how these really works. Table of Contents # Attribute Get Attributes Creating an Attribute Updating an Attribute Get Attribute by inum Delete Attributes Patch Attributes Get Attributes # Prerequisite: Know how to use the Janssen CLI in command-line mode As we know, Attributes are individual pieces of user data, like uid or email , that are required by applications in order to identify a user and grant access to protect resources. The user attributes that are available in your Janssen Server can be found by using this operation-ID. If we look at the description below: Operation ID: get-attributes Description: Gets a list of Gluu attributes. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] To get all the attributes without any arguments, run the following command: jans cli --operation-id get-attributes To get attributes with passing the arguments, let's retrieve randomly limit:5: jans cli --operation-id get-attributes --endpoint-args limit:1 It will return only one attribute details randomly: Getting access token for scope https://jans.io/oauth/config/attributes.readonly Calling with params limit=1 { \"start\": 0, \"totalEntriesCount\": 71, \"entriesCount\": 1, \"entries\": [ { \"dn\": \"inum=29DA,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"29DA\", \"name\": \"inum\", \"displayName\": \"Inum\", \"description\": \"XRI i-number, persistent non-reassignable identifier\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"inum\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:inum\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.117\", \"urn\": \"urn:jans:dir:attribute-def:inum\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": false, \"whitePagesCanView\": false, \"baseDn\": \"inum=29DA,ou=attributes,o=jans\" } ] } To get attributes with pattern & status : jans cli --operation-id get-attributes --endpoint-args limit:3,pattern:profile,status:ACTIVE In return, we get a list of attribute that are matched with the given pattern and status : Please wait while retrieving data ... { \"start\": 0, \"totalEntriesCount\": 2, \"entriesCount\": 2, \"entries\": [ { \"dn\": \"inum=64A0,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"64A0\", \"name\": \"profile\", \"displayName\": \"Profile URL\", \"description\": \"URL of the End-User's profile page. The contents of this Web page SHOULD be about the End-User.\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"user\", \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"profile\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:profile\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.321\", \"urn\": \"http://openid.net/specs/openid-connect-core-1_0.html/StandardClaims/profile\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": true, \"whitePagesCanView\": false, \"baseDn\": \"inum=64A0,ou=attributes,o=jans\" }, { \"dn\": \"inum=EC3A,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"EC3A\", \"name\": \"picture\", \"displayName\": \"Picture URL\", \"description\": \"URL of the End-User's profile picture\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"user\", \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"picture\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:picture\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.322\", \"urn\": \"http://openid.net/specs/openid-connect-core-1_0.html/StandardClaims/picture\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": true, \"whitePagesCanView\": false, \"baseDn\": \"inum=EC3A,ou=attributes,o=jans\" } ] } Creating an Attribute # To create SSO for certain applications, you may need to add custom attributes to your Janssen Server. Custom attributes can be added by using this operation-ID. It has a schema file where it's defined: the properties it needs to be filled to create a new custom attribute. Operation ID: post-attributes Description: Adds a new attribute Schema: JansAttribute Before adding a new attribute, let's get sample schema : jans cli --schema JansAttribute > /tmp/attribute.json It will return as below: { \"dn\" : \"string\" , \"selected\" : false , \"inum\" : \"string\" , \"sourceAttribute\" : \"string\" , \"nameIdType\" : \"string\" , \"name\" : \"string\" , \"displayName\" : \"string\" , \"description\" : \"string\" , \"origin\" : \"string\" , \"dataType\" : \"certificate\" , \"editType\" : [ \"manager\" ], \"viewType\" : [ \"user\" ], \"usageType\" : [ \"openid\" ], \"claimName\" : \"string\" , \"seeAlso\" : \"string\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"string\" , \"saml2Uri\" : \"string\" , \"urn\" : \"string\" , \"scimCustomAttr\" : true , \"oxMultiValuedAttribute\" : true , \"jansHideOnDiscovery\" : true , \"custom\" : false , \"attributeValidation\" : { \"minLength\" : { \"type\" : \"integer\" , \"format\" : \"int32\" }, \"maxLength\" : { \"type\" : \"integer\" , \"format\" : \"int32\" }, \"regexp\" : { \"type\" : \"string\" } }, \"tooltip\" : \"string\" , \"whitePagesCanView\" : false , \"adminCanView\" : true , \"userCanAccess\" : false , \"userCanView\" : true , \"adminCanAccess\" : false , \"adminCanEdit\" : false , \"userCanEdit\" : true , \"baseDn\" : \"string\" } Modify it to update attribute name , display name , view type : nano /tmp/attribute.json Now, let's add this attribute using post-attributes : jans cli --operation-id post-attributes --data /tmp/attribute.json It will create a new attribute into the Attribute list with updated inum & dn : { \"dn\" : \"inum=0272b98e-0ead-43e9-94eb-4af9548af97d,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"0272b98e-0ead-43e9-94eb-4af9548af97d\" , \"nameIdType\" : \"string\" , \"name\" : \"testAttribute\" , \"displayName\" : \"testAttribute\" , \"description\" : \"testAttribute\" , \"dataType\" : \"certificate\" , \"editType\" : [ \"manager\" ], \"viewType\" : [ \"user\" ], \"usageType\" : [ \"openid\" ], \"status\" : \"inactive\" , \"scimCustomAttr\" : true , \"oxMultiValuedAttribute\" : true , \"jansHideOnDiscovery\" : true , \"custom\" : false , \"tooltip\" : \"string\" , \"adminCanAccess\" : false , \"adminCanView\" : false , \"adminCanEdit\" : false , \"userCanAccess\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"whitePagesCanView\" : false , \"baseDn\" : \"inum=0272b98e-0ead-43e9-94eb-4af9548af97d,ou=attributes,o=jans\" } Updating an Attribute # This operation-id can be used to update an existing attribute information. The Janssen Server administrator can make changes to attributes, such as changing their status to active/inactive by using this operation-ID. Let's look at the schema: jans cli --schema JansAttribute > /tmp/attrib.json You must see the similar schema while performed in post-attributes operation. To update an existing attribute, we have to ensure following properties in the schema file. In our case, I have modified the schema file as below: { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": true, \"name\": \"testAttribute\", \"display_name\": \"testAttribute\", \"description\": \"testing put-attribute\", \"data_type\": \"STRING\", \"status\": \"ACTIVE\", \"edit_type\": [\"ADMIN\", \"OWNER\"], \"view_type\": [\"ADMIN\", \"OWNER\", \"USER\"] } Now if we run the below command line: jans cli --operation-id put-attributes --data /tmp/attrb.json Getting access token for scope https://jans.io/oauth/config/attributes.write Server Response: { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": false, \"name\": \"testAttribute\", \"displayName\": \"testAttribute\", \"description\": \"testing put-attribute\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": null, \"editType\": [ \"ADMIN\", \"OWNER\" ], \"viewType\": [ \"ADMIN\", \"OWNER\", \"USER\" ], \"usageType\": null, \"claimName\": null, \"seeAlso\": null, \"saml1Uri\": null, \"saml2Uri\": null, \"urn\": null, \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null } It just replace the previous value with new one. Get Attribute by inum # As we know, There are a lot of attributes available in the Janssen Server including custom attributes as well. You may want to know details information for a single attribute uniquely identified by inum . Getting an attribute information by using its inum is pretty simple. jans cli --operation-id get-attributes-by-inum --url-suffix inum:attribute-iunm-value It will show all details information of the selected Attribute as below example. jans cli --operation-id get-attributes-by-inum --url-suffix inum:b691f2ab-a7db-4725-b85b-9961575b441f Getting access token for scope https://jans.io/oauth/config/attributes.readonly { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": false, \"name\": \"testAttribute\", \"displayName\": \"testAttribute\", \"description\": \"testing put-attribute\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": null, \"editType\": [ \"ADMIN\", \"OWNER\" ], \"viewType\": [ \"ADMIN\", \"OWNER\", \"USER\" ], \"usageType\": null, \"claimName\": null, \"seeAlso\": null, \"saml1Uri\": null, \"saml2Uri\": null, \"urn\": null, \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null } Delete Attributes # For any reason, If it needs to delete any attribute, you can do that simply using its inum value. See below example, just change the inum value with one that you want to delete. jans cli --operation-id delete-attributes-by-inum --url-suffix inum:b691f2ab-a7db-4725-b85b-9961575b441f Patch Attributes # This operation can also used for updating an existing attribute by using its inum value. Operation ID: patch-attributes-by-inum Description: Partially modify a JansAttribute. url-suffix: inum Schema: Array of PatchRequest If we look at the description, we see that there is a schema file. Let's get the schema file with below command: jans cli --schema PatchRequest > /tmp/patch.json # cat /tmp/patch.json { \"op\": \"add\", \"path\": \"string\", \"value\": {} } Let's modify this schema file to change the status of an attribute as below: In the above image, added two tasks. To know more about how we can modify this schema file to perform a specific task, follow this link: patch-request-schema Let's update an attribute by its inum value. In our case, inum : 6EEB. Before patching the selected attribute, you can check its properties using get-attributes-by-inum operation. Before patching the attribute, its properties are: { \"dn\": \"inum=6EEB,ou=attributes,o=jans\", \"inum\": \"6EEB\", \"selected\": false, \"name\": \"l\", \"displayName\": \"City\", \"description\": \"City\", \"dataType\": \"STRING\", \"status\": \"INACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": \"jansCustomPerson\", \"editType\": [ \"USER\", \"ADMIN\" ], \"viewType\": [ \"USER\", \"ADMIN\" ], \"usageType\": null, \"claimName\": \"locality\", \"seeAlso\": null, \"saml1Uri\": \"urn:mace:dir:attribute-def:l\", \"saml2Uri\": \"urn:oid:2.5.4.7\", \"urn\": \"urn:mace:dir:attribute-def:l\", \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null } According to the schema file, There should be two changes, status and jansHideOnDiscovery . Let's perform the operation: jans cli --operation-id patch-attributes-by-inum --url-suffix inum:6EEB --data /tmp/patch.json The updated attribute looks like: Getting access token for scope https://jans.io/oauth/config/attributes.write Server Response: { \"dn\": \"inum=6EEB,ou=attributes,o=jans\", \"inum\": \"6EEB\", \"selected\": false, \"name\": \"l\", \"displayName\": \"City\", \"description\": \"City\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": \"jansCustomPerson\", \"editType\": [ \"USER\", \"ADMIN\" ], \"viewType\": [ \"USER\", \"ADMIN\" ], \"usageType\": null, \"claimName\": \"locality\", \"seeAlso\": null, \"saml1Uri\": \"urn:mace:dir:attribute-def:l\", \"saml2Uri\": \"urn:oid:2.5.4.7\", \"urn\": \"urn:mace:dir:attribute-def:l\", \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": true } As you see, there are two changes.", "title": "Attribute"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#attribute", "text": "First thing, let's get the information for Attribute : jans cli --info Attribute In return, we get a list of Operations ID as below: Operation ID: get-attributes Description: Gets a list of Gluu attributes. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-attributes Description: Updates an existing attribute Schema: JansAttribute Operation ID: post-attributes Description: Adds a new attribute Schema: JansAttribute Operation ID: get-attributes-by-inum Description: Gets an attribute based on inum Parameters: inum: Attribute Id [string] Operation ID: delete-attributes-by-inum Description: Deletes an attribute based on inum Parameters: inum: Attribute Id [string] Operation ID: patch-attributes-by-inum Description: Partially modify a JansAttribute Parameters: inum: Attribute Id [string] Schema: Array of PatchRequest To get sample schema type jans cli --schema <schma>, for example jans cli --schema PatchRequest We have discussed here about each of this operations ID with few examples to understand how these really works.", "title": "Attribute"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#table-of-contents", "text": "Attribute Get Attributes Creating an Attribute Updating an Attribute Get Attribute by inum Delete Attributes Patch Attributes", "title": "Table of Contents"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#get-attributes", "text": "Prerequisite: Know how to use the Janssen CLI in command-line mode As we know, Attributes are individual pieces of user data, like uid or email , that are required by applications in order to identify a user and grant access to protect resources. The user attributes that are available in your Janssen Server can be found by using this operation-ID. If we look at the description below: Operation ID: get-attributes Description: Gets a list of Gluu attributes. Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] To get all the attributes without any arguments, run the following command: jans cli --operation-id get-attributes To get attributes with passing the arguments, let's retrieve randomly limit:5: jans cli --operation-id get-attributes --endpoint-args limit:1 It will return only one attribute details randomly: Getting access token for scope https://jans.io/oauth/config/attributes.readonly Calling with params limit=1 { \"start\": 0, \"totalEntriesCount\": 71, \"entriesCount\": 1, \"entries\": [ { \"dn\": \"inum=29DA,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"29DA\", \"name\": \"inum\", \"displayName\": \"Inum\", \"description\": \"XRI i-number, persistent non-reassignable identifier\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"inum\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:inum\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.117\", \"urn\": \"urn:jans:dir:attribute-def:inum\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": false, \"whitePagesCanView\": false, \"baseDn\": \"inum=29DA,ou=attributes,o=jans\" } ] } To get attributes with pattern & status : jans cli --operation-id get-attributes --endpoint-args limit:3,pattern:profile,status:ACTIVE In return, we get a list of attribute that are matched with the given pattern and status : Please wait while retrieving data ... { \"start\": 0, \"totalEntriesCount\": 2, \"entriesCount\": 2, \"entries\": [ { \"dn\": \"inum=64A0,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"64A0\", \"name\": \"profile\", \"displayName\": \"Profile URL\", \"description\": \"URL of the End-User's profile page. The contents of this Web page SHOULD be about the End-User.\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"user\", \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"profile\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:profile\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.321\", \"urn\": \"http://openid.net/specs/openid-connect-core-1_0.html/StandardClaims/profile\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": true, \"whitePagesCanView\": false, \"baseDn\": \"inum=64A0,ou=attributes,o=jans\" }, { \"dn\": \"inum=EC3A,ou=attributes,o=jans\", \"selected\": false, \"inum\": \"EC3A\", \"name\": \"picture\", \"displayName\": \"Picture URL\", \"description\": \"URL of the End-User's profile picture\", \"origin\": \"jansPerson\", \"dataType\": \"string\", \"editType\": [ \"user\", \"admin\" ], \"viewType\": [ \"user\", \"admin\" ], \"claimName\": \"picture\", \"status\": \"active\", \"saml1Uri\": \"urn:mace:dir:attribute-def:picture\", \"saml2Uri\": \"urn:oid:1.3.6.1.4.1.48710.1.3.322\", \"urn\": \"http://openid.net/specs/openid-connect-core-1_0.html/StandardClaims/picture\", \"oxMultiValuedAttribute\": false, \"custom\": false, \"adminCanAccess\": true, \"adminCanView\": true, \"adminCanEdit\": true, \"userCanAccess\": true, \"userCanView\": true, \"userCanEdit\": true, \"whitePagesCanView\": false, \"baseDn\": \"inum=EC3A,ou=attributes,o=jans\" } ] }", "title": "Get Attributes"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#creating-an-attribute", "text": "To create SSO for certain applications, you may need to add custom attributes to your Janssen Server. Custom attributes can be added by using this operation-ID. It has a schema file where it's defined: the properties it needs to be filled to create a new custom attribute. Operation ID: post-attributes Description: Adds a new attribute Schema: JansAttribute Before adding a new attribute, let's get sample schema : jans cli --schema JansAttribute > /tmp/attribute.json It will return as below: { \"dn\" : \"string\" , \"selected\" : false , \"inum\" : \"string\" , \"sourceAttribute\" : \"string\" , \"nameIdType\" : \"string\" , \"name\" : \"string\" , \"displayName\" : \"string\" , \"description\" : \"string\" , \"origin\" : \"string\" , \"dataType\" : \"certificate\" , \"editType\" : [ \"manager\" ], \"viewType\" : [ \"user\" ], \"usageType\" : [ \"openid\" ], \"claimName\" : \"string\" , \"seeAlso\" : \"string\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"string\" , \"saml2Uri\" : \"string\" , \"urn\" : \"string\" , \"scimCustomAttr\" : true , \"oxMultiValuedAttribute\" : true , \"jansHideOnDiscovery\" : true , \"custom\" : false , \"attributeValidation\" : { \"minLength\" : { \"type\" : \"integer\" , \"format\" : \"int32\" }, \"maxLength\" : { \"type\" : \"integer\" , \"format\" : \"int32\" }, \"regexp\" : { \"type\" : \"string\" } }, \"tooltip\" : \"string\" , \"whitePagesCanView\" : false , \"adminCanView\" : true , \"userCanAccess\" : false , \"userCanView\" : true , \"adminCanAccess\" : false , \"adminCanEdit\" : false , \"userCanEdit\" : true , \"baseDn\" : \"string\" } Modify it to update attribute name , display name , view type : nano /tmp/attribute.json Now, let's add this attribute using post-attributes : jans cli --operation-id post-attributes --data /tmp/attribute.json It will create a new attribute into the Attribute list with updated inum & dn : { \"dn\" : \"inum=0272b98e-0ead-43e9-94eb-4af9548af97d,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"0272b98e-0ead-43e9-94eb-4af9548af97d\" , \"nameIdType\" : \"string\" , \"name\" : \"testAttribute\" , \"displayName\" : \"testAttribute\" , \"description\" : \"testAttribute\" , \"dataType\" : \"certificate\" , \"editType\" : [ \"manager\" ], \"viewType\" : [ \"user\" ], \"usageType\" : [ \"openid\" ], \"status\" : \"inactive\" , \"scimCustomAttr\" : true , \"oxMultiValuedAttribute\" : true , \"jansHideOnDiscovery\" : true , \"custom\" : false , \"tooltip\" : \"string\" , \"adminCanAccess\" : false , \"adminCanView\" : false , \"adminCanEdit\" : false , \"userCanAccess\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"whitePagesCanView\" : false , \"baseDn\" : \"inum=0272b98e-0ead-43e9-94eb-4af9548af97d,ou=attributes,o=jans\" }", "title": "Creating an Attribute"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#updating-an-attribute", "text": "This operation-id can be used to update an existing attribute information. The Janssen Server administrator can make changes to attributes, such as changing their status to active/inactive by using this operation-ID. Let's look at the schema: jans cli --schema JansAttribute > /tmp/attrib.json You must see the similar schema while performed in post-attributes operation. To update an existing attribute, we have to ensure following properties in the schema file. In our case, I have modified the schema file as below: { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": true, \"name\": \"testAttribute\", \"display_name\": \"testAttribute\", \"description\": \"testing put-attribute\", \"data_type\": \"STRING\", \"status\": \"ACTIVE\", \"edit_type\": [\"ADMIN\", \"OWNER\"], \"view_type\": [\"ADMIN\", \"OWNER\", \"USER\"] } Now if we run the below command line: jans cli --operation-id put-attributes --data /tmp/attrb.json Getting access token for scope https://jans.io/oauth/config/attributes.write Server Response: { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": false, \"name\": \"testAttribute\", \"displayName\": \"testAttribute\", \"description\": \"testing put-attribute\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": null, \"editType\": [ \"ADMIN\", \"OWNER\" ], \"viewType\": [ \"ADMIN\", \"OWNER\", \"USER\" ], \"usageType\": null, \"claimName\": null, \"seeAlso\": null, \"saml1Uri\": null, \"saml2Uri\": null, \"urn\": null, \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null } It just replace the previous value with new one.", "title": "Updating an Attribute"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#get-attribute-by-inum", "text": "As we know, There are a lot of attributes available in the Janssen Server including custom attributes as well. You may want to know details information for a single attribute uniquely identified by inum . Getting an attribute information by using its inum is pretty simple. jans cli --operation-id get-attributes-by-inum --url-suffix inum:attribute-iunm-value It will show all details information of the selected Attribute as below example. jans cli --operation-id get-attributes-by-inum --url-suffix inum:b691f2ab-a7db-4725-b85b-9961575b441f Getting access token for scope https://jans.io/oauth/config/attributes.readonly { \"dn\": \"inum=b691f2ab-a7db-4725-b85b-9961575b441f,ou=attributes,o=jans\", \"inum\": \"b691f2ab-a7db-4725-b85b-9961575b441f\", \"selected\": false, \"name\": \"testAttribute\", \"displayName\": \"testAttribute\", \"description\": \"testing put-attribute\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": null, \"editType\": [ \"ADMIN\", \"OWNER\" ], \"viewType\": [ \"ADMIN\", \"OWNER\", \"USER\" ], \"usageType\": null, \"claimName\": null, \"seeAlso\": null, \"saml1Uri\": null, \"saml2Uri\": null, \"urn\": null, \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null }", "title": "Get Attribute by inum"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#delete-attributes", "text": "For any reason, If it needs to delete any attribute, you can do that simply using its inum value. See below example, just change the inum value with one that you want to delete. jans cli --operation-id delete-attributes-by-inum --url-suffix inum:b691f2ab-a7db-4725-b85b-9961575b441f", "title": "Delete Attributes"}, {"location": "janssen-server/config-guide/auth-server-config/attribute-configuration/#patch-attributes", "text": "This operation can also used for updating an existing attribute by using its inum value. Operation ID: patch-attributes-by-inum Description: Partially modify a JansAttribute. url-suffix: inum Schema: Array of PatchRequest If we look at the description, we see that there is a schema file. Let's get the schema file with below command: jans cli --schema PatchRequest > /tmp/patch.json # cat /tmp/patch.json { \"op\": \"add\", \"path\": \"string\", \"value\": {} } Let's modify this schema file to change the status of an attribute as below: In the above image, added two tasks. To know more about how we can modify this schema file to perform a specific task, follow this link: patch-request-schema Let's update an attribute by its inum value. In our case, inum : 6EEB. Before patching the selected attribute, you can check its properties using get-attributes-by-inum operation. Before patching the attribute, its properties are: { \"dn\": \"inum=6EEB,ou=attributes,o=jans\", \"inum\": \"6EEB\", \"selected\": false, \"name\": \"l\", \"displayName\": \"City\", \"description\": \"City\", \"dataType\": \"STRING\", \"status\": \"INACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": \"jansCustomPerson\", \"editType\": [ \"USER\", \"ADMIN\" ], \"viewType\": [ \"USER\", \"ADMIN\" ], \"usageType\": null, \"claimName\": \"locality\", \"seeAlso\": null, \"saml1Uri\": \"urn:mace:dir:attribute-def:l\", \"saml2Uri\": \"urn:oid:2.5.4.7\", \"urn\": \"urn:mace:dir:attribute-def:l\", \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": null } According to the schema file, There should be two changes, status and jansHideOnDiscovery . Let's perform the operation: jans cli --operation-id patch-attributes-by-inum --url-suffix inum:6EEB --data /tmp/patch.json The updated attribute looks like: Getting access token for scope https://jans.io/oauth/config/attributes.write Server Response: { \"dn\": \"inum=6EEB,ou=attributes,o=jans\", \"inum\": \"6EEB\", \"selected\": false, \"name\": \"l\", \"displayName\": \"City\", \"description\": \"City\", \"dataType\": \"STRING\", \"status\": \"ACTIVE\", \"lifetime\": null, \"sourceAttribute\": null, \"salt\": null, \"nameIdType\": null, \"origin\": \"jansCustomPerson\", \"editType\": [ \"USER\", \"ADMIN\" ], \"viewType\": [ \"USER\", \"ADMIN\" ], \"usageType\": null, \"claimName\": \"locality\", \"seeAlso\": null, \"saml1Uri\": \"urn:mace:dir:attribute-def:l\", \"saml2Uri\": \"urn:oid:2.5.4.7\", \"urn\": \"urn:mace:dir:attribute-def:l\", \"scimCustomAttr\": null, \"oxMultiValuedAttribute\": false, \"custom\": false, \"attributeValidation\": null, \"tooltip\": null, \"jansHideOnDiscovery\": true } As you see, there are two changes.", "title": "Patch Attributes"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/", "tags": ["administration", "configuration", "default authentication", "ACR", "authentication method"], "text": "Authentication Method Configuration # The Janssen Server allows administrators to set and manage the default authentication method for the authentication server. The Janssen Server provides multiple configuration tools to perform these tasks. Note Only one of the available authentication methods can be set as the default. While setting the Default authentication method, the Janssen Server checks if the same authentication is available and active. See script documentation to know how to enable/disable authentication methods using custom scripts. If the script is not active then the following error notification is returned by API. { \"code\": \"400\", \"message\": \"INVALID_ACR\", \"description\": \"Authentication script {acr} is not active\" } Also, to understand how Janssen Server picks the authentication method in the absence of the default authentication method, refer to ACR documentation Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # Operations to manage the default authentication method are grouped under the DefaultAuthenticationMethod task. To get information about those operations use the command below. Command jans cli --info DefaultAuthenticationMethod Output Operation ID: get-acrs Description: Gets default authentication method. Operation ID: put-acrs Description: Updates default authentication method. Schema: AuthenticationMethod To get sample schema type jans cli --schema <schma>, for example jans cli --schema /components/schemas/AuthenticationMethod Find Current Authentication Method # To get the current default authentication method use the command below. Command jans cli --operation-id get-acrs Sample Output { \"defaultAcr\" : \"simple_password_auth\" } Update Default Authentication Method # Let's update the Default Authentication Method using the Janssen CLI command line. To perform the put-acrs operation, we have to use its schema. To get its schema: Command jans cli --schema AuthenticationMethod > /tmp/patch-default-auth.json The schema can now be found in the patch-default-auth.json file. For your information, you can obtain the format of the AuthenticationMethod schema by running the aforementioned command without a file. Schema Format defaultAcr string you can also use the following command for AuthenticationMethod schema example. Command jans cli --schema-sample AuthenticationMethod Schema Example { \"defaultAcr\" : \"string\" } We need to modify the patch-default-auth.json file. We have seen that our default authentication method is simple_password_auth . We are going to update it with passport_saml authentication method. input { \"defaultAcr\" : \"passport_saml\" } Now let's trigger the operation using the above file. Command jans cli --operation-id put-acrs --data /tmp/patch-default-auth.json It will show the updated result. Sample Output { \"defaultAcr\" : \"passport_saml\" } Using Text-based UI # In Janssen, You can manage the default authentication method using the Text-Based UI also. You can start TUI using the command below: Command jans tui Find Current Default Authentication Method # Navigate to Auth Server -> Authn to open the Authn screen as shown in the image below. In Default ACR sub-tab, available authentication methods are listed as radio buttons. To update the default authentication method, bring the tab focus to the authentication method, and navigate to the new default method with Up and Down keys. To choose hit Space key. Navigate to Save button and hit Enter key Basic Authentication Method # This tab displays the basic, builtin, authentication method as shown in the image below. You can set basic as the default authentication method by selecting Default Authn Method , navigate to Save button and hit Enter key LDAP Servers As Authentication Method # In this tab you can add and modify LDAP Servers are to be used as the default authentication method. See below image To add a new LDAP server, navigate to Add Source LDAP Server button and hit Enter . A popup screen will be displayed as shown in the image below. Fill in the fields provided in the popup. Before saving LDAP server, it is recommended to test it by navigating Test button and hitting Enter . If the test is successful, chose Save button and hit Enter . If you want the current edited LDAP server as the default authentication method, select Default Authn Method before saving. Authentication Methods Enabled By Scripts # All enabled Person Authentication scripts are listed in this tab as below To edit Level and/or Properties of the authentication script, navigate to the script in the list by hitting tab key and hit Enter . You will see a popup like in the image below If the script you want to use as the default authentication method is not in the list, you should enable the script by navigating Scripts in the main tab. Find the script you want to enable and hit Enter , you will get a popup where you can select Enabled checkbox and Save it as shown in the image below: Configure Aliases For Authencation Methods # Authentication aliases are listed in this tab. You can modify aliases by navigating to the list and hitting Enter . If you want to add a new alias, choose Add Alias button and hit Enter Authentication Methods Enabled by Agama Flows # If you deployed an Agama project, ACR values for the project are displayed in this tab as shown below: Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Default Authentication Method. Endpoint details are published in the Swagger document .", "title": "Authentication Method Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#authentication-method-configuration", "text": "The Janssen Server allows administrators to set and manage the default authentication method for the authentication server. The Janssen Server provides multiple configuration tools to perform these tasks. Note Only one of the available authentication methods can be set as the default. While setting the Default authentication method, the Janssen Server checks if the same authentication is available and active. See script documentation to know how to enable/disable authentication methods using custom scripts. If the script is not active then the following error notification is returned by API. { \"code\": \"400\", \"message\": \"INVALID_ACR\", \"description\": \"Authentication script {acr} is not active\" } Also, to understand how Janssen Server picks the authentication method in the absence of the default authentication method, refer to ACR documentation Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Authentication Method Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#using-command-line", "text": "Operations to manage the default authentication method are grouped under the DefaultAuthenticationMethod task. To get information about those operations use the command below. Command jans cli --info DefaultAuthenticationMethod Output Operation ID: get-acrs Description: Gets default authentication method. Operation ID: put-acrs Description: Updates default authentication method. Schema: AuthenticationMethod To get sample schema type jans cli --schema <schma>, for example jans cli --schema /components/schemas/AuthenticationMethod", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#find-current-authentication-method", "text": "To get the current default authentication method use the command below. Command jans cli --operation-id get-acrs Sample Output { \"defaultAcr\" : \"simple_password_auth\" }", "title": "Find Current Authentication Method"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#update-default-authentication-method", "text": "Let's update the Default Authentication Method using the Janssen CLI command line. To perform the put-acrs operation, we have to use its schema. To get its schema: Command jans cli --schema AuthenticationMethod > /tmp/patch-default-auth.json The schema can now be found in the patch-default-auth.json file. For your information, you can obtain the format of the AuthenticationMethod schema by running the aforementioned command without a file. Schema Format defaultAcr string you can also use the following command for AuthenticationMethod schema example. Command jans cli --schema-sample AuthenticationMethod Schema Example { \"defaultAcr\" : \"string\" } We need to modify the patch-default-auth.json file. We have seen that our default authentication method is simple_password_auth . We are going to update it with passport_saml authentication method. input { \"defaultAcr\" : \"passport_saml\" } Now let's trigger the operation using the above file. Command jans cli --operation-id put-acrs --data /tmp/patch-default-auth.json It will show the updated result. Sample Output { \"defaultAcr\" : \"passport_saml\" }", "title": "Update Default Authentication Method"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#using-text-based-ui", "text": "In Janssen, You can manage the default authentication method using the Text-Based UI also. You can start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#find-current-default-authentication-method", "text": "Navigate to Auth Server -> Authn to open the Authn screen as shown in the image below. In Default ACR sub-tab, available authentication methods are listed as radio buttons. To update the default authentication method, bring the tab focus to the authentication method, and navigate to the new default method with Up and Down keys. To choose hit Space key. Navigate to Save button and hit Enter key", "title": "Find Current Default Authentication Method"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#basic-authentication-method", "text": "This tab displays the basic, builtin, authentication method as shown in the image below. You can set basic as the default authentication method by selecting Default Authn Method , navigate to Save button and hit Enter key", "title": "Basic Authentication Method"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#ldap-servers-as-authentication-method", "text": "In this tab you can add and modify LDAP Servers are to be used as the default authentication method. See below image To add a new LDAP server, navigate to Add Source LDAP Server button and hit Enter . A popup screen will be displayed as shown in the image below. Fill in the fields provided in the popup. Before saving LDAP server, it is recommended to test it by navigating Test button and hitting Enter . If the test is successful, chose Save button and hit Enter . If you want the current edited LDAP server as the default authentication method, select Default Authn Method before saving.", "title": "LDAP Servers As Authentication Method"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#authentication-methods-enabled-by-scripts", "text": "All enabled Person Authentication scripts are listed in this tab as below To edit Level and/or Properties of the authentication script, navigate to the script in the list by hitting tab key and hit Enter . You will see a popup like in the image below If the script you want to use as the default authentication method is not in the list, you should enable the script by navigating Scripts in the main tab. Find the script you want to enable and hit Enter , you will get a popup where you can select Enabled checkbox and Save it as shown in the image below:", "title": "Authentication Methods Enabled By Scripts"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#configure-aliases-for-authencation-methods", "text": "Authentication aliases are listed in this tab. You can modify aliases by navigating to the list and hitting Enter . If you want to add a new alias, choose Add Alias button and hit Enter", "title": "Configure Aliases For Authencation Methods"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#authentication-methods-enabled-by-agama-flows", "text": "If you deployed an Agama project, ACR values for the project are displayed in this tab as shown below:", "title": "Authentication Methods Enabled by Agama Flows"}, {"location": "janssen-server/config-guide/auth-server-config/authentication-method-config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Default Authentication Method. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/", "tags": ["administration", "configuration", "cache"], "text": "Cache Configuration # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Cache configuration is not possible in Text-based UI. Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # To get the details of Janssen command line operations relevant to the cache configuration, you can check the operations under CacheConfiguration using the command below: Command jans cli --info CacheConfiguration It prints below two operations: Output Operation ID: get-config-cache Description: Returns cache configuration. Operation ID: patch-config-cache Description: Patch cache configuration Schema: Array of JsonPatch To get sample schema type jans cli --schema <schema>, for example jans cli --schema JsonPatch Get Cache Configuration # You can get the current Cache Configuration of your Janssen Server by performing this operation. Command jans cli --operation-id get-config-cache It will show the Cache configuration details. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { \"cacheProviderType\" : \"NATIVE_PERSISTENCE\" , \"memcachedConfiguration\" : { \"servers\" : \"localhost:11211\" , \"maxOperationQueueLength\" : 100000 , \"bufferSize\" : 32768 , \"defaultPutExpiration\" : 60 , \"connectionFactoryType\" : \"DEFAULT\" }, \"inMemoryConfiguration\" : { \"defaultPutExpiration\" : 60 }, \"redisConfiguration\" : { \"redisProviderType\" : \"STANDALONE\" , \"servers\" : \"localhost:6379\" , \"defaultPutExpiration\" : 60 , \"useSSL\" : false , \"maxIdleConnections\" : 10 , \"maxTotalConnections\" : 500 , \"connectionTimeout\" : 3000 , \"soTimeout\" : 3000 , \"maxRetryAttempts\" : 5 }, \"nativePersistenceConfiguration\" : { \"defaultPutExpiration\" : 60 , \"defaultCleanupBatchSize\" : 10000 , \"deleteExpiredOnGetRequest\" : false , \"disableAttemptUpdateBeforeInsert\" : false } } Patch Cache Configuration # You may need to update Cache configuration, In that case patch-config-cache can be used to modify the cache configuration. Operation ID: patch-config-cache Description: Patch cache configuration Schema: Array of JsonPatch To get sample schema type jans cli --schema <schema>, for example jans cli --schema JsonPatch The patch-config-cache operation uses the JSON Patch schema to describe the configuration change. Refer here to know more about schema. For instance, to perform a replace operation at memcachedConfiguration/bufferSize and change it from 32768 to 32788 , the JSON Patch data would look like below: Input [ { \"op\" : \"replace\" , \"path\" : \"memcachedConfiguration/bufferSize\" , \"value\" : \"32788\" } ] Store the above JSON Patch data in a file, for instance, /tmp/patch-cache.json Using the above file, perform the operation as below: Sample Command jans cli --operation-id patch-config-cache --data /tmp/patch-cache.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { \"cacheProviderType\" : \"NATIVE_PERSISTENCE\" , \"memcachedConfiguration\" : { \"servers\" : \"localhost:11211\" , \"maxOperationQueueLength\" : 100000 , \"bufferSize\" : 32788 , \"defaultPutExpiration\" : 60 , \"connectionFactoryType\" : \"DEFAULT\" }, \"inMemoryConfiguration\" : { \"defaultPutExpiration\" : 60 }, \"redisConfiguration\" : { \"redisProviderType\" : \"STANDALONE\" , \"servers\" : \"localhost:6379\" , \"defaultPutExpiration\" : 60 , \"useSSL\" : false , \"maxIdleConnections\" : 10 , \"maxTotalConnections\" : 500 , \"connectionTimeout\" : 3000 , \"soTimeout\" : 3000 , \"maxRetryAttempts\" : 5 }, \"nativePersistenceConfiguration\" : { \"defaultPutExpiration\" : 60 , \"defaultCleanupBatchSize\" : 10000 , \"deleteExpiredOnGetRequest\" : false , \"disableAttemptUpdateBeforeInsert\" : false } } Quick Patch Operation # In case you need to do a quick patch operation, you can do that also. For example, let's say we would like to replace defaultPutExpiration value from nativePersistenceConfiguration . We can do that simply by the following command line: Command jans cli --operation-id patch-config-cache \\ --patch-replace nativePersistenceConfiguration/defaultPutExpiration:90 It will change the value with the given one. There are few options to do such quick patch operations. Please check them out from here . Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring Cache. Endpoint details are published in the Swagger document .", "title": "Cache Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#cache-configuration", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Cache configuration is not possible in Text-based UI. Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Cache Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#using-command-line", "text": "To get the details of Janssen command line operations relevant to the cache configuration, you can check the operations under CacheConfiguration using the command below: Command jans cli --info CacheConfiguration It prints below two operations: Output Operation ID: get-config-cache Description: Returns cache configuration. Operation ID: patch-config-cache Description: Patch cache configuration Schema: Array of JsonPatch To get sample schema type jans cli --schema <schema>, for example jans cli --schema JsonPatch", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#get-cache-configuration", "text": "You can get the current Cache Configuration of your Janssen Server by performing this operation. Command jans cli --operation-id get-config-cache It will show the Cache configuration details. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { \"cacheProviderType\" : \"NATIVE_PERSISTENCE\" , \"memcachedConfiguration\" : { \"servers\" : \"localhost:11211\" , \"maxOperationQueueLength\" : 100000 , \"bufferSize\" : 32768 , \"defaultPutExpiration\" : 60 , \"connectionFactoryType\" : \"DEFAULT\" }, \"inMemoryConfiguration\" : { \"defaultPutExpiration\" : 60 }, \"redisConfiguration\" : { \"redisProviderType\" : \"STANDALONE\" , \"servers\" : \"localhost:6379\" , \"defaultPutExpiration\" : 60 , \"useSSL\" : false , \"maxIdleConnections\" : 10 , \"maxTotalConnections\" : 500 , \"connectionTimeout\" : 3000 , \"soTimeout\" : 3000 , \"maxRetryAttempts\" : 5 }, \"nativePersistenceConfiguration\" : { \"defaultPutExpiration\" : 60 , \"defaultCleanupBatchSize\" : 10000 , \"deleteExpiredOnGetRequest\" : false , \"disableAttemptUpdateBeforeInsert\" : false } }", "title": "Get Cache Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#patch-cache-configuration", "text": "You may need to update Cache configuration, In that case patch-config-cache can be used to modify the cache configuration. Operation ID: patch-config-cache Description: Patch cache configuration Schema: Array of JsonPatch To get sample schema type jans cli --schema <schema>, for example jans cli --schema JsonPatch The patch-config-cache operation uses the JSON Patch schema to describe the configuration change. Refer here to know more about schema. For instance, to perform a replace operation at memcachedConfiguration/bufferSize and change it from 32768 to 32788 , the JSON Patch data would look like below: Input [ { \"op\" : \"replace\" , \"path\" : \"memcachedConfiguration/bufferSize\" , \"value\" : \"32788\" } ] Store the above JSON Patch data in a file, for instance, /tmp/patch-cache.json Using the above file, perform the operation as below: Sample Command jans cli --operation-id patch-config-cache --data /tmp/patch-cache.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { \"cacheProviderType\" : \"NATIVE_PERSISTENCE\" , \"memcachedConfiguration\" : { \"servers\" : \"localhost:11211\" , \"maxOperationQueueLength\" : 100000 , \"bufferSize\" : 32788 , \"defaultPutExpiration\" : 60 , \"connectionFactoryType\" : \"DEFAULT\" }, \"inMemoryConfiguration\" : { \"defaultPutExpiration\" : 60 }, \"redisConfiguration\" : { \"redisProviderType\" : \"STANDALONE\" , \"servers\" : \"localhost:6379\" , \"defaultPutExpiration\" : 60 , \"useSSL\" : false , \"maxIdleConnections\" : 10 , \"maxTotalConnections\" : 500 , \"connectionTimeout\" : 3000 , \"soTimeout\" : 3000 , \"maxRetryAttempts\" : 5 }, \"nativePersistenceConfiguration\" : { \"defaultPutExpiration\" : 60 , \"defaultCleanupBatchSize\" : 10000 , \"deleteExpiredOnGetRequest\" : false , \"disableAttemptUpdateBeforeInsert\" : false } }", "title": "Patch Cache Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#quick-patch-operation", "text": "In case you need to do a quick patch operation, you can do that also. For example, let's say we would like to replace defaultPutExpiration value from nativePersistenceConfiguration . We can do that simply by the following command line: Command jans cli --operation-id patch-config-cache \\ --patch-replace nativePersistenceConfiguration/defaultPutExpiration:90 It will change the value with the given one. There are few options to do such quick patch operations. Please check them out from here .", "title": "Quick Patch Operation"}, {"location": "janssen-server/config-guide/auth-server-config/cache-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring Cache. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/", "tags": ["administration", "configuration", "jans-auth-server"], "text": "Janssen Authorization Server # Prerequisite: Know how to use the Janssen CLI in command-line mode To get info about Jans Authorization Server operations: jans cli --info ConfigurationProperties Operation ID: get-properties Description: Gets all Jans authorization server configuration properties. Operation ID: patch-properties Description: Partially modifies Jans authorization server AppConfiguration properties. Schema: Array of JsonPatch Operation ID: get-properties-persistence Description: Returns persistence type configured for Jans authorization server. To get sample schema type jans cli --schema <schma>, for example jans cli --schema JsonPatch Jans Authorization server has two operations id to get/modify its properties. Table of Contents # Janssen Authorization Server Table of Contents Get All Jans Auth Server Configuration Properties Partially Modify Jans Auth Server Configuration Properties Get Persistence type for Jans Auth Get All Jans Auth Server Configuration Properties # It returns all the information of the Jans Authorization server. jans cli --operation-id get-properties ``` You will get output like below ```json { \"issuer\": \"https://example.jans.io\", \"baseEndpoint\": \"https://example.jans.io/jans-auth/restv1\", \"authorizationEndpoint\": \"https://example.jans.io/jans-auth/restv1/authorize\", \"authorizationChallengeEndpoint\":\"https://example.jans.io/jans-auth/restv1/authorize-challenge\", \"tokenEndpoint\": \"https://example.jans.io/jans-auth/restv1/token\", \"tokenRevocationEndpoint\": \"https://example.jans.io/jans-auth/restv1/revoke\", \"userInfoEndpoint\": \"https://example.jans.io/jans-auth/restv1/userinfo\", \"clientInfoEndpoint\": \"https://example.jans.io/jans-auth/restv1/clientinfo\", \"checkSessionIFrame\": \"https://example.jans.io/jans-auth/opiframe.htm\", \"endSessionEndpoint\": \"https://example.jans.io/jans-auth/restv1/end_session\", \"jwksUri\": \"https://example.jans.io/jans-auth/restv1/jwks\", \"registrationEndpoint\": \"https://example.jans.io/jans-auth/restv1/register\", \"openIdDiscoveryEndpoint\": \"https://example.jans.io/.well-known/webfinger\", \"openIdConfigurationEndpoint\": \"https://example.jans.io/.well-known/openid-configuration\", \"idGenerationEndpoint\": \"https://example.jans.io/jans-auth/restv1/id\", \"introspectionEndpoint\": \"https://example.jans.io/jans-auth/restv1/introspection\", \"parEndpoint\": \"https://example.jans.io/jans-auth/restv1/par\", \"requirePar\": false, \"deviceAuthzEndpoint\": \"https://example.jans.io/jans-auth/restv1/device_authorization\", \"requireRequestObjectEncryption\": false, \"requirePkce\": false, \"allowAllValueForRevokeEndpoint\": false, \"sectorIdentifierCacheLifetimeInMinutes\": 1440, \"umaConfigurationEndpoint\": \"https://example.jans.io/jans-auth/restv1/uma2-configuration\", \"umaRptAsJwt\": false, \"umaRptLifetime\": 3600, \"umaTicketLifetime\": 3600, \"umaPctLifetime\": 1728000, \"umaResourceLifetime\": 1728000, \"umaAddScopesAutomatically\": true, \"umaValidateClaimToken\": false, \"umaGrantAccessIfNoPolicies\": false, \"umaRestrictResourceToAssociatedClient\": false, \"statTimerIntervalInSeconds\": 0, \"statAuthorizationScope\": \"jans_stat\", \"allowSpontaneousScopes\": false, \"spontaneousScopeLifetime\": 86400, \"openidSubAttribute\": \"inum\", \"publicSubjectIdentifierPerClientEnabled\": true, \"subjectIdentifiersPerClientSupported\": [ \"mail\", \"uid\" ], \"responseTypesSupported\": [ [ \"code\", \"id_token\" ], [ \"code\", \"token\" ], [ \"code\" ], [ \"token\", \"id_token\" ], [ \"token\" ], [ \"code\", \"token\", \"id_token\" ], [ \"id_token\" ] ], \"responseModesSupported\": [ \"form_post.jwt\", \"form_post\", \"fragment\", \"query.jwt\", \"fragment.jwt\", \"jwt\", \"query\" ], \"grantTypesSupported\": [ \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"implicit\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"urn:ietf:params:oauth:grant-type:device_code\", \"client_credentials\", \"refresh_token\", \"authorization_code\", \"password\", \"tx_token\" ], \"subjectTypesSupported\": [ \"public\", \"pairwise\" ], \"defaultSubjectType\": \"pairwise\", \"authorizationSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorizationEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"authorizationEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"userInfoSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"userInfoEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"userInfoEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"idTokenSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"idTokenEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"idTokenEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"accessTokenSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"forceSignedRequestObject\": false, \"requestObjectSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"requestObjectEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"requestObjectEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"tokenEndpointAuthMethodsSupported\": [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tokenEndpointAuthSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"displayValuesSupported\": [ \"page\", \"popup\" ], \"claimTypesSupported\": [ \"normal\" ], \"jwksAlgorithmsSupported\": [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"PS256\", \"PS384\", \"PS512\", \"RSA1_5\", \"RSA-OAEP\" ], \"serviceDocumentation\": \"http://jans.org/docs\", \"claimsLocalesSupported\": [ \"en\" ], \"idTokenTokenBindingCnfValuesSupported\": [ \"tbh\" ], \"uiLocalesSupported\": [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"claimsParameterSupported\": false, \"requestParameterSupported\": true, \"requestUriParameterSupported\": true, \"requestUriHashVerificationEnabled\": false, \"requireRequestUriRegistration\": false, \"requestUriBlockList\": [ \"localhost\", \"127.0.0.1\" ], \"opPolicyUri\": \"https://example.jans.io/opPolicy\", \"opTosUri\": \"https://example.jans.io/tos\", \"authorizationCodeLifetime\": 60, \"refreshTokenLifetime\": 14400, \"txTokenLifetime\": 180, \"idTokenLifetime\": 3600, \"idTokenFilterClaimsBasedOnAccessToken\": false, \"accessTokenLifetime\": 300, \"cleanServiceInterval\": 60, \"cleanServiceBatchChunkSize\": 10000, \"keyRegenerationEnabled\": true, \"keyRegenerationInterval\": 48, \"defaultSignatureAlgorithm\": \"RS256\", \"jansOpenIdConnectVersion\": \"openidconnect-1.0\", \"jansId\": \"https://example.jans.io/oxid/service/jans/inum\", \"dynamicRegistrationExpirationTime\": -1, \"dynamicRegistrationPersistClientAuthorizations\": true, \"trustedClientEnabled\": true, \"skipAuthorizationForOpenIdScopeAndPairwiseId\": false, \"dynamicRegistrationScopesParamEnabled\": true, \"dynamicRegistrationPasswordGrantTypeEnabled\": false, \"personCustomObjectClassList\": [ \"jansCustomPerson\", \"jansPerson\" ], \"persistIdToken\": false, \"persistRefreshToken\": true, \"allowPostLogoutRedirectWithoutValidation\": false, \"invalidateSessionCookiesAfterAuthorizationFlow\": false, \"returnClientSecretOnRead\": true, \"rotateClientRegistrationAccessTokenOnUsage\": false, \"rejectJwtWithNoneAlg\": true, \"expirationNotificatorEnabled\": false, \"useNestedJwtDuringEncryption\": true, \"expirationNotificatorMapSizeLimit\": 100000, \"expirationNotificatorIntervalInSeconds\": 600, \"redirectUrisRegexEnabled\": true, \"useHighestLevelScriptIfAcrScriptNotFound\": false, \"authenticationFiltersEnabled\": false, \"clientAuthenticationFiltersEnabled\": false, \"clientRegDefaultToCodeFlowWithRefresh\": true, \"grantTypesAndResponseTypesAutofixEnabled\": false, \"authenticationFilters\": [ { \"filter\": \"(&(mail=*{0}*)(inum={1}))\", \"bind\": false, \"baseDn\": \"ou=people,o=jans\" }, { \"filter\": \"uid={0}\", \"bind\": true, \"bindPasswordAttribute\": \"pwd\", \"baseDn\": \"ou=people,o=jans\" } ], \"clientAuthenticationFilters\": [ { \"filter\": \"myCustomAttr1={0}\", \"baseDn\": \"ou=clients,o=jans\" } ], \"corsConfigurationFilters\": [ { \"filterName\": \"CorsFilter\", \"corsEnabled\": true, \"corsAllowedOrigins\": \"*\", \"corsAllowedMethods\": \"GET,POST,HEAD,OPTIONS\", \"corsAllowedHeaders\": \"Origin,Authorization,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers\", \"corsSupportCredentials\": true, \"corsLoggingEnabled\": false, \"corsPreflightMaxAge\": 1800, \"corsRequestDecorate\": true } ], \"sessionIdUnusedLifetime\": 86400, \"sessionIdUnauthenticatedUnusedLifetime\": 7200, \"sessionIdPersistOnPromptNone\": true, \"sessionIdRequestParameterEnabled\": false, \"changeSessionIdOnAuthentication\": true, \"sessionIdPersistInCache\": false, \"includeSidInResponse\": false, \"disablePromptLogin\": false, \"disablePromptConsent\": false, \"sessionIdLifetime\": 86400, \"sessionIdCookieLifetime\": 86400, \"configurationUpdateInterval\": 3600, \"enableClientGrantTypeUpdate\": true, \"grantTypesSupportedByDynamicRegistration\": [ \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"implicit\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"urn:ietf:params:oauth:grant-type:device_code\", \"client_credentials\", \"refresh_token\", \"authorization_code\", \"tx_token\" ], \"metricReporterInterval\": 300, \"metricReporterKeepDataDays\": 15, \"pairwiseIdType\": \"algorithmic\", \"pairwiseCalculationKey\": \"9jwJNNXd9mMua666QDhfEKGcR\", \"pairwiseCalculationSalt\": \"aUn2q1HDtsUXtmTNovNeN1QTk\", \"shareSubjectIdBetweenClientsWithSameSectorId\": true, \"webKeysStorage\": \"keystore\", \"dnName\": \"CN=Jans Auth CA Certificates\", \"keyStoreFile\": \"/etc/certs/jans-auth-keys.pkcs12\", \"keyStoreSecret\": \"S63ogThoRsEf\", \"keySelectionStrategy\": \"OLDER\", \"keySignWithSameKeyButDiffAlg\": false, \"introspectionAccessTokenMustHaveUmaProtectionScope\": false, \"introspectionAccessTokenMustHaveIntrospectionScope\": false, \"introspectionSkipAuthorization\": false, \"endSessionWithAccessToken\": false, \"clientWhiteList\": [ \"*\" ], \"clientBlackList\": [ \"*.attacker.com/*\" ], \"legacyIdTokenClaims\": false, \"customHeadersWithAuthorizationResponse\": true, \"frontChannelLogoutSessionSupported\": true, \"loggingLevel\": \"INFO\", \"loggingLayout\": \"text\", \"updateUserLastLogonTime\": false, \"updateClientAccessTime\": false, \"logClientIdOnClientAuthentication\": true, \"logClientNameOnClientAuthentication\": false, \"disableJdkLogger\": true, \"authorizationRequestCustomAllowedParameters\": [ { \"paramName\": \"customParam3\", \"returnInResponse\": false }, { \"paramName\": \"customParam4\", \"returnInResponse\": true }, { \"paramName\": \"customParam5\", \"returnInResponse\": true }, { \"paramName\": \"customParam1\", \"returnInResponse\": false }, { \"paramName\": \"customParam2\", \"returnInResponse\": false } ], \"openidScopeBackwardCompatibility\": false, \"disableU2fEndpoint\": false, \"rotateDeviceSecret\": false, \"returnDeviceSecretFromAuthzEndpoint\": false, \"dcrSignatureValidationEnabled\": false, \"dcrAuthorizationWithClientCredentials\": false, \"dcrAuthorizationWithMTLS\": false, \"useLocalCache\": true, \"fapiCompatibility\": false, \"forceIdTokenHintPresence\": false, \"rejectEndSessionIfIdTokenExpired\": false, \"allowEndSessionWithUnmatchedSid\": false, \"forceOfflineAccessScopeToEnableRefreshToken\": true, \"errorReasonEnabled\": false, \"removeRefreshTokensForClientOnLogout\": true, \"skipRefreshTokenDuringRefreshing\": false, \"refreshTokenExtendLifetimeOnRotation\": false, \"checkUserPresenceOnRefreshToken\": false, \"consentGatheringScriptBackwardCompatibility\": false, \"introspectionScriptBackwardCompatibility\": false, \"introspectionResponseScopesBackwardCompatibility\": false, \"softwareStatementValidationType\": \"script\", \"authenticationProtectionConfiguration\": { \"attemptExpiration\": 15, \"maximumAllowedAttemptsWithoutDelay\": 4, \"delayTime\": 2, \"bruteForceProtectionEnabled\": false }, \"errorHandlingMethod\": \"remote\", \"keepAuthenticatorAttributesOnAcrChange\": false, \"deviceAuthzRequestExpiresIn\": 1800, \"deviceAuthzTokenPollInterval\": 5, \"deviceAuthzResponseTypeToProcessAuthz\": \"code\", \"backchannelRedirectUri\": \"https://example.jans.io/jans-auth/ciba/home.htm\", \"backchannelAuthenticationEndpoint\": \"https://example.jans.io/jans-auth/restv1/bc-authorize\", \"backchannelDeviceRegistrationEndpoint\": \"https://example.jans.io/jans-auth/restv1/bc-deviceRegistration\", \"backchannelTokenDeliveryModesSupported\": [ \"poll\", \"ping\", \"push\" ], \"backchannelUserCodeParameterSupported\": false, \"backchannelBindingMessagePattern\": \"^[a-zA-Z0-9]{4,8}$\", \"backchannelAuthenticationResponseExpiresIn\": 3600, \"backchannelAuthenticationResponseInterval\": 2, \"backchannelLoginHintClaims\": [ \"inum\", \"uid\", \"mail\" ], \"cibaEndUserNotificationConfig\": {}, \"backchannelRequestsProcessorJobIntervalSec\": 5, \"backchannelRequestsProcessorJobChunkSize\": 100, \"cibaGrantLifeExtraTimeSec\": 180, \"cibaMaxExpirationTimeAllowedSec\": 1800, \"dpopSigningAlgValuesSupported\": [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"dpopTimeframe\": 5, \"dpopJtiCacheTime\": 3600, \"allowIdTokenWithoutImplicitGrantType\": false, \"discoveryCacheLifetimeInMinutes\": 60, \"discoveryDenyKeys\": [ \"id_generation_endpoint\", \"auth_level_mapping\", \"scope_to_claims_mapping\", \"op_policy_uri\" ], \"httpLoggingEnabled\": false, \"agamaConfiguration\": { \"enabled\": false, \"rootDir\": \"/opt/jans/jetty/jans-auth/agama\", \"templatesPath\": \"/ftl\", \"scriptsPath\": \"/scripts\", \"serializerType\": \"KRYO\", \"maxItemsLoggedInCollections\": 9, \"pageMismatchErrorPage\": \"mismatch.ftlh\", \"interruptionErrorPage\": \"timeout.ftlh\", \"crashErrorPage\": \"crash.ftlh\", \"finishedFlowPage\": \"finished.ftlh\", \"bridgeScriptPage\": \"agama.xhtml\", \"defaultResponseHeaders\": { \"Cache-Control\": \"max-age=0, no-store\" } }, \"ssaConfiguration\": { \"ssaEndpoint\": \"https://example.jans.io/jans-auth/restv1/ssa\", \"ssaSigningAlg\": \"RS256\", \"ssaExpirationInDays\": 30 }, \"blockWebviewAuthorizationEnabled\": false, \"dateFormatterPatterns\": { \"birthdate\": \"yyyy-MM-dd\" }, \"httpLoggingResponseBodyContent\": false, \"fapi\": false, \"allResponseTypesSupported\": [ \"code\", \"id_token\", \"token\" ] } Partially Modify Jans Auth Server Configuration Properties # Operation ID: patch-properties Description: Partially modifies Jans authorization server AppConfiguration properties. Schema: Array of /components/schemas/PatchRequest To get sample shema type jans cli --schema <schma>, for example jans cli --schema /components/schemas/PatchRequest Let's look at the schema first: jans cli --schema /components/schemas/PatchRequest > /tmp/patch-jans-auth.json It will create a .json file in /tmp with schema. Let's modify this schema: nano /tmp/patch-jans-auth.json This schema has three properties; op , path & value . Let's perform a replace operation at cibaEnabled to change it from false to true . So, the .json file will look like this: [ { \"op\": \"replace\", \"path\": \"cibaEnabled\", \"value\": true } ] Don't forget to use square brackets ( [] ). Otherwise, it won't work. Now, let's do the operation. jans cli --operation-id patch-properties --data /tmp/patch-jans-auth.json If you run the following command line, you must see that cibaEnabled is true : Get Persistence type for Jans Auth Configuration # You can get the persistence details for jans auth server. jans cli --operation-id get-properties-persistence Default persistence type is MySQL . Please wait while retrieving data ... { \"persistenceType\": \"sql\" }", "title": "Auth Server Property Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/#janssen-authorization-server", "text": "Prerequisite: Know how to use the Janssen CLI in command-line mode To get info about Jans Authorization Server operations: jans cli --info ConfigurationProperties Operation ID: get-properties Description: Gets all Jans authorization server configuration properties. Operation ID: patch-properties Description: Partially modifies Jans authorization server AppConfiguration properties. Schema: Array of JsonPatch Operation ID: get-properties-persistence Description: Returns persistence type configured for Jans authorization server. To get sample schema type jans cli --schema <schma>, for example jans cli --schema JsonPatch Jans Authorization server has two operations id to get/modify its properties.", "title": "Janssen Authorization Server"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/#table-of-contents", "text": "Janssen Authorization Server Table of Contents Get All Jans Auth Server Configuration Properties Partially Modify Jans Auth Server Configuration Properties Get Persistence type for Jans Auth", "title": "Table of Contents"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/#get-all-jans-auth-server-configuration-properties", "text": "It returns all the information of the Jans Authorization server. jans cli --operation-id get-properties ``` You will get output like below ```json { \"issuer\": \"https://example.jans.io\", \"baseEndpoint\": \"https://example.jans.io/jans-auth/restv1\", \"authorizationEndpoint\": \"https://example.jans.io/jans-auth/restv1/authorize\", \"authorizationChallengeEndpoint\":\"https://example.jans.io/jans-auth/restv1/authorize-challenge\", \"tokenEndpoint\": \"https://example.jans.io/jans-auth/restv1/token\", \"tokenRevocationEndpoint\": \"https://example.jans.io/jans-auth/restv1/revoke\", \"userInfoEndpoint\": \"https://example.jans.io/jans-auth/restv1/userinfo\", \"clientInfoEndpoint\": \"https://example.jans.io/jans-auth/restv1/clientinfo\", \"checkSessionIFrame\": \"https://example.jans.io/jans-auth/opiframe.htm\", \"endSessionEndpoint\": \"https://example.jans.io/jans-auth/restv1/end_session\", \"jwksUri\": \"https://example.jans.io/jans-auth/restv1/jwks\", \"registrationEndpoint\": \"https://example.jans.io/jans-auth/restv1/register\", \"openIdDiscoveryEndpoint\": \"https://example.jans.io/.well-known/webfinger\", \"openIdConfigurationEndpoint\": \"https://example.jans.io/.well-known/openid-configuration\", \"idGenerationEndpoint\": \"https://example.jans.io/jans-auth/restv1/id\", \"introspectionEndpoint\": \"https://example.jans.io/jans-auth/restv1/introspection\", \"parEndpoint\": \"https://example.jans.io/jans-auth/restv1/par\", \"requirePar\": false, \"deviceAuthzEndpoint\": \"https://example.jans.io/jans-auth/restv1/device_authorization\", \"requireRequestObjectEncryption\": false, \"requirePkce\": false, \"allowAllValueForRevokeEndpoint\": false, \"sectorIdentifierCacheLifetimeInMinutes\": 1440, \"umaConfigurationEndpoint\": \"https://example.jans.io/jans-auth/restv1/uma2-configuration\", \"umaRptAsJwt\": false, \"umaRptLifetime\": 3600, \"umaTicketLifetime\": 3600, \"umaPctLifetime\": 1728000, \"umaResourceLifetime\": 1728000, \"umaAddScopesAutomatically\": true, \"umaValidateClaimToken\": false, \"umaGrantAccessIfNoPolicies\": false, \"umaRestrictResourceToAssociatedClient\": false, \"statTimerIntervalInSeconds\": 0, \"statAuthorizationScope\": \"jans_stat\", \"allowSpontaneousScopes\": false, \"spontaneousScopeLifetime\": 86400, \"openidSubAttribute\": \"inum\", \"publicSubjectIdentifierPerClientEnabled\": true, \"subjectIdentifiersPerClientSupported\": [ \"mail\", \"uid\" ], \"responseTypesSupported\": [ [ \"code\", \"id_token\" ], [ \"code\", \"token\" ], [ \"code\" ], [ \"token\", \"id_token\" ], [ \"token\" ], [ \"code\", \"token\", \"id_token\" ], [ \"id_token\" ] ], \"responseModesSupported\": [ \"form_post.jwt\", \"form_post\", \"fragment\", \"query.jwt\", \"fragment.jwt\", \"jwt\", \"query\" ], \"grantTypesSupported\": [ \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"implicit\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"urn:ietf:params:oauth:grant-type:device_code\", \"client_credentials\", \"refresh_token\", \"authorization_code\", \"password\", \"tx_token\" ], \"subjectTypesSupported\": [ \"public\", \"pairwise\" ], \"defaultSubjectType\": \"pairwise\", \"authorizationSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"authorizationEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"authorizationEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"userInfoSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"userInfoEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"userInfoEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"idTokenSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"idTokenEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"idTokenEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"accessTokenSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"forceSignedRequestObject\": false, \"requestObjectSigningAlgValuesSupported\": [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"requestObjectEncryptionAlgValuesSupported\": [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"requestObjectEncryptionEncValuesSupported\": [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"tokenEndpointAuthMethodsSupported\": [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tokenEndpointAuthSigningAlgValuesSupported\": [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"displayValuesSupported\": [ \"page\", \"popup\" ], \"claimTypesSupported\": [ \"normal\" ], \"jwksAlgorithmsSupported\": [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"PS256\", \"PS384\", \"PS512\", \"RSA1_5\", \"RSA-OAEP\" ], \"serviceDocumentation\": \"http://jans.org/docs\", \"claimsLocalesSupported\": [ \"en\" ], \"idTokenTokenBindingCnfValuesSupported\": [ \"tbh\" ], \"uiLocalesSupported\": [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"claimsParameterSupported\": false, \"requestParameterSupported\": true, \"requestUriParameterSupported\": true, \"requestUriHashVerificationEnabled\": false, \"requireRequestUriRegistration\": false, \"requestUriBlockList\": [ \"localhost\", \"127.0.0.1\" ], \"opPolicyUri\": \"https://example.jans.io/opPolicy\", \"opTosUri\": \"https://example.jans.io/tos\", \"authorizationCodeLifetime\": 60, \"refreshTokenLifetime\": 14400, \"txTokenLifetime\": 180, \"idTokenLifetime\": 3600, \"idTokenFilterClaimsBasedOnAccessToken\": false, \"accessTokenLifetime\": 300, \"cleanServiceInterval\": 60, \"cleanServiceBatchChunkSize\": 10000, \"keyRegenerationEnabled\": true, \"keyRegenerationInterval\": 48, \"defaultSignatureAlgorithm\": \"RS256\", \"jansOpenIdConnectVersion\": \"openidconnect-1.0\", \"jansId\": \"https://example.jans.io/oxid/service/jans/inum\", \"dynamicRegistrationExpirationTime\": -1, \"dynamicRegistrationPersistClientAuthorizations\": true, \"trustedClientEnabled\": true, \"skipAuthorizationForOpenIdScopeAndPairwiseId\": false, \"dynamicRegistrationScopesParamEnabled\": true, \"dynamicRegistrationPasswordGrantTypeEnabled\": false, \"personCustomObjectClassList\": [ \"jansCustomPerson\", \"jansPerson\" ], \"persistIdToken\": false, \"persistRefreshToken\": true, \"allowPostLogoutRedirectWithoutValidation\": false, \"invalidateSessionCookiesAfterAuthorizationFlow\": false, \"returnClientSecretOnRead\": true, \"rotateClientRegistrationAccessTokenOnUsage\": false, \"rejectJwtWithNoneAlg\": true, \"expirationNotificatorEnabled\": false, \"useNestedJwtDuringEncryption\": true, \"expirationNotificatorMapSizeLimit\": 100000, \"expirationNotificatorIntervalInSeconds\": 600, \"redirectUrisRegexEnabled\": true, \"useHighestLevelScriptIfAcrScriptNotFound\": false, \"authenticationFiltersEnabled\": false, \"clientAuthenticationFiltersEnabled\": false, \"clientRegDefaultToCodeFlowWithRefresh\": true, \"grantTypesAndResponseTypesAutofixEnabled\": false, \"authenticationFilters\": [ { \"filter\": \"(&(mail=*{0}*)(inum={1}))\", \"bind\": false, \"baseDn\": \"ou=people,o=jans\" }, { \"filter\": \"uid={0}\", \"bind\": true, \"bindPasswordAttribute\": \"pwd\", \"baseDn\": \"ou=people,o=jans\" } ], \"clientAuthenticationFilters\": [ { \"filter\": \"myCustomAttr1={0}\", \"baseDn\": \"ou=clients,o=jans\" } ], \"corsConfigurationFilters\": [ { \"filterName\": \"CorsFilter\", \"corsEnabled\": true, \"corsAllowedOrigins\": \"*\", \"corsAllowedMethods\": \"GET,POST,HEAD,OPTIONS\", \"corsAllowedHeaders\": \"Origin,Authorization,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers\", \"corsSupportCredentials\": true, \"corsLoggingEnabled\": false, \"corsPreflightMaxAge\": 1800, \"corsRequestDecorate\": true } ], \"sessionIdUnusedLifetime\": 86400, \"sessionIdUnauthenticatedUnusedLifetime\": 7200, \"sessionIdPersistOnPromptNone\": true, \"sessionIdRequestParameterEnabled\": false, \"changeSessionIdOnAuthentication\": true, \"sessionIdPersistInCache\": false, \"includeSidInResponse\": false, \"disablePromptLogin\": false, \"disablePromptConsent\": false, \"sessionIdLifetime\": 86400, \"sessionIdCookieLifetime\": 86400, \"configurationUpdateInterval\": 3600, \"enableClientGrantTypeUpdate\": true, \"grantTypesSupportedByDynamicRegistration\": [ \"urn:ietf:params:oauth:grant-type:uma-ticket\", \"implicit\", \"urn:ietf:params:oauth:grant-type:token-exchange\", \"urn:ietf:params:oauth:grant-type:device_code\", \"client_credentials\", \"refresh_token\", \"authorization_code\", \"tx_token\" ], \"metricReporterInterval\": 300, \"metricReporterKeepDataDays\": 15, \"pairwiseIdType\": \"algorithmic\", \"pairwiseCalculationKey\": \"9jwJNNXd9mMua666QDhfEKGcR\", \"pairwiseCalculationSalt\": \"aUn2q1HDtsUXtmTNovNeN1QTk\", \"shareSubjectIdBetweenClientsWithSameSectorId\": true, \"webKeysStorage\": \"keystore\", \"dnName\": \"CN=Jans Auth CA Certificates\", \"keyStoreFile\": \"/etc/certs/jans-auth-keys.pkcs12\", \"keyStoreSecret\": \"S63ogThoRsEf\", \"keySelectionStrategy\": \"OLDER\", \"keySignWithSameKeyButDiffAlg\": false, \"introspectionAccessTokenMustHaveUmaProtectionScope\": false, \"introspectionAccessTokenMustHaveIntrospectionScope\": false, \"introspectionSkipAuthorization\": false, \"endSessionWithAccessToken\": false, \"clientWhiteList\": [ \"*\" ], \"clientBlackList\": [ \"*.attacker.com/*\" ], \"legacyIdTokenClaims\": false, \"customHeadersWithAuthorizationResponse\": true, \"frontChannelLogoutSessionSupported\": true, \"loggingLevel\": \"INFO\", \"loggingLayout\": \"text\", \"updateUserLastLogonTime\": false, \"updateClientAccessTime\": false, \"logClientIdOnClientAuthentication\": true, \"logClientNameOnClientAuthentication\": false, \"disableJdkLogger\": true, \"authorizationRequestCustomAllowedParameters\": [ { \"paramName\": \"customParam3\", \"returnInResponse\": false }, { \"paramName\": \"customParam4\", \"returnInResponse\": true }, { \"paramName\": \"customParam5\", \"returnInResponse\": true }, { \"paramName\": \"customParam1\", \"returnInResponse\": false }, { \"paramName\": \"customParam2\", \"returnInResponse\": false } ], \"openidScopeBackwardCompatibility\": false, \"disableU2fEndpoint\": false, \"rotateDeviceSecret\": false, \"returnDeviceSecretFromAuthzEndpoint\": false, \"dcrSignatureValidationEnabled\": false, \"dcrAuthorizationWithClientCredentials\": false, \"dcrAuthorizationWithMTLS\": false, \"useLocalCache\": true, \"fapiCompatibility\": false, \"forceIdTokenHintPresence\": false, \"rejectEndSessionIfIdTokenExpired\": false, \"allowEndSessionWithUnmatchedSid\": false, \"forceOfflineAccessScopeToEnableRefreshToken\": true, \"errorReasonEnabled\": false, \"removeRefreshTokensForClientOnLogout\": true, \"skipRefreshTokenDuringRefreshing\": false, \"refreshTokenExtendLifetimeOnRotation\": false, \"checkUserPresenceOnRefreshToken\": false, \"consentGatheringScriptBackwardCompatibility\": false, \"introspectionScriptBackwardCompatibility\": false, \"introspectionResponseScopesBackwardCompatibility\": false, \"softwareStatementValidationType\": \"script\", \"authenticationProtectionConfiguration\": { \"attemptExpiration\": 15, \"maximumAllowedAttemptsWithoutDelay\": 4, \"delayTime\": 2, \"bruteForceProtectionEnabled\": false }, \"errorHandlingMethod\": \"remote\", \"keepAuthenticatorAttributesOnAcrChange\": false, \"deviceAuthzRequestExpiresIn\": 1800, \"deviceAuthzTokenPollInterval\": 5, \"deviceAuthzResponseTypeToProcessAuthz\": \"code\", \"backchannelRedirectUri\": \"https://example.jans.io/jans-auth/ciba/home.htm\", \"backchannelAuthenticationEndpoint\": \"https://example.jans.io/jans-auth/restv1/bc-authorize\", \"backchannelDeviceRegistrationEndpoint\": \"https://example.jans.io/jans-auth/restv1/bc-deviceRegistration\", \"backchannelTokenDeliveryModesSupported\": [ \"poll\", \"ping\", \"push\" ], \"backchannelUserCodeParameterSupported\": false, \"backchannelBindingMessagePattern\": \"^[a-zA-Z0-9]{4,8}$\", \"backchannelAuthenticationResponseExpiresIn\": 3600, \"backchannelAuthenticationResponseInterval\": 2, \"backchannelLoginHintClaims\": [ \"inum\", \"uid\", \"mail\" ], \"cibaEndUserNotificationConfig\": {}, \"backchannelRequestsProcessorJobIntervalSec\": 5, \"backchannelRequestsProcessorJobChunkSize\": 100, \"cibaGrantLifeExtraTimeSec\": 180, \"cibaMaxExpirationTimeAllowedSec\": 1800, \"dpopSigningAlgValuesSupported\": [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"dpopTimeframe\": 5, \"dpopJtiCacheTime\": 3600, \"allowIdTokenWithoutImplicitGrantType\": false, \"discoveryCacheLifetimeInMinutes\": 60, \"discoveryDenyKeys\": [ \"id_generation_endpoint\", \"auth_level_mapping\", \"scope_to_claims_mapping\", \"op_policy_uri\" ], \"httpLoggingEnabled\": false, \"agamaConfiguration\": { \"enabled\": false, \"rootDir\": \"/opt/jans/jetty/jans-auth/agama\", \"templatesPath\": \"/ftl\", \"scriptsPath\": \"/scripts\", \"serializerType\": \"KRYO\", \"maxItemsLoggedInCollections\": 9, \"pageMismatchErrorPage\": \"mismatch.ftlh\", \"interruptionErrorPage\": \"timeout.ftlh\", \"crashErrorPage\": \"crash.ftlh\", \"finishedFlowPage\": \"finished.ftlh\", \"bridgeScriptPage\": \"agama.xhtml\", \"defaultResponseHeaders\": { \"Cache-Control\": \"max-age=0, no-store\" } }, \"ssaConfiguration\": { \"ssaEndpoint\": \"https://example.jans.io/jans-auth/restv1/ssa\", \"ssaSigningAlg\": \"RS256\", \"ssaExpirationInDays\": 30 }, \"blockWebviewAuthorizationEnabled\": false, \"dateFormatterPatterns\": { \"birthdate\": \"yyyy-MM-dd\" }, \"httpLoggingResponseBodyContent\": false, \"fapi\": false, \"allResponseTypesSupported\": [ \"code\", \"id_token\", \"token\" ] }", "title": "Get All Jans Auth Server Configuration Properties"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/#partially-modify-jans-auth-server-configuration-properties", "text": "Operation ID: patch-properties Description: Partially modifies Jans authorization server AppConfiguration properties. Schema: Array of /components/schemas/PatchRequest To get sample shema type jans cli --schema <schma>, for example jans cli --schema /components/schemas/PatchRequest Let's look at the schema first: jans cli --schema /components/schemas/PatchRequest > /tmp/patch-jans-auth.json It will create a .json file in /tmp with schema. Let's modify this schema: nano /tmp/patch-jans-auth.json This schema has three properties; op , path & value . Let's perform a replace operation at cibaEnabled to change it from false to true . So, the .json file will look like this: [ { \"op\": \"replace\", \"path\": \"cibaEnabled\", \"value\": true } ] Don't forget to use square brackets ( [] ). Otherwise, it won't work. Now, let's do the operation. jans cli --operation-id patch-properties --data /tmp/patch-jans-auth.json If you run the following command line, you must see that cibaEnabled is true :", "title": "Partially Modify Jans Auth Server Configuration Properties"}, {"location": "janssen-server/config-guide/auth-server-config/jans-authorization-server-config/#get-persistence-type-for-jans-auth-configuration", "text": "You can get the persistence details for jans auth server. jans cli --operation-id get-properties-persistence Default persistence type is MySQL . Please wait while retrieving data ... { \"persistenceType\": \"sql\" }", "title": "Get Persistence type for Jans Auth Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/", "tags": ["administration", "configuration", "JWK", "json web keys", "JWKS"], "text": "JSON Web Key (JWK) # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and manage the JSON Web keys using the command Line. To get the details of Janssen command line operations relevant to JSON Web Key, you can check the operations under ConfigurationJwkJsonWebKeyJwk task using the command below: Command jans cli --info ConfigurationJwkJsonWebKeyJwk Sample Output Operation ID: get-jwk-by-kid Description: Get a JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Operation ID: delete-config-jwk-kid Description: Delete a JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Operation ID: patch-config-jwk-kid Description: Patch a specific JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Schema: Array of JsonPatch Operation ID: get-config-jwks Description: Gets list of JSON Web Key (JWK) used by server Operation ID: put-config-jwks Description: Replaces JSON Web Keys Schema: WebKeysConfiguration Operation ID: patch-config-jwks Description: Patches JSON Web Keys Schema: Array of JsonPatch Operation ID: post-config-jwks-key Description: Configuration \u2013 JWK - JSON Web Key (JWK) Schema: JSONWebKey To get sample schema type jans cli --schema <schema>, for example jans cli --schema JSONWebKey Get Configurations list of JWKs # We can get list of all configurations of the jwk configuration using a command like this: Command jans cli --operation-id get-config-jwks It will return all the jwk configuration information as below: Sample Output { \"keys\" : [ { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-384\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_fed19dd0-7139-4ed8-ad43-43322b7eeaea_sig_rs384\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAKLBm5p06uGv/lXT4tKLgjsS5kosfHb1rgO50fdLAFRoMA0GCSqGSIb3DQEBDAUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkIt6G/MDIyfp1uTERxFYoY1nGuq3FhZG7xdPYi7eHoyM+PAbq+8rKeIRcJWJi37TazbqqLViGbejaD6rRxOihzoMPo1LtBuqGGw8m6fI1UJlvnt1NHd+du3Q6065WufL+nXn2Osmg962TF+gSvExgxr+HFeAgjP/kyG99dzSv4mUFbikegK8Dql1K36fZ427vDQ7mGRrR1vBsbMPqW5d9huXhl+iy11AOtYNNcfRDu47Hzae5Srzp32si36+Da/dEwntuMXnK7BwxDp/BGoOuWLPFoVctH6PDoIYzXUiTbj+XiQ8zFgPydt+x/2ZEGyq61Ewebjkpj9b0g+yHk/2aQIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQEMBQADggEBAHnfO3jItuXdSr5Js3kj/7kI1OElwcU4fco53ThSilbtq6FBOk5GzonaZOHFQayzjo3Qp5qe/uShSknFQ+sjEmhGTVPiQFssNTXxEnEw1WrTvEc/09I9oTNg9jitppn1z4/QT/wP0X3erRIjBQvFe4ov1wL/atjs5Mg8KRHqGttze5xN1pY3r0hrUiIxYiA7F5DUigGD4hYGGXKXymr0SgEoMZQx9Duxn8wxtX5l3fcC0FA53vn/4ZDd/ikhQRqTyz/C7ffHsVcOxnlWd3pm37+W9swGhkb9EaKRg2gJOdA5+Vw62tJA4Gp8WOIeMrRiXvtn2AVks5nyG7oiWt0ldYk=\" ], \"name\" : \"Connect RS384 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS384\" , \"n\" : \"kIt6G_MDIyfp1uTERxFYoY1nGuq3FhZG7xdPYi7eHoyM-PAbq-8rKeIRcJWJi37TazbqqLViGbejaD6rRxOihzoMPo1LtBuqGGw8m6fI1UJlvnt1NHd-du3Q6065WufL-nXn2Osmg962TF-gSvExgxr-HFeAgjP_kyG99dzSv4mUFbikegK8Dql1K36fZ427vDQ7mGRrR1vBsbMPqW5d9huXhl-iy11AOtYNNcfRDu47Hzae5Srzp32si36-Da_dEwntuMXnK7BwxDp_BGoOuWLPFoVctH6PDoIYzXUiTbj-XiQ8zFgPydt-x_2ZEGyq61Ewebjkpj9b0g-yHk_2aQ\" } ] Adds new JSON Web key (JWK) # To add a new key, we can use post-config-jwks-key operation id. As shown in the output for --info command, the post-config-jwks-key operation requires data to be sent according to JSONWebKey schema. To see the schema, use the command below: Command jans cli --schema JSONWebKey The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample JSONWebKey Using the schema and the example above, we have added below key data to the file /tmp/jwk.json . Input \"name\" : \"Connect RSA-OAEP Encryption Key 2\" , \"descr\" : \"Encryption Key 2: Elliptic Curve Diffie-Hellman Ephemeral Static key agreement using Concat KDF\" , \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"crv\" : \"\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ] , \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" , \"x\" : null, \"y\" : null Now let's post this key to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-config-jwks-key --data /tmp/jwk.json Replace JSON Web Key Set # To replace the current JWKS configuration, use the put-config-jwks operation. This operation replaces the current set of JWK with the provided set. Operation ID: put-config-jwks Description: Replaces JSON Web Keys Schema: WebKeysConfiguration To get the schema file: Command jans cli --schema WebKeysConfiguration As suggested in the schema, we have to provide an array of keys in a json file containing key-value pairs. The properties in the key are defined by the JWK specification RFC 7517 , and for algorithm-specific properties, in RFC 7518 . Properties # name Description kid It's a unique identifier for the key configuration. kty It's used to define the type of the specific cryptographic algorithms use This parameter identifies the intended use of the public key. sig for signature and enc for encryption alg The specific algorithm used with the key crv exp The exponent for the RSA public key. x5c The x5c parameter contains a chain of one or more PKIX certificates RFC5280 n The modulus for the RSA public key . e The \"e\" (exponent) parameter contains the exponent value for the RSA public key . It is represented as a Base64urlUInt-encoded value. x The \"x\" (x coordinate) parameter contains the x coordinate for the Elliptic Curve point . y The \"y\" (y coordinate) parameter contains the y coordinate for the Elliptic Curve point . Let's update the json file to create a new key configuration. Input Key { \"keys\" : [{ \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"crv\" : \"\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" , \"x\" : null , \"y\" : null }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ /ja nssen - server/co nf ig - guide/au t h - server - co nf ig/jso n - web - key - co nf ig \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" } ] } Now let's put the new keys into the Janssen server. Command jans cli --operation-id put-config-jwks --data /tmp/path-jwk.json Please remember that this operation replaces all JWKs in the Janssen server with new ones. So, in this case, if you want to keep old JWKs, you have to put them as well in the input file. Output Sample { \"keys\" : [ { \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"enc\" , \"key_ops_type\" : [], \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"exp\" : 1622245655163 , \"alg\" : \"RSA-OAEP\" , \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" } ] } Now use the Get Configurations list of JWKs to confirm the replacement. Get a JSON Web Key Based on kid # With get-jwk-by-kid operation-id, we can get any specific jwk matched with kid . If we know the kid , we can simply use the below command: Command jans cli --operation-id get-jwk/janssen-server/config-guide/auth-server-config/json-web-key-config-by-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 It returns the details as below: Sample Output { \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" } Patch JSON Web Key (JWK) by kid # Using patch-config-jwks operation, we can modify JSON Web Keys partially for its properties. Operation ID: patch-config-jwks Description: Patches JSON Web Keys Schema: Array of JsonPatch To use this operation, specify the id of the key that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property use from enc to sig . Input [ { \"op\" : \"replace\" , \"path\" : \"use\" , \"value\" : \"sig\" } ] Now let's do the operation with the command line. Command jans cli --operation-id patch-config-jwk-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 --data /tmp/schema.json Updated Json Web Key: Key { \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"sig\" , \"alg\" : \"RSA-OAEP\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" } We see it has replaced the value of the use property from enc to sig . Please read about patch method , You can get some idea of how this patch method works to modify particular properties of any task. Delete Json Web Key using kid # It's pretty simple to delete json web key using its kid . The command line is: Command jans cli --operation-id delete-config-jwk-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 It will delete the jwk if it matches with the given kid . Using Text-based UI # In Janssen, you can view the JSON web keys using the Text-Based UI also. You can start TUI using the command below: Command jans tui JSON Web Key (JWK) Screen # Navigate to Auth Server -> Keys to open the JSON Web Key screen as shown in the image below. After clicking on Get keys , You can view Key's list on this page. You cannot perform any operations in text-based UI. Only you can perform operations using the command line. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Json Web key. Endpoint details are published in the Swagger document .", "title": "JSON Web Key"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#json-web-key-jwk", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "JSON Web Key (JWK)"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#using-command-line", "text": "In the Janssen Server, you can deploy and manage the JSON Web keys using the command Line. To get the details of Janssen command line operations relevant to JSON Web Key, you can check the operations under ConfigurationJwkJsonWebKeyJwk task using the command below: Command jans cli --info ConfigurationJwkJsonWebKeyJwk Sample Output Operation ID: get-jwk-by-kid Description: Get a JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Operation ID: delete-config-jwk-kid Description: Delete a JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Operation ID: patch-config-jwk-kid Description: Patch a specific JSON Web Key based on kid Parameters: kid: The unique identifier for the key [string] Schema: Array of JsonPatch Operation ID: get-config-jwks Description: Gets list of JSON Web Key (JWK) used by server Operation ID: put-config-jwks Description: Replaces JSON Web Keys Schema: WebKeysConfiguration Operation ID: patch-config-jwks Description: Patches JSON Web Keys Schema: Array of JsonPatch Operation ID: post-config-jwks-key Description: Configuration \u2013 JWK - JSON Web Key (JWK) Schema: JSONWebKey To get sample schema type jans cli --schema <schema>, for example jans cli --schema JSONWebKey", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#get-configurations-list-of-jwks", "text": "We can get list of all configurations of the jwk configuration using a command like this: Command jans cli --operation-id get-config-jwks It will return all the jwk configuration information as below: Sample Output { \"keys\" : [ { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-384\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_fed19dd0-7139-4ed8-ad43-43322b7eeaea_sig_rs384\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAKLBm5p06uGv/lXT4tKLgjsS5kosfHb1rgO50fdLAFRoMA0GCSqGSIb3DQEBDAUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkIt6G/MDIyfp1uTERxFYoY1nGuq3FhZG7xdPYi7eHoyM+PAbq+8rKeIRcJWJi37TazbqqLViGbejaD6rRxOihzoMPo1LtBuqGGw8m6fI1UJlvnt1NHd+du3Q6065WufL+nXn2Osmg962TF+gSvExgxr+HFeAgjP/kyG99dzSv4mUFbikegK8Dql1K36fZ427vDQ7mGRrR1vBsbMPqW5d9huXhl+iy11AOtYNNcfRDu47Hzae5Srzp32si36+Da/dEwntuMXnK7BwxDp/BGoOuWLPFoVctH6PDoIYzXUiTbj+XiQ8zFgPydt+x/2ZEGyq61Ewebjkpj9b0g+yHk/2aQIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQEMBQADggEBAHnfO3jItuXdSr5Js3kj/7kI1OElwcU4fco53ThSilbtq6FBOk5GzonaZOHFQayzjo3Qp5qe/uShSknFQ+sjEmhGTVPiQFssNTXxEnEw1WrTvEc/09I9oTNg9jitppn1z4/QT/wP0X3erRIjBQvFe4ov1wL/atjs5Mg8KRHqGttze5xN1pY3r0hrUiIxYiA7F5DUigGD4hYGGXKXymr0SgEoMZQx9Duxn8wxtX5l3fcC0FA53vn/4ZDd/ikhQRqTyz/C7ffHsVcOxnlWd3pm37+W9swGhkb9EaKRg2gJOdA5+Vw62tJA4Gp8WOIeMrRiXvtn2AVks5nyG7oiWt0ldYk=\" ], \"name\" : \"Connect RS384 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS384\" , \"n\" : \"kIt6G_MDIyfp1uTERxFYoY1nGuq3FhZG7xdPYi7eHoyM-PAbq-8rKeIRcJWJi37TazbqqLViGbejaD6rRxOihzoMPo1LtBuqGGw8m6fI1UJlvnt1NHd-du3Q6065WufL-nXn2Osmg962TF-gSvExgxr-HFeAgjP_kyG99dzSv4mUFbikegK8Dql1K36fZ427vDQ7mGRrR1vBsbMPqW5d9huXhl-iy11AOtYNNcfRDu47Hzae5Srzp32si36-Da_dEwntuMXnK7BwxDp_BGoOuWLPFoVctH6PDoIYzXUiTbj-XiQ8zFgPydt-x_2ZEGyq61Ewebjkpj9b0g-yHk_2aQ\" } ]", "title": "Get Configurations list of JWKs"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#adds-new-json-web-key-jwk", "text": "To add a new key, we can use post-config-jwks-key operation id. As shown in the output for --info command, the post-config-jwks-key operation requires data to be sent according to JSONWebKey schema. To see the schema, use the command below: Command jans cli --schema JSONWebKey The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample JSONWebKey Using the schema and the example above, we have added below key data to the file /tmp/jwk.json . Input \"name\" : \"Connect RSA-OAEP Encryption Key 2\" , \"descr\" : \"Encryption Key 2: Elliptic Curve Diffie-Hellman Ephemeral Static key agreement using Concat KDF\" , \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"crv\" : \"\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ] , \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" , \"x\" : null, \"y\" : null Now let's post this key to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-config-jwks-key --data /tmp/jwk.json", "title": "Adds new JSON Web key (JWK)"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#replace-json-web-key-set", "text": "To replace the current JWKS configuration, use the put-config-jwks operation. This operation replaces the current set of JWK with the provided set. Operation ID: put-config-jwks Description: Replaces JSON Web Keys Schema: WebKeysConfiguration To get the schema file: Command jans cli --schema WebKeysConfiguration As suggested in the schema, we have to provide an array of keys in a json file containing key-value pairs. The properties in the key are defined by the JWK specification RFC 7517 , and for algorithm-specific properties, in RFC 7518 .", "title": "Replace JSON Web Key Set"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#properties", "text": "name Description kid It's a unique identifier for the key configuration. kty It's used to define the type of the specific cryptographic algorithms use This parameter identifies the intended use of the public key. sig for signature and enc for encryption alg The specific algorithm used with the key crv exp The exponent for the RSA public key. x5c The x5c parameter contains a chain of one or more PKIX certificates RFC5280 n The modulus for the RSA public key . e The \"e\" (exponent) parameter contains the exponent value for the RSA public key . It is represented as a Base64urlUInt-encoded value. x The \"x\" (x coordinate) parameter contains the x coordinate for the Elliptic Curve point . y The \"y\" (y coordinate) parameter contains the y coordinate for the Elliptic Curve point . Let's update the json file to create a new key configuration. Input Key { \"keys\" : [{ \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"crv\" : \"\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" , \"x\" : null , \"y\" : null }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ /ja nssen - server/co nf ig - guide/au t h - server - co nf ig/jso n - web - key - co nf ig \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" } ] } Now let's put the new keys into the Janssen server. Command jans cli --operation-id put-config-jwks --data /tmp/path-jwk.json Please remember that this operation replaces all JWKs in the Janssen server with new ones. So, in this case, if you want to keep old JWKs, you have to put them as well in the input file. Output Sample { \"keys\" : [ { \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"enc\" , \"key_ops_type\" : [], \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"exp\" : 1622245655163 , \"alg\" : \"RSA-OAEP\" , \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" }, { \"descr\" : \"Signature Key: RSA RSASSA-PKCS1-v1_5 using SHA-256\" , \"kty\" : \"RSA\" , \"e\" : \"AQAB\" , \"use\" : \"sig\" , \"key_ops_type\" : [ \"connect\" ], \"kid\" : \"connect_e47fd367-51d6-4d17-811d-adb1f1a0b723_sig_rs256\" , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhAInuAAbxL2O7H+/V0lm3bbEdCmdPdgJh+OqljtWpwi7wMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjQwNjIxMDg0ODE5WhcNMjQwNjIzMDg0ODI4WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1RCY0ZfJ/SHZ+jojCyStBjIh4upkLXuMgZLi6b7k0fQ8/oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4+pd+lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS/axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md+wejIf4hVtusRbEHz+wwZFhnrfh/nvHCvrWCcxBgeEntAin+ig1RlR8N4x9Ox9K01wIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBACkrKROjAIf6n1PKpXFTRQVov32EFcwhi1YSao/MZHURV2ruYXjh/S6HuvHWWofV8R6muLnD938GytS2mRjr+X7DOZj/bsDT7amd810SDvFUCh6IoPt46FeXFZMV4XyL4DQKoNxOEGGDVnD41NVC6k5GLzPwcVBwX11+b7wRfy/KoPP9aoSXjyWnNbhwClFQ9oTJYkNtaNeh2kJZ2j1UIqO51vyhUjpSM9awqV2u+ouxDKCT4h9xRcDwkOUlVXtBwn+dfJHnG6riLzT59MiPtWeo037hESUxIvJxLQP6jV97eEi/CMhSb1y6YJPFjnTBmCpzeHRp5+DNu65KPaGntB8=\" ], \"name\" : \"Connect RS256 Sign Key\" , \"exp\" : 1719132508905 , \"alg\" : \"RS256\" , \"n\" : \"1RCY0ZfJ_SHZ-jojCyStBjIh4upkLXuMgZLi6b7k0fQ8_oNmCBEsOKMPUubHFEHrDHZLbXj7w5gEdMPZOiLaBP8Pv0JD8IbOUtoSXEawE33LRldKiof296nlBJFsX00ipiLq3ANXuTDXtP4-pd-lvIufv1nBXpqqrN4MOsSsKuvKvxRPCg6JusHVU5hsiqbwh9y3X7sPFwqw4LJFa0U3Z4RoX7vCsS_axPPSyUi9x0zsF4S7ZGHclBReC6IipOnGyGeSEQdpuchhoZs382md-wejIf4hVtusRbEHz-wwZFhnrfh_nvHCvrWCcxBgeEntAin-ig1RlR8N4x9Ox9K01w\" } ] } Now use the Get Configurations list of JWKs to confirm the replacement.", "title": "Properties"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#get-a-json-web-key-based-on-kid", "text": "With get-jwk-by-kid operation-id, we can get any specific jwk matched with kid . If we know the kid , we can simply use the below command: Command jans cli --operation-id get-jwk/janssen-server/config-guide/auth-server-config/json-web-key-config-by-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 It returns the details as below: Sample Output { \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"enc\" , \"alg\" : \"RSA-OAEP\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" }", "title": "Get a JSON Web Key Based on kid"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#patch-json-web-key-jwk-by-kid", "text": "Using patch-config-jwks operation, we can modify JSON Web Keys partially for its properties. Operation ID: patch-config-jwks Description: Patches JSON Web Keys Schema: Array of JsonPatch To use this operation, specify the id of the key that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property use from enc to sig . Input [ { \"op\" : \"replace\" , \"path\" : \"use\" , \"value\" : \"sig\" } ] Now let's do the operation with the command line. Command jans cli --operation-id patch-config-jwk-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 --data /tmp/schema.json Updated Json Web Key: Key { \"kid\" : \"dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5\" , \"kty\" : \"RSA\" , \"use\" : \"sig\" , \"alg\" : \"RSA-OAEP\" , \"exp\" : 1622245655163 , \"x5c\" : [ \"MIIDCjCCAfKgAwIBAgIhANYLiviUTmgOsf9Bf+6N/pr6H4Mis5ku1VXNj7VW/CMbMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGUphbnMgQXV0aCBDQSBDZXJ0aWZpY2F0ZXMwHhcNMjEwNTI2MjM0NzI5WhcNMjEwNTI4MjM0NzM1WjAkMSIwIAYDVQQDDBlKYW5zIEF1dGggQ0EgQ2VydGlmaWNhdGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlD19ib3J2bKYr2iap1d/gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx/CfHSgdEmACCXMiG7sQt80DPM67dlbtv/pEnWrHk4fwwst83OF+HXTSi4Sd9QWhDtBvaUu8Rp8ir+x2D0RK8YNGs0prA+qGR8O/h6Y+ascz4VNbbDlbJ+w7DJYeWU1HVp/5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y/9i8kf2pmznpu5QEDimj1yxEB+G5WEYuHD/+qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk/KKB7/KT0rEOn7T2rXW9QIDAQABoycwJTAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZIhvcNAQELBQADggEBAKrtlIPhvDBxBfcqS9Xy39QqE1WOPiNQooa/FVVOsCROdRZrHhFcP27HpxO9e6genQSJ6nBRaJ4ykEf0oM535Ker5jZcDWzCwPIyt+5Kc6qeacZI5FxEHRldYkSd4lF1OTzQNvGLOPKnNWnYnXwj48ZxO50lJUsRFspVbP79E6llVNOPexrZ2GOzWghyY1E74f4uGr6fzcXQk2aFaIfLusoJlvbROPTnDu68Jt+IW4WZcO4F0tl0JIcuaqSmLS6McJW0Mpmu4wqEPV6E45zRAuX0kJUkKDMzM/lYW1MZ8QaSTt/pCmlknX1+KTgb6Sf9zZJEya8AyKML/NCpc4sfn8g=\" ], \"n\" : \"rlD19ib3J2bKYr2iap1d_gCmbXocMJTk5o7o3h9jJKXbh9pdf2gd3ZOE6wc5XwGx_CfHSgdEmACCXMiG7sQt80DPM67dlbtv_pEnWrHk4fwwst83OF-HXTSi4Sd9QWhDtBvaUu8Rp8ir-x2D0RK8YNGs0prA-qGR8O_h6Y-ascz4VNbbDlbJ-w7DJYeWU1HVp_5Lt8O5i4Q6I8KZEAytwvspF5y8m8DCrfYXF6Kz14vXgqr08hj0l0Aj4O3y_9i8kf2pmznpu5QEDimj1yxEB-G5WEYuHD_-qRTV85OXDIQJz6fgNM4kEimv7pmspcDfk_KKB7_KT0rEOn7T2rXW9Q\" , \"e\" : \"AQAB\" } We see it has replaced the value of the use property from enc to sig . Please read about patch method , You can get some idea of how this patch method works to modify particular properties of any task.", "title": "Patch JSON Web Key (JWK) by kid"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#delete-json-web-key-using-kid", "text": "It's pretty simple to delete json web key using its kid . The command line is: Command jans cli --operation-id delete-config-jwk-kid \\ --url-suffix kid:dd550214-7969-41b9-b919-2a0cfa36047b_enc_rsa1_5 It will delete the jwk if it matches with the given kid .", "title": "Delete Json Web Key using kid"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#using-text-based-ui", "text": "In Janssen, you can view the JSON web keys using the Text-Based UI also. You can start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#json-web-key-jwk-screen", "text": "Navigate to Auth Server -> Keys to open the JSON Web Key screen as shown in the image below. After clicking on Get keys , You can view Key's list on this page. You cannot perform any operations in text-based UI. Only you can perform operations using the command line.", "title": "JSON Web Key (JWK) Screen"}, {"location": "janssen-server/config-guide/auth-server-config/json-web-key-config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Json Web key. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/", "tags": ["administration", "configuration", "logging"], "text": "Log Management # Logging for Janssen Server modules is managed at the individual module level. Meaning there is no single switch or configuration that will enable or disable logs for all modules. Each module can be individually configured and can be configured differently when it comes to logging. Log Configuration For jans-auth # Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using-text-based-ui Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and customize the Logging Configuration using the command line. To get the details of Janssen command line operations relevant to Logging configuration, you can check the operations under ConfigurationLogging task using the command below: Command jans cli --info ConfigurationLogging Sample Output Operation ID: get-config-logging Description: Returns Jans Authorization Server logging settings Operation ID: put-config-logging Description: Updates Jans Authorization Server logging settings Schema: Logging To get sample schema type jans cli --schema <schema>, for example jans cli --schema Logging Find Logging Configuration # Command jans cli --operation-id get-config-logging Sample Output 1 2 3 4 5 6 7 8 9 10 11 { \"loggingLevel\" : \"DEBUG\" , \"loggingLayout\" : \"string\" , \"httpLoggingEnabled\" : true , \"disableJdkLogger\" : true , \"enabledOAuthAuditLogging\" : true , \"externalLoggerConfiguration\" : \"string\" , \"httpLoggingExcludePaths\" : [ \"string\" ] } Update Logging Configuration # To update the configuration follow the steps below. Get the current logging configuration and store it in a file for editing. The following command will retrieve the current logging configuration and store it in a file. Command jans cli -no-color --operation-id get-config-logging > /tmp/log-config.json Update the configuration with desired value in the file while keeping other properties and values unchanged. Updates must adhere to the Logging schema as mentioned here . The schema details can be retrieved using the command below. The schema defines what values and datatypes are acceptable for each property value. Command jans cli --schema Logging Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-config-logging --data /tmp/log-config.json Upon successful execution of the update, the Janssen Server responds with updated configuration. Using-text-based-ui # Start TUI using the command below: Command jans tui Logging Configuration for Auth Server # Navigate to Auth Server -> Logging to open the Logging screen as shown in the image below to change the logging properties configuration. Logging Configuration for FIDO # Navigate to FIDO to open the Logging screen as shown in the image below to change the logging properties configuration. Logging Configuration for SCIM # Navigate to SCIM to open the Logging screen as shown in the image below to change the logging properties configuration. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring logging. Endpoint details are published in the Swagger document . Default Log Location # On a VM installation, logs for jans-auth module are generated at /opt/jans/jetty/jans-auth/logs/ . Similarly, logs for FIDO2 and SCIM modules are generated under /opt/jans/jetty/jans-fido2/logs/ and /opt/jans/jetty/jans-scim/logs/ respectively. Cloud-Native Deployments # Logging configuration for a cloud-native deployment is detailed here", "title": "Logging"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#log-management", "text": "Logging for Janssen Server modules is managed at the individual module level. Meaning there is no single switch or configuration that will enable or disable logs for all modules. Each module can be individually configured and can be configured differently when it comes to logging.", "title": "Log Management"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#log-configuration-for-jans-auth", "text": "Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using-text-based-ui Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Log Configuration For jans-auth"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the Logging Configuration using the command line. To get the details of Janssen command line operations relevant to Logging configuration, you can check the operations under ConfigurationLogging task using the command below: Command jans cli --info ConfigurationLogging Sample Output Operation ID: get-config-logging Description: Returns Jans Authorization Server logging settings Operation ID: put-config-logging Description: Updates Jans Authorization Server logging settings Schema: Logging To get sample schema type jans cli --schema <schema>, for example jans cli --schema Logging", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#find-logging-configuration", "text": "Command jans cli --operation-id get-config-logging Sample Output 1 2 3 4 5 6 7 8 9 10 11 { \"loggingLevel\" : \"DEBUG\" , \"loggingLayout\" : \"string\" , \"httpLoggingEnabled\" : true , \"disableJdkLogger\" : true , \"enabledOAuthAuditLogging\" : true , \"externalLoggerConfiguration\" : \"string\" , \"httpLoggingExcludePaths\" : [ \"string\" ] }", "title": "Find Logging Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#update-logging-configuration", "text": "To update the configuration follow the steps below. Get the current logging configuration and store it in a file for editing. The following command will retrieve the current logging configuration and store it in a file. Command jans cli -no-color --operation-id get-config-logging > /tmp/log-config.json Update the configuration with desired value in the file while keeping other properties and values unchanged. Updates must adhere to the Logging schema as mentioned here . The schema details can be retrieved using the command below. The schema defines what values and datatypes are acceptable for each property value. Command jans cli --schema Logging Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-config-logging --data /tmp/log-config.json Upon successful execution of the update, the Janssen Server responds with updated configuration.", "title": "Update Logging Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#using-text-based-ui", "text": "Start TUI using the command below: Command jans tui", "title": "Using-text-based-ui"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#logging-configuration-for-auth-server", "text": "Navigate to Auth Server -> Logging to open the Logging screen as shown in the image below to change the logging properties configuration.", "title": "Logging Configuration for Auth Server"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#logging-configuration-for-fido", "text": "Navigate to FIDO to open the Logging screen as shown in the image below to change the logging properties configuration.", "title": "Logging Configuration for FIDO"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#logging-configuration-for-scim", "text": "Navigate to SCIM to open the Logging screen as shown in the image below to change the logging properties configuration.", "title": "Logging Configuration for SCIM"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring logging. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#default-log-location", "text": "On a VM installation, logs for jans-auth module are generated at /opt/jans/jetty/jans-auth/logs/ . Similarly, logs for FIDO2 and SCIM modules are generated under /opt/jans/jetty/jans-fido2/logs/ and /opt/jans/jetty/jans-scim/logs/ respectively.", "title": "Default Log Location"}, {"location": "janssen-server/config-guide/auth-server-config/logging-configuration/#cloud-native-deployments", "text": "Logging configuration for a cloud-native deployment is detailed here", "title": "Cloud-Native Deployments"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/", "tags": ["administration", "configuration", "scopes"], "text": "OAuth Scopes # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the configuration steps Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and customize the OAuth scopes using the command line. To get the details of Janssen command line operations relevant to OAuth Scope, you can check the operations under the OauthScopes task using the command below. Command jans cli --info OauthScopes Sample Output Operation ID: get-oauth-scopes Description: Gets list of Scopes Parameters: type: Scope type [string] limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] withAssociatedClients: Boolean fag to indicate if clients associated with the scope are to be returned [boolean] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-scopes Description: Update Scope Schema: Scope Operation ID: post-oauth-scopes Description: Create Scope Schema: Scope Operation ID: get-oauth-scopes-by-inum Description: Get Scope by Inum Parameters: inum: Scope identifier [string] withAssociatedClients: No description is provided for this parameter [boolean] Operation ID: delete-oauth-scopes-by-inum Description: Delete Scope Parameters: inum: Scope identifier [string] Operation ID: patch-oauth-scopes-by-id Description: Patch Scope Parameters: inum: Scope identifier [string] Schema: Array of JsonPatch Operation ID: get-scope-by-creator Description: Get Scope by creatorId Parameters: creatorId: Id of the scope creator. If creator is client then client_id if user then user_id [string] Operation ID: get-scope-by-type Description: Get Scope by type Parameters: type: Type of the scope [string] To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch Find/View OAuth Scopes # Use the operation ID get-oauth-scopes to find and view the current scopes. Let's retrieve 3 scopes that contain view in the description and openid as the Type. Command jans cli --operation-id get-oauth-scopes \\ --endpoint-args limit:3,pattern:view,type:openid Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 { \"start\": 0, \"totalEntriesCount\": 7, \"entriesCount\": 3, \"entries\": [ { \"dn\": \"inum=10B2,ou=scopes,o=jans\", \"inum\": \"10B2\", \"displayName\": \"view_username\", \"id\": \"user_name\", \"description\": \"View your local username in the Janssen Server.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=42E0,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=10B2,ou=scopes,o=jans\" }, { \"dn\": \"inum=341A,ou=scopes,o=jans\", \"inum\": \"341A\", \"displayName\": \"view_client\", \"id\": \"clientinfo\", \"description\": \"View the client info.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=2B29,ou=attributes,o=jans\", \"inum=29DA,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=341A,ou=scopes,o=jans\" }, { \"dn\": \"inum=43F1,ou=scopes,o=jans\", \"inum\": \"43F1\", \"displayName\": \"view_profile\", \"id\": \"profile\", \"description\": \"View your basic profile info.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=2B29,ou=attributes,o=jans\", \"inum=0C85,ou=attributes,o=jans\", \"inum=B4B0,ou=attributes,o=jans\", \"inum=A0E8,ou=attributes,o=jans\", \"inum=5EC6,ou=attributes,o=jans\", \"inum=B52A,ou=attributes,o=jans\", \"inum=64A0,ou=attributes,o=jans\", \"inum=EC3A,ou=attributes,o=jans\", \"inum=3B47,ou=attributes,o=jans\", \"inum=3692,ou=attributes,o=jans\", \"inum=98FC,ou=attributes,o=jans\", \"inum=A901,ou=attributes,o=jans\", \"inum=36D9,ou=attributes,o=jans\", \"inum=BE64,ou=attributes,o=jans\", \"inum=6493,ou=attributes,o=jans\", \"inum=4CF1,ou=attributes,o=jans\", \"inum=29DA,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=43F1,ou=scopes,o=jans\" } ] } Create an OAuth Scope # To create a new scope, we can use post-oauth-scopes operation id. As shown in the output for --info command, the post-oauth-scopes operation requires data to be sent according to Scope schema. To see the schema, use the command below: Command jans cli --schema Scope For better understanding, the Janssen Server also provides an sample of data to be sent to the server. This sample conforms to the schema above. Use the command below to get the sample. Command jans cli --schema-sample Scope Using the schema and the example above, we have added below key data to the file /tmp/scope.json Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { \"dn\" : null , \"id\" : \"TestScopeID\" , \"inum\" : null , \"displayName\" : \"TestScope\" , \"description\" : \"Test Scope created by jans-cli\" , \"iconUrl\" : null , \"authorizationPolicies\" : [], \"defaultScope\" : true , \"scopeType\" : \"openid\" , \"claims\" : [], \"umaType\" : false , \"umaAuthorizationPolicies\" : [], \"attributes\" : { \"spontaneousClientId\" : null , \"spontaneousClientScopes\" : [], \"showInConfigurationEndpoint\" : true } } Now let's post this scope to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-scopes \\ --data /tmp/scope.json Update Existing OAuth Scopes # To update the configuration follow the steps below. Get the existing OAuth Scope and store it into a file for editing. The following command will retrieve the existing OAuth Scope in the schema file. Sample Command jans cli -no-color --operation-id get-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 > /tmp/scopdata.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Scope schema as mentioned here . We have changed only the scopeType to dynamic in existing OAuth Scope. Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-scopes --data /tmp/scope.json This will updated the existing oauth scopes matched with inum value. Patch OAuth Scopes by inum # Let's update iconUrl with patch method. So we need a schema for the patch method. Remember when we queried info for the task OAuthScopes it printed: Operation ID: patch-oauth-scopes-by-id Description: Patch Scope Parameters: inum: Scope identifier [string] Schema: Array of JsonPatch The patch-oauth-scopes-by-id operation uses the JSON Patch schema to describe the configuration change. Refer here to know more about schema. Command jans cli --schema JsonPatch > /tmp/patch.json For instance, to perform a replace operation at iconUrl and change it from null to https://www.jans.io/icon.png , the JSON Patch data would look like below: Input [ { \"op\" : \"replace\" , \"path\" : \"iconUrl\" , \"value\" : \"https://www.jans.io/icon.png\" } ] Store the above JSON Patch data in a file, for instance, /tmp/patch.json Let's do the operation: Command jans cli --operation-id patch-oauth-scopes-by-id \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 --data /tmp/patch.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"dn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" , \"inum\" : \"8eb2b0c0-d1d9-453d-8364-e2809ce857f2\" , \"displayName\" : \"TestScope\" , \"id\" : \"TestScopeID\" , \"iconUrl\" : \"https://www.jans.io/icon.png\" , \"description\" : \"Test Scope created by jans-cli\" , \"scopeType\" : \"dynamic\" , \"defaultScope\" : true , \"attributes\" : { \"showInConfigurationEndpoint\" : true }, \"creationDate\" : \"2024-06-25T08:44:08\" , \"umaType\" : false , \"baseDn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" } Find OAuth Scopes by inum # In case We know the inum value of an OAuth Scope, We can get the details of that scope. Operation ID: get-oauth-scopes-by-inum Description: Get Scope by Inum Parameters: inum: Scope identifier [string] withAssociatedClients: No description is provided for this parameter [boolean] We can use the url-suffix for the inum value. Sample Command jans cli --operation-id get-oauth-scopes-by-inum --url-suffix inum:value For example: Command jans cli --operation-id get-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 It returns the details of the scope matched with the inum value. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"dn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" , \"inum\" : \"8eb2b0c0-d1d9-453d-8364-e2809ce857f2\" , \"displayName\" : \"TestScope\" , \"id\" : \"TestScopeID\" , \"iconUrl\" : \"https://www.jans.io/icon.png\" , \"description\" : \"Test Scope created by jans-cli\" , \"scopeType\" : \"dynamic\" , \"defaultScope\" : true , \"attributes\" : { \"showInConfigurationEndpoint\" : true }, \"creationDate\" : \"2024-06-25T08:44:08\" , \"umaType\" : false , \"baseDn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" } Delete OAuth Scopes by inum # You can delete any OAuth Scopes by its inum value. Command jans cli --operation-id delete-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 Just change the inum value to your own according to which one you want to delete. Using Text-based UI # You can start TUI using the command below: Command jans tui Scope Screen # Navigate to Auth Server -> Scopes to open the scope screen as shown in the image below. To get the list of currently added Scope, bring the control to Search box (using the tab key), and press Enter. Type the search string to search for Scope with matching id and inum . Add Scope screen # Use the Add Scope button to create a new scope. You can create several types of scopes in the screen below, such as oauth , OpenID , dynamic , and uma , with the correct data. For example, below is the picture availability scope data. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OAuth Scope. Endpoint details are published in the Swagger document .", "title": "OAuth Scope Management"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#oauth-scopes", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the configuration steps Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "OAuth Scopes"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the OAuth scopes using the command line. To get the details of Janssen command line operations relevant to OAuth Scope, you can check the operations under the OauthScopes task using the command below. Command jans cli --info OauthScopes Sample Output Operation ID: get-oauth-scopes Description: Gets list of Scopes Parameters: type: Scope type [string] limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] withAssociatedClients: Boolean fag to indicate if clients associated with the scope are to be returned [boolean] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-scopes Description: Update Scope Schema: Scope Operation ID: post-oauth-scopes Description: Create Scope Schema: Scope Operation ID: get-oauth-scopes-by-inum Description: Get Scope by Inum Parameters: inum: Scope identifier [string] withAssociatedClients: No description is provided for this parameter [boolean] Operation ID: delete-oauth-scopes-by-inum Description: Delete Scope Parameters: inum: Scope identifier [string] Operation ID: patch-oauth-scopes-by-id Description: Patch Scope Parameters: inum: Scope identifier [string] Schema: Array of JsonPatch Operation ID: get-scope-by-creator Description: Get Scope by creatorId Parameters: creatorId: Id of the scope creator. If creator is client then client_id if user then user_id [string] Operation ID: get-scope-by-type Description: Get Scope by type Parameters: type: Type of the scope [string] To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#findview-oauth-scopes", "text": "Use the operation ID get-oauth-scopes to find and view the current scopes. Let's retrieve 3 scopes that contain view in the description and openid as the Type. Command jans cli --operation-id get-oauth-scopes \\ --endpoint-args limit:3,pattern:view,type:openid Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 { \"start\": 0, \"totalEntriesCount\": 7, \"entriesCount\": 3, \"entries\": [ { \"dn\": \"inum=10B2,ou=scopes,o=jans\", \"inum\": \"10B2\", \"displayName\": \"view_username\", \"id\": \"user_name\", \"description\": \"View your local username in the Janssen Server.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=42E0,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=10B2,ou=scopes,o=jans\" }, { \"dn\": \"inum=341A,ou=scopes,o=jans\", \"inum\": \"341A\", \"displayName\": \"view_client\", \"id\": \"clientinfo\", \"description\": \"View the client info.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=2B29,ou=attributes,o=jans\", \"inum=29DA,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=341A,ou=scopes,o=jans\" }, { \"dn\": \"inum=43F1,ou=scopes,o=jans\", \"inum\": \"43F1\", \"displayName\": \"view_profile\", \"id\": \"profile\", \"description\": \"View your basic profile info.\", \"scopeType\": \"openid\", \"claims\": [ \"inum=2B29,ou=attributes,o=jans\", \"inum=0C85,ou=attributes,o=jans\", \"inum=B4B0,ou=attributes,o=jans\", \"inum=A0E8,ou=attributes,o=jans\", \"inum=5EC6,ou=attributes,o=jans\", \"inum=B52A,ou=attributes,o=jans\", \"inum=64A0,ou=attributes,o=jans\", \"inum=EC3A,ou=attributes,o=jans\", \"inum=3B47,ou=attributes,o=jans\", \"inum=3692,ou=attributes,o=jans\", \"inum=98FC,ou=attributes,o=jans\", \"inum=A901,ou=attributes,o=jans\", \"inum=36D9,ou=attributes,o=jans\", \"inum=BE64,ou=attributes,o=jans\", \"inum=6493,ou=attributes,o=jans\", \"inum=4CF1,ou=attributes,o=jans\", \"inum=29DA,ou=attributes,o=jans\" ], \"defaultScope\": false, \"attributes\": { \"showInConfigurationEndpoint\": true }, \"creationDate\": \"2024-06-25T09:02:25\", \"umaType\": false, \"baseDn\": \"inum=43F1,ou=scopes,o=jans\" } ] }", "title": "Find/View OAuth Scopes"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#create-an-oauth-scope", "text": "To create a new scope, we can use post-oauth-scopes operation id. As shown in the output for --info command, the post-oauth-scopes operation requires data to be sent according to Scope schema. To see the schema, use the command below: Command jans cli --schema Scope For better understanding, the Janssen Server also provides an sample of data to be sent to the server. This sample conforms to the schema above. Use the command below to get the sample. Command jans cli --schema-sample Scope Using the schema and the example above, we have added below key data to the file /tmp/scope.json Input 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { \"dn\" : null , \"id\" : \"TestScopeID\" , \"inum\" : null , \"displayName\" : \"TestScope\" , \"description\" : \"Test Scope created by jans-cli\" , \"iconUrl\" : null , \"authorizationPolicies\" : [], \"defaultScope\" : true , \"scopeType\" : \"openid\" , \"claims\" : [], \"umaType\" : false , \"umaAuthorizationPolicies\" : [], \"attributes\" : { \"spontaneousClientId\" : null , \"spontaneousClientScopes\" : [], \"showInConfigurationEndpoint\" : true } } Now let's post this scope to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-scopes \\ --data /tmp/scope.json", "title": "Create an OAuth Scope"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#update-existing-oauth-scopes", "text": "To update the configuration follow the steps below. Get the existing OAuth Scope and store it into a file for editing. The following command will retrieve the existing OAuth Scope in the schema file. Sample Command jans cli -no-color --operation-id get-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 > /tmp/scopdata.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Scope schema as mentioned here . We have changed only the scopeType to dynamic in existing OAuth Scope. Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-scopes --data /tmp/scope.json This will updated the existing oauth scopes matched with inum value.", "title": "Update Existing OAuth Scopes"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#patch-oauth-scopes-by-inum", "text": "Let's update iconUrl with patch method. So we need a schema for the patch method. Remember when we queried info for the task OAuthScopes it printed: Operation ID: patch-oauth-scopes-by-id Description: Patch Scope Parameters: inum: Scope identifier [string] Schema: Array of JsonPatch The patch-oauth-scopes-by-id operation uses the JSON Patch schema to describe the configuration change. Refer here to know more about schema. Command jans cli --schema JsonPatch > /tmp/patch.json For instance, to perform a replace operation at iconUrl and change it from null to https://www.jans.io/icon.png , the JSON Patch data would look like below: Input [ { \"op\" : \"replace\" , \"path\" : \"iconUrl\" , \"value\" : \"https://www.jans.io/icon.png\" } ] Store the above JSON Patch data in a file, for instance, /tmp/patch.json Let's do the operation: Command jans cli --operation-id patch-oauth-scopes-by-id \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 --data /tmp/patch.json Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"dn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" , \"inum\" : \"8eb2b0c0-d1d9-453d-8364-e2809ce857f2\" , \"displayName\" : \"TestScope\" , \"id\" : \"TestScopeID\" , \"iconUrl\" : \"https://www.jans.io/icon.png\" , \"description\" : \"Test Scope created by jans-cli\" , \"scopeType\" : \"dynamic\" , \"defaultScope\" : true , \"attributes\" : { \"showInConfigurationEndpoint\" : true }, \"creationDate\" : \"2024-06-25T08:44:08\" , \"umaType\" : false , \"baseDn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" }", "title": "Patch OAuth Scopes by inum"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#find-oauth-scopes-by-inum", "text": "In case We know the inum value of an OAuth Scope, We can get the details of that scope. Operation ID: get-oauth-scopes-by-inum Description: Get Scope by Inum Parameters: inum: Scope identifier [string] withAssociatedClients: No description is provided for this parameter [boolean] We can use the url-suffix for the inum value. Sample Command jans cli --operation-id get-oauth-scopes-by-inum --url-suffix inum:value For example: Command jans cli --operation-id get-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 It returns the details of the scope matched with the inum value. Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { \"dn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" , \"inum\" : \"8eb2b0c0-d1d9-453d-8364-e2809ce857f2\" , \"displayName\" : \"TestScope\" , \"id\" : \"TestScopeID\" , \"iconUrl\" : \"https://www.jans.io/icon.png\" , \"description\" : \"Test Scope created by jans-cli\" , \"scopeType\" : \"dynamic\" , \"defaultScope\" : true , \"attributes\" : { \"showInConfigurationEndpoint\" : true }, \"creationDate\" : \"2024-06-25T08:44:08\" , \"umaType\" : false , \"baseDn\" : \"inum=8eb2b0c0-d1d9-453d-8364-e2809ce857f2,ou=scopes,o=jans\" }", "title": "Find OAuth Scopes by inum"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#delete-oauth-scopes-by-inum", "text": "You can delete any OAuth Scopes by its inum value. Command jans cli --operation-id delete-oauth-scopes-by-inum \\ --url-suffix inum:8eb2b0c0-d1d9-453d-8364-e2809ce857f2 Just change the inum value to your own according to which one you want to delete.", "title": "Delete OAuth Scopes by inum"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#using-text-based-ui", "text": "You can start TUI using the command below: Command jans tui", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#scope-screen", "text": "Navigate to Auth Server -> Scopes to open the scope screen as shown in the image below. To get the list of currently added Scope, bring the control to Search box (using the tab key), and press Enter. Type the search string to search for Scope with matching id and inum .", "title": "Scope Screen"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#add-scope-screen", "text": "Use the Add Scope button to create a new scope. You can create several types of scopes in the screen below, such as oauth , OpenID , dynamic , and uma , with the correct data. For example, below is the picture availability scope data.", "title": "Add Scope screen"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-scopes-config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OAuth Scope. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/", "tags": ["administration", "configuration", "uma"], "text": "UMA Resources # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line UMA Resource is not possible in Text-based UI. The UMA Resource does not have a REST API. Using Command Line # In the Janssen Server, you can deploy and customize the UMA Resources using the command line. To get the details of Janssen command line operations relevant to UMA Resource, you can check the operations under the OauthUmaResources task using the command below. Command jans cli --info OauthUmaResources Sample Output Operation ID: get-oauth-uma-resources Description: Gets list of UMA resources Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-uma-resources Description: Updates an UMA resource Schema: UmaResource Operation ID: post-oauth-uma-resources Description: Creates an UMA resource Schema: UmaResource Operation ID: get-oauth-uma-resources-by-id Description: Gets an UMA resource by ID Parameters: id: Resource description ID [string] Operation ID: delete-oauth-uma-resources-by-id Description: Deletes an UMA resource Parameters: id: Resource description ID [string] Operation ID: patch-oauth-uma-resources-by-id Description: Patch UMA resource Parameters: id: Resource description ID [string] Schema: Array of JsonPatch Operation ID: get-oauth-uma-resources-by-clientid Description: Fetch uma resources by client id Parameters: clientId: Client ID [string] To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch Get List of UMA Resources # To find the existing UMA Resources, let's run the following command: get-oauth-uma-resources operation is used to search UMA Resources. To get a list of UMA resources: Command jans cli --operation-id get-oauth-uma-resources Sample Output { \"start\" : 0 , \"totalEntriesCount\" : 2 , \"entriesCount\" : 2 , \"entries\" : [ { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true }, { \"dn\" : \"jansId=c0204b2a-4047-4c2b-86a8-a088e2ee54de,ou=resources,ou=uma,o=jans\" , \"id\" : \"c0204b2a-4047-4c2b-86a8-a088e2ee54de\" , \"name\" : \"Jans Cofig Api Uma Resource\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"deletable\" : true } ] } To search using multiple arguments, you can change pattern that you want to find: jans cli --operation-id get-oauth-uma-resources \\ --endpoint-args limit:1,pattern: \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true } ] } Get Oauth UMA Resource by ID # With get-oauth-uma-resources-by-id operation-id, we can get any specific uma Resource matched with ID . If we know the ID , we can simply use the below command: Command jans cli --operation-id get-oauth-uma-resources-by-id \\ --url-suffix id:361e1db0-19b4-4d83-9cb8-616dda8292b7 Sample Output { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true } Patch OAuth UMA Resource by ID # Using patch-oauth-uma-resources-by-id operation, we can modify UMA Resource partially for its properties. Operation ID: patch-oauth-uma-resources-by-id Description: Patch UMA resource Parameters: id: Resource description ID [string] Schema: Array of JsonPatch To use this operation, specify the id of the Uma that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property name from uma resource to UMA . Input [ { \"op\" : \"replace\" , \"path\" : \"name\" , \"value\" : \"UMA\" } ] Now let's do the operation with the command line. Command jans cli --operation-id patch-oauth-uma-resources-by-id \\ --url-suffix id:c0204b2a-4047-4c2b-86a8-a088e2ee54de --data /tmp/patch-uma.json Sample Output { \"dn\" : \"jansId=c0204b2a-4047-4c2b-86a8-a088e2ee54de,ou=resources,ou=uma,o=jans\" , \"id\" : \"c0204b2a-4047-4c2b-86a8-a088e2ee54de\" , \"name\" : \"UMA\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"deletable\" : true } We see it has replaced the value of the name property from Jans Cofig Api Uma Resource to UMA . Please read about patch method , You can get some idea of how this patch method works to modify particular properties of any task. Adds new Uma Resource # To add a new Uma Resource, we can use post-oauth-uma-resources operation id. As shown in the output for --info command, the post-oauth-uma-resources operation requires data to be sent according to UmaResource schema. To see the schema, use the command below: Command jans cli --schema UmaResource The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample UmaResource Using the schema and the example above, we have added below data to the file /tmp/uma.json . Input { \"name\" : \"Jans Cofig Api Uma\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : null , \"scopeExpression\" : null , \"clients\" : [ \"inum=b294adfd-b825-4e7f-9815-55d744002315,ou=clients,o=jans\" ], \"resources\" : [ \"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\" ], \"rev\" : \"1\" , \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"type\" : null , \"creationDate\" : null , \"expirationDate\" : null , \"deletable\" : true } Now let's post this uma to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-uma-resources --data /tmp/uma.json Updates an UMA resource # To update the uma resource follow the steps below. Get Oauth UMA Resource by ID and store it into a file for editing. The following command will retrieve the existing Uma resource in the schema file. Sample Command jans cli -no-color --operation-id get-oauth-uma-resources-by-id \\ --url-suffix id:c70c3b5c-d543-4dec-923c-4035bdce52bb > /tmp/update-uma.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the UmaResource schema as mentioned here . We have changed only the true to false for deletable in existing uma resource. Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-uma-resources --data /tmp/update-uma.json This will updated the existing uma resource matched with id. Get Oauth UMA Resource by Client id # With get-oauth-uma-resources-by-clientid operation-id, we can get any specific uma Resource matched with clientid . If we know the clientid , we can simply use the below command: Command jans cli --operation-id get-oauth-uma-resources-by-clientid \\ --url-suffix client id:361e1db0-19b4-4d83-9cb8-616dda8292b7 Sample Output { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true } Delete Uma Resource by id # You can delete any Uma Resource by its id value. Command jans cli --operation-id delete-oauth-uma-resources-by-id \\ --url-suffix id:c0204b2a-4047-4c2b-86a8-a088e2ee54de Just change the id to your own according to which one you want to delete.", "title": "UMA Management"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#uma-resources", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line UMA Resource is not possible in Text-based UI. The UMA Resource does not have a REST API.", "title": "UMA Resources"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the UMA Resources using the command line. To get the details of Janssen command line operations relevant to UMA Resource, you can check the operations under the OauthUmaResources task using the command below. Command jans cli --info OauthUmaResources Sample Output Operation ID: get-oauth-uma-resources Description: Gets list of UMA resources Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-uma-resources Description: Updates an UMA resource Schema: UmaResource Operation ID: post-oauth-uma-resources Description: Creates an UMA resource Schema: UmaResource Operation ID: get-oauth-uma-resources-by-id Description: Gets an UMA resource by ID Parameters: id: Resource description ID [string] Operation ID: delete-oauth-uma-resources-by-id Description: Deletes an UMA resource Parameters: id: Resource description ID [string] Operation ID: patch-oauth-uma-resources-by-id Description: Patch UMA resource Parameters: id: Resource description ID [string] Schema: Array of JsonPatch Operation ID: get-oauth-uma-resources-by-clientid Description: Fetch uma resources by client id Parameters: clientId: Client ID [string] To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#get-list-of-uma-resources", "text": "To find the existing UMA Resources, let's run the following command: get-oauth-uma-resources operation is used to search UMA Resources. To get a list of UMA resources: Command jans cli --operation-id get-oauth-uma-resources Sample Output { \"start\" : 0 , \"totalEntriesCount\" : 2 , \"entriesCount\" : 2 , \"entries\" : [ { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true }, { \"dn\" : \"jansId=c0204b2a-4047-4c2b-86a8-a088e2ee54de,ou=resources,ou=uma,o=jans\" , \"id\" : \"c0204b2a-4047-4c2b-86a8-a088e2ee54de\" , \"name\" : \"Jans Cofig Api Uma Resource\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"deletable\" : true } ] } To search using multiple arguments, you can change pattern that you want to find: jans cli --operation-id get-oauth-uma-resources \\ --endpoint-args limit:1,pattern: \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" { \"start\" : 0 , \"totalEntriesCount\" : 1 , \"entriesCount\" : 1 , \"entries\" : [ { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true } ] }", "title": "Get List of UMA Resources"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#get-oauth-uma-resource-by-id", "text": "With get-oauth-uma-resources-by-id operation-id, we can get any specific uma Resource matched with ID . If we know the ID , we can simply use the below command: Command jans cli --operation-id get-oauth-uma-resources-by-id \\ --url-suffix id:361e1db0-19b4-4d83-9cb8-616dda8292b7 Sample Output { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true }", "title": "Get Oauth UMA Resource by ID"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#patch-oauth-uma-resource-by-id", "text": "Using patch-oauth-uma-resources-by-id operation, we can modify UMA Resource partially for its properties. Operation ID: patch-oauth-uma-resources-by-id Description: Patch UMA resource Parameters: id: Resource description ID [string] Schema: Array of JsonPatch To use this operation, specify the id of the Uma that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property name from uma resource to UMA . Input [ { \"op\" : \"replace\" , \"path\" : \"name\" , \"value\" : \"UMA\" } ] Now let's do the operation with the command line. Command jans cli --operation-id patch-oauth-uma-resources-by-id \\ --url-suffix id:c0204b2a-4047-4c2b-86a8-a088e2ee54de --data /tmp/patch-uma.json Sample Output { \"dn\" : \"jansId=c0204b2a-4047-4c2b-86a8-a088e2ee54de,ou=resources,ou=uma,o=jans\" , \"id\" : \"c0204b2a-4047-4c2b-86a8-a088e2ee54de\" , \"name\" : \"UMA\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"deletable\" : true } We see it has replaced the value of the name property from Jans Cofig Api Uma Resource to UMA . Please read about patch method , You can get some idea of how this patch method works to modify particular properties of any task.", "title": "Patch OAuth UMA Resource by ID"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#adds-new-uma-resource", "text": "To add a new Uma Resource, we can use post-oauth-uma-resources operation id. As shown in the output for --info command, the post-oauth-uma-resources operation requires data to be sent according to UmaResource schema. To see the schema, use the command below: Command jans cli --schema UmaResource The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample UmaResource Using the schema and the example above, we have added below data to the file /tmp/uma.json . Input { \"name\" : \"Jans Cofig Api Uma\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : null , \"scopeExpression\" : null , \"clients\" : [ \"inum=b294adfd-b825-4e7f-9815-55d744002315,ou=clients,o=jans\" ], \"resources\" : [ \"https://testjans.gluu.com/jans-config-api/api/v1/config/cache/native-persistence\" ], \"rev\" : \"1\" , \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma resource\" , \"type\" : null , \"creationDate\" : null , \"expirationDate\" : null , \"deletable\" : true } Now let's post this uma to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-uma-resources --data /tmp/uma.json", "title": "Adds new Uma Resource"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#updates-an-uma-resource", "text": "To update the uma resource follow the steps below. Get Oauth UMA Resource by ID and store it into a file for editing. The following command will retrieve the existing Uma resource in the schema file. Sample Command jans cli -no-color --operation-id get-oauth-uma-resources-by-id \\ --url-suffix id:c70c3b5c-d543-4dec-923c-4035bdce52bb > /tmp/update-uma.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the UmaResource schema as mentioned here . We have changed only the true to false for deletable in existing uma resource. Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-uma-resources --data /tmp/update-uma.json This will updated the existing uma resource matched with id.", "title": "Updates an UMA resource"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#get-oauth-uma-resource-by-client-id", "text": "With get-oauth-uma-resources-by-clientid operation-id, we can get any specific uma Resource matched with clientid . If we know the clientid , we can simply use the below command: Command jans cli --operation-id get-oauth-uma-resources-by-clientid \\ --url-suffix client id:361e1db0-19b4-4d83-9cb8-616dda8292b7 Sample Output { \"dn\" : \"jansId=361e1db0-19b4-4d83-9cb8-616dda8292b7,ou=resources,ou=uma,o=jans\" , \"id\" : \"361e1db0-19b4-4d83-9cb8-616dda8292b7\" , \"name\" : \"Jans Cofig Api Uma Resource /jans-config-api/api/v1/attributes\" , \"iconUri\" : \"http://www.jans.io/img/scim_logo.png\" , \"scopes\" : [ \"[\\\"inum=CACA-0B30,ou=scopes,o=jans\\\"]\" ], \"clients\" : [ \"inum=1801.6e8351d4-5d3f-4773-b632-6c84bf8207cd,ou=clients,o=jans\" ], \"resources\" : [ \"[\\\"https://testjans.gluu.com/jans-config-api/api/v1/attributes\\\"]\" ], \"creator\" : \"inum=d206dd87-3a22-465d-bd25-bec9313cd42d,ou=people,o=json\" , \"description\" : \"uma\" , \"deletable\" : true }", "title": "Get Oauth UMA Resource by Client id"}, {"location": "janssen-server/config-guide/auth-server-config/oauth-umaresources-config/#delete-uma-resource-by-id", "text": "You can delete any Uma Resource by its id value. Command jans cli --operation-id delete-oauth-uma-resources-by-id \\ --url-suffix id:c0204b2a-4047-4c2b-86a8-a088e2ee54de Just change the id to your own according to which one you want to delete.", "title": "Delete Uma Resource by id"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/", "tags": ["administration", "configuration", "openid-connect"], "text": "OpenID Connect Configuration # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and manage the OpenID Connect Client using the command Line. To get the details of Janssen command line operations relevant to OpenID Connect Client, you can check the operations under OauthOpenidConnectClients task using the command below: Let's get the information about OpenID Connect Client Configuration: Command jans cli --info OauthOpenidConnectClients Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Operation ID: get-oauth-openid-clients Description: Gets list of OpenID Connect clients Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-openid-client Description: Update OpenId Connect client Schema: Client Operation ID: post-oauth-openid-client Description: Create new OpenId Connect client Schema: Client Operation ID: get-oauth-openid-clients-by-inum Description: Get OpenId Connect Client by Inum Parameters: inum: Client identifier [string] Operation ID: delete-oauth-openid-client-by-inum Description: Delete OpenId Connect client Parameters: inum: Client identifier [string] Operation ID: patch-oauth-openid-client-by-inum Description: Patch OpenId Connect client Parameters: inum: Client identifier [string] Schema: Array of JsonPatch To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch Get List of OpenID Connect Clients # To get the list of OpenID Connect clients, run the following command: Command jans cli --operation-id get-oauth-openid-clients Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 { { \"start\" : 0 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 3 , \"entries\" : [ { \"dn\" : \"inum=1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"qAnnHv5Yxw6I+xHXJI6kj6f4pogINrnw7Z/sDPXSW10=\" , \"frontChannelLogoutUri\" : \"null\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://www.google.com/\" ], \"claimRedirectUris\" : [], \"responseTypes\" : [ \"code\" ], \"grantTypes\" : [ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"applicationType\" : \"web\" , \"contacts\" : [], \"clientName\" : \"Jans Config Api Client\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"RS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"defaultAcrValues\" : [], \"postLogoutRedirectUris\" : [], \"requestUris\" : [], \"scopes\" : [ \"inum=1800.01.75,ou=scopes,o=jans\" , \"inum=1800.01.76,ou=scopes,o=jans\" , \"inum=1800.01.77,ou=scopes,o=jans\" , \"inum=1800.01.78,ou=scopes,o=jans\" , \"inum=1800.01.71,ou=scopes,o=jans\" , \"inum=1800.01.72,ou=scopes,o=jans\" , ], \"claims\" : [], \"trustedClient\" : false , .... .... .... \"baseDn\" : \"inum=1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe,ou=clients,o=jans\" , \"inum\" : \"1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe\" }, { \"dn\" : \"inum=478049e2-210d-4b64-bc16-10440c973f65,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"37983639-0586-4ed3-8644-b5bc41c4ce49\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://www.google.com/\" ], \"grantTypes\" : [], \"applicationType\" : \"web\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"public\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"trustedClient\" : false , ..... ..... ..... ], \"baseDn\" : \"inum=478049e2-210d-4b64-bc16-10440c973f65,ou=clients,o=jans\" , \"inum\" : \"478049e2-210d-4b64-bc16-10440c973f65\" }, { \"dn\" : \"inum=ec53d411-5243-4c76-b91c-661b35853cd0,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"456e1c1e-796d-4dc0-9f16-7b54c9e4eb5b\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://docs.jans.io/\" ], \"grantTypes\" : [], \"applicationType\" : \"web\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"public\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"trustedClient\" : false , ..... ..... ..... \"baseDn\" : \"inum=ec53d411-5243-4c76-b91c-661b35853cd0,ou=clients,o=jans\" , \"inum\" : \"ec53d411-5243-4c76-b91c-661b35853cd0\" } ] } To search using parameters, use the command below: Command jans cli --operation-id get-oauth-openid-clients \\ --endpoint-args limit:2 Creating a New OpenID Connect Clients # To add an OpenID Connect client, we can use post-oauth-openid-client operation id. As shown in the output for --info command, the post-oauth-openid-client operation requires data to be sent according to Client schema. To see the schema, use the command below: Command jans cli --schema Client The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample Client Using the schema and the example above, we have added OpenID Connect client data to the file /tmp/openid-connect.json . An OpenID Connect client may have many properties, but we are going to fill only the required properties as shown below: Input { \"redirectUris\" : [ \"https://www.google.com/\" ] } Now let's post an OpenID Connect client to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-openid-client \\ --data /tmp/openid-connect.json Update OpenId Connect client # To update the configuration follow the steps below. Get the existing OpenID Connect Client and store it into a file for editing. The following command will retrieve the existing OpenID Connect Client in the schema file. Command jans cli -no-color \\ --operation-id get-oauth-openid-clients-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe > /tmp/update-client.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Client schema as mentioned here . We have changed in parLifetime only the 600 to 700 . Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-openid-client \\ --data /tmp/update-client.json Upon successful execution of the update, the Janssen Server responds with updated configuration Patch OpenID Connect Client by inum # Using patch-oauth-openid-client-by-inum , we can modify OpenID Connect Clients partially for its properties. To use this operation, specify the inum of the OpenID Connect Client that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property applicationType from web to native . Input 1 2 3 4 5 6 7 [ { \"op\" : \"replace\" , \"path\" : \"applicationType\" , \"value\" : \"native\" } ] Now let's do the operation with the command line. jans cli \\ --operation-id patch-oauth-openid-client-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe --data /tmp/schema.json Get OpenID Connect Client by Inum # With get-oauth-openid-clients-by-inum operation-id, we can get any specific OpenID Connect Client matched with Inum . If we know the inum , we can use the below command: jans cli \\ --operation-id get-oauth-openid-clients-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe The result will only show details of client with inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe . Delete OpenID Connect client # Delete the OpenID Connect client using its inum . The command line is: Command jans cli \\ --operation-id delete-oauth-openid-client-by-inum \\ --url-suffix inum:a89b5c29-2a91-48b5-bf27-1bf786954a06 It will delete the OpenID Connect client if it matches with the given inum . Using Text Based UI # Start TUI using the command below: Command jans tui Client Screen # Navigate to Auth Server -> Clients to open the client screen as shown in the image below. This screen shows the OpenID Connect Clients list. To get the list of currently added clients, bring the control to Search box (using the tab key), and press the Enter key. Type the search string to search for the client with the matching client name. Add-Update Client screen # Use the Add Client button to create a new client. After adding the valid data using the Save button, add a new OpenID Connect client. Update the OpenID Connect client as well. To update the client, bring the control to the Specific Client row and press the Enter key, then it will show the edit client screen. If you are editing a client, you will have Active Tokens where you can search and delete tokens related to the edited client as shown image below. To view client details in json format, press key v on keyboard, to delete press delete (or d ) key. Delete Screen # To delete the client, bring the control to the Specific Client row and press the Delete key. Then it will show the Delete confirmation box. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document .", "title": "OpenID Connect Client Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#openid-connect-configuration", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "OpenID Connect Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#using-command-line", "text": "In the Janssen Server, you can deploy and manage the OpenID Connect Client using the command Line. To get the details of Janssen command line operations relevant to OpenID Connect Client, you can check the operations under OauthOpenidConnectClients task using the command below: Let's get the information about OpenID Connect Client Configuration: Command jans cli --info OauthOpenidConnectClients Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Operation ID: get-oauth-openid-clients Description: Gets list of OpenID Connect clients Parameters: limit: Search size - max size of the results to return [integer] pattern: Search pattern [string] startIndex: The 1-based index of the first query result [integer] sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] fieldValuePair: Field and value pair for seraching [string] Operation ID: put-oauth-openid-client Description: Update OpenId Connect client Schema: Client Operation ID: post-oauth-openid-client Description: Create new OpenId Connect client Schema: Client Operation ID: get-oauth-openid-clients-by-inum Description: Get OpenId Connect Client by Inum Parameters: inum: Client identifier [string] Operation ID: delete-oauth-openid-client-by-inum Description: Delete OpenId Connect client Parameters: inum: Client identifier [string] Operation ID: patch-oauth-openid-client-by-inum Description: Patch OpenId Connect client Parameters: inum: Client identifier [string] Schema: Array of JsonPatch To get sample schema type jans cli --schema-sample <schema>, for example jans cli --schema-sample JsonPatch", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#get-list-of-openid-connect-clients", "text": "To get the list of OpenID Connect clients, run the following command: Command jans cli --operation-id get-oauth-openid-clients Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 { { \"start\" : 0 , \"totalEntriesCount\" : 3 , \"entriesCount\" : 3 , \"entries\" : [ { \"dn\" : \"inum=1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"qAnnHv5Yxw6I+xHXJI6kj6f4pogINrnw7Z/sDPXSW10=\" , \"frontChannelLogoutUri\" : \"null\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://www.google.com/\" ], \"claimRedirectUris\" : [], \"responseTypes\" : [ \"code\" ], \"grantTypes\" : [ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"applicationType\" : \"web\" , \"contacts\" : [], \"clientName\" : \"Jans Config Api Client\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"RS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"defaultAcrValues\" : [], \"postLogoutRedirectUris\" : [], \"requestUris\" : [], \"scopes\" : [ \"inum=1800.01.75,ou=scopes,o=jans\" , \"inum=1800.01.76,ou=scopes,o=jans\" , \"inum=1800.01.77,ou=scopes,o=jans\" , \"inum=1800.01.78,ou=scopes,o=jans\" , \"inum=1800.01.71,ou=scopes,o=jans\" , \"inum=1800.01.72,ou=scopes,o=jans\" , ], \"claims\" : [], \"trustedClient\" : false , .... .... .... \"baseDn\" : \"inum=1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe,ou=clients,o=jans\" , \"inum\" : \"1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe\" }, { \"dn\" : \"inum=478049e2-210d-4b64-bc16-10440c973f65,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"37983639-0586-4ed3-8644-b5bc41c4ce49\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://www.google.com/\" ], \"grantTypes\" : [], \"applicationType\" : \"web\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"public\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"trustedClient\" : false , ..... ..... ..... ], \"baseDn\" : \"inum=478049e2-210d-4b64-bc16-10440c973f65,ou=clients,o=jans\" , \"inum\" : \"478049e2-210d-4b64-bc16-10440c973f65\" }, { \"dn\" : \"inum=ec53d411-5243-4c76-b91c-661b35853cd0,ou=clients,o=jans\" , \"deletable\" : false , \"clientSecret\" : \"456e1c1e-796d-4dc0-9f16-7b54c9e4eb5b\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" : [ \"https://docs.jans.io/\" ], \"grantTypes\" : [], \"applicationType\" : \"web\" , \"clientNameLocalized\" : {}, \"logoUriLocalized\" : {}, \"clientUriLocalized\" : {}, \"policyUriLocalized\" : {}, \"tosUriLocalized\" : {}, \"subjectType\" : \"public\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"trustedClient\" : false , ..... ..... ..... \"baseDn\" : \"inum=ec53d411-5243-4c76-b91c-661b35853cd0,ou=clients,o=jans\" , \"inum\" : \"ec53d411-5243-4c76-b91c-661b35853cd0\" } ] } To search using parameters, use the command below: Command jans cli --operation-id get-oauth-openid-clients \\ --endpoint-args limit:2", "title": "Get List of OpenID Connect Clients"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#creating-a-new-openid-connect-clients", "text": "To add an OpenID Connect client, we can use post-oauth-openid-client operation id. As shown in the output for --info command, the post-oauth-openid-client operation requires data to be sent according to Client schema. To see the schema, use the command below: Command jans cli --schema Client The Janssen Server also provides an example of data that adheres to the above schema. To fetch the example, use the command below. Command jans cli --schema-sample Client Using the schema and the example above, we have added OpenID Connect client data to the file /tmp/openid-connect.json . An OpenID Connect client may have many properties, but we are going to fill only the required properties as shown below: Input { \"redirectUris\" : [ \"https://www.google.com/\" ] } Now let's post an OpenID Connect client to the Janssen Server to be added to the existing set: Command jans cli --operation-id post-oauth-openid-client \\ --data /tmp/openid-connect.json", "title": "Creating a New OpenID Connect Clients"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#update-openid-connect-client", "text": "To update the configuration follow the steps below. Get the existing OpenID Connect Client and store it into a file for editing. The following command will retrieve the existing OpenID Connect Client in the schema file. Command jans cli -no-color \\ --operation-id get-oauth-openid-clients-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe > /tmp/update-client.json Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Client schema as mentioned here . We have changed in parLifetime only the 600 to 700 . Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-oauth-openid-client \\ --data /tmp/update-client.json Upon successful execution of the update, the Janssen Server responds with updated configuration", "title": "Update OpenId Connect client"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#patch-openid-connect-client-by-inum", "text": "Using patch-oauth-openid-client-by-inum , we can modify OpenID Connect Clients partially for its properties. To use this operation, specify the inum of the OpenID Connect Client that needs to be updated using the --url-suffix and the property and the new value using the JSON Patch . Refer here to know more about schema. In this example; We will change the value of the property applicationType from web to native . Input 1 2 3 4 5 6 7 [ { \"op\" : \"replace\" , \"path\" : \"applicationType\" , \"value\" : \"native\" } ] Now let's do the operation with the command line. jans cli \\ --operation-id patch-oauth-openid-client-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe --data /tmp/schema.json", "title": "Patch OpenID Connect Client by inum"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#get-openid-connect-client-by-inum", "text": "With get-oauth-openid-clients-by-inum operation-id, we can get any specific OpenID Connect Client matched with Inum . If we know the inum , we can use the below command: jans cli \\ --operation-id get-oauth-openid-clients-by-inum \\ --url-suffix inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe The result will only show details of client with inum:1800.ca57f8f8-e163-4cdc-96f2-e2760e627bfe .", "title": "Get OpenID Connect Client by Inum"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#delete-openid-connect-client", "text": "Delete the OpenID Connect client using its inum . The command line is: Command jans cli \\ --operation-id delete-oauth-openid-client-by-inum \\ --url-suffix inum:a89b5c29-2a91-48b5-bf27-1bf786954a06 It will delete the OpenID Connect client if it matches with the given inum .", "title": "Delete OpenID Connect client"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#using-text-based-ui", "text": "Start TUI using the command below: Command jans tui", "title": "Using Text Based UI"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#client-screen", "text": "Navigate to Auth Server -> Clients to open the client screen as shown in the image below. This screen shows the OpenID Connect Clients list. To get the list of currently added clients, bring the control to Search box (using the tab key), and press the Enter key. Type the search string to search for the client with the matching client name.", "title": "Client Screen"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#add-update-client-screen", "text": "Use the Add Client button to create a new client. After adding the valid data using the Save button, add a new OpenID Connect client. Update the OpenID Connect client as well. To update the client, bring the control to the Specific Client row and press the Enter key, then it will show the edit client screen. If you are editing a client, you will have Active Tokens where you can search and delete tokens related to the edited client as shown image below. To view client details in json format, press key v on keyboard, to delete press delete (or d ) key.", "title": "Add-Update Client screen"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#delete-screen", "text": "To delete the client, bring the control to the Specific Client row and press the Delete key. Then it will show the Delete confirmation box.", "title": "Delete Screen"}, {"location": "janssen-server/config-guide/auth-server-config/openid-connect-client-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/auth-server-config/ssa-config/", "tags": ["administration", "recipes", "open-banking"], "text": "SSA Configuration # This document is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "SSA Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/ssa-config/#ssa-configuration", "text": "This document is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "SSA Configuration"}, {"location": "janssen-server/config-guide/auth-server-config/ssa-config/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/config-guide/auth-server-config/ssa-config/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/", "tags": ["administration", "configuration", "tools", "cli", "curl"], "text": "Most useful configurations and operations on Jans server using CURL # Configuring the Janssen server # To use CURL commands and configure Janssen's Authorization server, you need to have an access token of \"Config-API\" (which is an RP of Jans-auth server). Configurations to the AS can be done only through \"The Config-API client (RP)\". Obtaining an Access token # All commands to configure the AS are protected by an Access token. According to the use case, you must specify the scope for which the access token has been requested. For the client_id and client_secret, contact your administrator. Template curl -u \"client_inum:client_secret\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=put_scope_name_here\" Example : To modify a custom script, you need to request an access token using the scope scope=https://jans.io/oauth/config/scripts.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scripts.write\" Enable an authentication script # Steps # Obtain a token, use scope https://jans.io/oauth/config/scripts.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scripts.write\" Enable the script curl https://<your.jans.server>/jans-config-api/api/v1/config/scripts/name/name_of_the_script \\ -H \"Authorization: Bearer put_access_token_here\" Examples of name_of_the_script ( Authentication methods that are present in the Janssen server.) Name of the script smpp otp duo fido2 super_gluu twilio_sms smpp otp duo fido2 super_gluu Client creation # Creating a client with minimal upfront configuration requires only redirectUris in following format. Add following content in a text file and save it as client.json. { \"redirectUris\" : [ \"http://localhost:8080\" ] } In place of http://localhost:8080 uri used above, any valid redirect URI can be used. To provide full client configuration at the time of creation, Download and use this json format , update the values and save it as client.json. Few important fields to populate are scope , responseTypes , redirectUris (The only mandatory field), grantTypes . If there is a need to update the attributes of the client after creation, then make sure that the client is created with grantTypes list having client_credentials grant type as well. Run curl command curl -X POST https://my.jans.server/jans-auth/restv1/register \\ -H \"Content-Type: application/json\" -d @/some/directory/client.json If client is created successfully, response similar to below will be received: { \"allow_spontaneous_scopes\" : false , \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://my.jans.server/jans-auth/restv1/register?client_id=994ec0a7-1143-456c-85ca-66ba592d7f9a\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"d34f30ff-ae31-4760-8b67-ef071ba9ee68\" , \"client_id\" : \"994ec0a7-1143-456c-85ca-66ba592d7f9a\" , \"token_endpoint_auth_method\" : \"client_secret_basic\" , \"scope\" : \"openid profile permission https://jans.io/auth/ssa.portal uma_protection work_phone phone address test https://jans.io/auth/ssa.admin user_name email clientinfo device_sso org_name https://jans.io/auth/ssa.developer offline_access\" , \"client_secret\" : \"da4c17de-b6bc-4f25-b642-4c7b887c7860\" , \"client_id_issued_at\" : 1672221633 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"par_lifetime\" : 600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : false , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" ], \"subject_type\" : \"pairwise\" , \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1672308033 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" ] } Response contains client_id and client_secret apart from other client configuration details. Get Client Details # Obtain an Access Token with scope https://jans.io/oauth/config/openid/clients.readonly . curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/openid/clients.readonly\" Obtain client information using: curl -X GET https://my.jans.server/jans-config-api/api/v1/openid/clients/client-s_inum_for_which_scope_to_be_added -H \"Authorization: Bearer put_access_token_here\" This will return JSON response similar to the one below. { \"dn\" : \"inum=994ec0a7-1143-456c-85ca-66ba592d7f9a,ou=clients,o=jans\" , \"expirationDate\" : \"2022-12-29T10:00:33\" , \"deletable\" : true , \"clientSecret\" : \"5Mlvuh0JRwl/WcpiUNGGXjtDO4+SprNBjiVFFcWqWB4gu7gYxqcSMw==\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" :[ \"http://localhost:8080\" ], \"responseTypes\" :[ \"code\" ], \"grantTypes\" :[ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"applicationType\" : \"web\" , \"clientName\" : \"dd-test-client\" , \"clientNameLocalized\" :{ }, \"logoUriLocalized\" :{ }, \"clientUriLocalized\" :{ }, \"policyUriLocalized\" :{ }, \"tosUriLocalized\" :{ }, \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"RS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"scopes\" :[ \"inum=F0C4,ou=scopes,o=jans\" , \"inum=43F1,ou=scopes,o=jans\" , \"inum=C4F5,ou=scopes,o=jans\" , \"inum=SSA1-PTL1,ou=scopes,o=jans\" , \"inum=6D99,ou=scopes,o=jans\" , \"inum=7D02,ou=scopes,o=jans\" , \"inum=D491,ou=scopes,o=jans\" , \"inum=C17A,ou=scopes,o=jans\" , \"inum=0465-1DEA,ou=scopes,o=jans\" , \"inum=SSA1-AD01,ou=scopes,o=jans\" , \"inum=10B2,ou=scopes,o=jans\" , \"inum=764C,ou=scopes,o=jans\" , \"inum=341A,ou=scopes,o=jans\" , \"inum=C4F8,ou=scopes,o=jans\" , \"inum=7D01,ou=scopes,o=jans\" , \"inum=SSA1-DEV1,ou=scopes,o=jans\" , \"inum=C4F6,ou=scopes,o=jans\" ], \"trustedClient\" : false , \"persistClientAuthorizations\" : true , \"includeClaimsInIdToken\" : false , \"customAttributes\" :[ ], \"customObjectClasses\" :[ \"top\" ], \"rptAsJwt\" : false , \"accessTokenAsJwt\" : false , \"accessTokenSigningAlg\" : \"RS256\" , \"disabled\" : false , \"attributes\" :{ \"runIntrospectionScriptBeforeJwtCreation\" : false , \"keepClientAuthorizationAfterExpiration\" : false , \"allowSpontaneousScopes\" : false , \"backchannelLogoutSessionRequired\" : false , \"parLifetime\" : 600 , \"requirePar\" : false , \"jansDefaultPromptLogin\" : false , \"minimumAcrLevel\" : -1 }, \"backchannelTokenDeliveryMode\" : \"poll\" , \"backchannelUserCodeParameter\" : false , \"displayName\" : \"dd-test-client\" , \"authenticationMethod\" : \"client_secret_basic\" , \"baseDn\" : \"inum=994ec0a7-1143-456c-85ca-66ba592d7f9a,ou=clients,o=jans\" , \"inum\" : \"994ec0a7-1143-456c-85ca-66ba592d7f9a\" } Add New Scope to Client # To the above client, lets append the profile, so the scope attrib should now have value \"openid user_name profile\"`. This new value will be patched onto the client. Obtain an Access Token with scope https://jans.io/oauth/config/openid/clients.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/openid/clients.write\" Patch the new scope for the client curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://my.jans.server/jans-config-api/api/v1/openid/clients/put_client_inum_here' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"/scope\", \"value\": \"openid user_name profile\" } ]' Add OpenID scope and map to database attribute # Obtain access token curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scopes.write\" Build json on similar lines { \"dn\": \"string\", \"inum\": \"string\", \"displayName\": \"string\", \"id\": \"string\", \"iconUrl\": \"string\", \"description\": \"string\", \"scopeType\": \"openid\", \"claims\": [ \"string\" ], \"defaultScope\": true, \"groupClaims\": true, \"dynamicScopeScripts\": [ \"string\" ], \"umaAuthorizationPolicies\": [ \"string\" ], \"attributes\": { \"spontaneousClientId\": \"string\", \"spontaneousClientScopes\": [ \"string\" ], \"showInConfigurationEndpoint\": true }, \"umaType\": false, \"deletable\": false, \"expirationDate\": \"2022-07-26\" } Run curl. Note the claims field which maps to the database attrib curl -k -X POST https://jans-ui.jans.io/jans-config-api/api/v1/scopes -H \"Content-Type: application/json\" -H \"Authorization: Bearer use_bearer_token_here\" --data '{ \"dn\": \"inum=AAC1,ou=scopes,o=jans\", \"inum\": \"AAC1\", \"displayName\": \"website\", \"id\": \"website\", \"description\": \"website\", \"scopeType\": \"openid\", \"claims\": [\"website\"], \"umaType\": false, \"deletable\": false }' Using the Janssen server # Accessing OpenID Discovery endpoint / Well-known endpoint # curl https://jans-ui.jans.io/.well-known/openid-configuration Client Credentials Flow # curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scopes.write\" Authorization code flow # Steps: On a browser type https://my.jans.server/jans-auth/restv1/authorize?redirect_uri=https://my-redirect-app:8080&client_id=Put_client_id_here&scope=username+openid&response_type=code Based on the default authentication method set, the user will be presented with credentials for login. The OpenID Provider (Gluu Server) verifies the user\u2019s identity and authenticates the user. In the back channel the following steps take place : The OpenID Provider (Gluu Server) sends the user back to the application with an authorization code. The application sends the code to the Token Endpoint to receive an Access Token and ID Token in the response. The application uses the ID Token to authorize the user. At this point the application/RP can access the UserInfo endpoint for claims. Device Authorization code flow # Client_id that is used in the curl command below should have grant_type urn:ietf:params:oauth:grant-type:device_code Call the Device Authorization Endpoint : curl -k -u \"client_id_here:client_secret_here\" https://jans-ui.jans.io/jans-auth/restv1/device_authorization \\ -d scope=openid+profile+email+offline_access\" Response received will be like this { \"user_code\": \"HJDN-BMHQ\", \"device_code\": \"b8a5e5e6b1c10506af4f4bbb5400ca2587dcfe44974d7e62\", \"interval\": 5, \"verification_uri_complete\": \"https://jans-ui.jans.io/device-code?user_code=HJDN-BMHQ\", \"verification_uri\": \"https://jans-ui.jans.io/device-code\", \"expires_in\": 1800 } User should visit the verification_uri link on a browser and enter the user_code . Until the user to activates the device, begin polling token URL to request an Access Token. Use interval from step 2 as the polling interval. curl -k -u \"client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=YOUR_DEVICE_CODE&client_id=YOUR_CLIENT_ID\"", "title": "CURL"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#most-useful-configurations-and-operations-on-jans-server-using-curl", "text": "", "title": "Most useful configurations and operations on Jans server using CURL"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#configuring-the-janssen-server", "text": "To use CURL commands and configure Janssen's Authorization server, you need to have an access token of \"Config-API\" (which is an RP of Jans-auth server). Configurations to the AS can be done only through \"The Config-API client (RP)\".", "title": "Configuring the Janssen server"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#obtaining-an-access-token", "text": "All commands to configure the AS are protected by an Access token. According to the use case, you must specify the scope for which the access token has been requested. For the client_id and client_secret, contact your administrator. Template curl -u \"client_inum:client_secret\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=put_scope_name_here\" Example : To modify a custom script, you need to request an access token using the scope scope=https://jans.io/oauth/config/scripts.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scripts.write\"", "title": "Obtaining an Access token"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#enable-an-authentication-script", "text": "", "title": "Enable an authentication script"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#steps", "text": "Obtain a token, use scope https://jans.io/oauth/config/scripts.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scripts.write\" Enable the script curl https://<your.jans.server>/jans-config-api/api/v1/config/scripts/name/name_of_the_script \\ -H \"Authorization: Bearer put_access_token_here\" Examples of name_of_the_script ( Authentication methods that are present in the Janssen server.) Name of the script smpp otp duo fido2 super_gluu twilio_sms smpp otp duo fido2 super_gluu", "title": "Steps"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#client-creation", "text": "Creating a client with minimal upfront configuration requires only redirectUris in following format. Add following content in a text file and save it as client.json. { \"redirectUris\" : [ \"http://localhost:8080\" ] } In place of http://localhost:8080 uri used above, any valid redirect URI can be used. To provide full client configuration at the time of creation, Download and use this json format , update the values and save it as client.json. Few important fields to populate are scope , responseTypes , redirectUris (The only mandatory field), grantTypes . If there is a need to update the attributes of the client after creation, then make sure that the client is created with grantTypes list having client_credentials grant type as well. Run curl command curl -X POST https://my.jans.server/jans-auth/restv1/register \\ -H \"Content-Type: application/json\" -d @/some/directory/client.json If client is created successfully, response similar to below will be received: { \"allow_spontaneous_scopes\" : false , \"application_type\" : \"web\" , \"rpt_as_jwt\" : false , \"registration_client_uri\" : \"https://my.jans.server/jans-auth/restv1/register?client_id=994ec0a7-1143-456c-85ca-66ba592d7f9a\" , \"tls_client_auth_subject_dn\" : \"\" , \"run_introspection_script_before_jwt_creation\" : false , \"registration_access_token\" : \"d34f30ff-ae31-4760-8b67-ef071ba9ee68\" , \"client_id\" : \"994ec0a7-1143-456c-85ca-66ba592d7f9a\" , \"token_endpoint_auth_method\" : \"client_secret_basic\" , \"scope\" : \"openid profile permission https://jans.io/auth/ssa.portal uma_protection work_phone phone address test https://jans.io/auth/ssa.admin user_name email clientinfo device_sso org_name https://jans.io/auth/ssa.developer offline_access\" , \"client_secret\" : \"da4c17de-b6bc-4f25-b642-4c7b887c7860\" , \"client_id_issued_at\" : 1672221633 , \"backchannel_logout_uri\" : \"\" , \"backchannel_logout_session_required\" : false , \"par_lifetime\" : 600 , \"spontaneous_scopes\" : [], \"id_token_signed_response_alg\" : \"RS256\" , \"access_token_as_jwt\" : false , \"grant_types\" : [ \"authorization_code\" , \"refresh_token\" ], \"subject_type\" : \"pairwise\" , \"keep_client_authorization_after_expiration\" : false , \"require_par\" : false , \"redirect_uris_regex\" : \"\" , \"additional_audience\" : [], \"frontchannel_logout_session_required\" : false , \"client_secret_expires_at\" : 1672308033 , \"access_token_signing_alg\" : \"RS256\" , \"response_types\" : [ \"code\" ] } Response contains client_id and client_secret apart from other client configuration details.", "title": "Client creation"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#get-client-details", "text": "Obtain an Access Token with scope https://jans.io/oauth/config/openid/clients.readonly . curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/openid/clients.readonly\" Obtain client information using: curl -X GET https://my.jans.server/jans-config-api/api/v1/openid/clients/client-s_inum_for_which_scope_to_be_added -H \"Authorization: Bearer put_access_token_here\" This will return JSON response similar to the one below. { \"dn\" : \"inum=994ec0a7-1143-456c-85ca-66ba592d7f9a,ou=clients,o=jans\" , \"expirationDate\" : \"2022-12-29T10:00:33\" , \"deletable\" : true , \"clientSecret\" : \"5Mlvuh0JRwl/WcpiUNGGXjtDO4+SprNBjiVFFcWqWB4gu7gYxqcSMw==\" , \"frontChannelLogoutSessionRequired\" : false , \"redirectUris\" :[ \"http://localhost:8080\" ], \"responseTypes\" :[ \"code\" ], \"grantTypes\" :[ \"authorization_code\" , \"refresh_token\" , \"client_credentials\" ], \"applicationType\" : \"web\" , \"clientName\" : \"dd-test-client\" , \"clientNameLocalized\" :{ }, \"logoUriLocalized\" :{ }, \"clientUriLocalized\" :{ }, \"policyUriLocalized\" :{ }, \"tosUriLocalized\" :{ }, \"subjectType\" : \"pairwise\" , \"idTokenSignedResponseAlg\" : \"RS256\" , \"tokenEndpointAuthMethod\" : \"client_secret_basic\" , \"scopes\" :[ \"inum=F0C4,ou=scopes,o=jans\" , \"inum=43F1,ou=scopes,o=jans\" , \"inum=C4F5,ou=scopes,o=jans\" , \"inum=SSA1-PTL1,ou=scopes,o=jans\" , \"inum=6D99,ou=scopes,o=jans\" , \"inum=7D02,ou=scopes,o=jans\" , \"inum=D491,ou=scopes,o=jans\" , \"inum=C17A,ou=scopes,o=jans\" , \"inum=0465-1DEA,ou=scopes,o=jans\" , \"inum=SSA1-AD01,ou=scopes,o=jans\" , \"inum=10B2,ou=scopes,o=jans\" , \"inum=764C,ou=scopes,o=jans\" , \"inum=341A,ou=scopes,o=jans\" , \"inum=C4F8,ou=scopes,o=jans\" , \"inum=7D01,ou=scopes,o=jans\" , \"inum=SSA1-DEV1,ou=scopes,o=jans\" , \"inum=C4F6,ou=scopes,o=jans\" ], \"trustedClient\" : false , \"persistClientAuthorizations\" : true , \"includeClaimsInIdToken\" : false , \"customAttributes\" :[ ], \"customObjectClasses\" :[ \"top\" ], \"rptAsJwt\" : false , \"accessTokenAsJwt\" : false , \"accessTokenSigningAlg\" : \"RS256\" , \"disabled\" : false , \"attributes\" :{ \"runIntrospectionScriptBeforeJwtCreation\" : false , \"keepClientAuthorizationAfterExpiration\" : false , \"allowSpontaneousScopes\" : false , \"backchannelLogoutSessionRequired\" : false , \"parLifetime\" : 600 , \"requirePar\" : false , \"jansDefaultPromptLogin\" : false , \"minimumAcrLevel\" : -1 }, \"backchannelTokenDeliveryMode\" : \"poll\" , \"backchannelUserCodeParameter\" : false , \"displayName\" : \"dd-test-client\" , \"authenticationMethod\" : \"client_secret_basic\" , \"baseDn\" : \"inum=994ec0a7-1143-456c-85ca-66ba592d7f9a,ou=clients,o=jans\" , \"inum\" : \"994ec0a7-1143-456c-85ca-66ba592d7f9a\" }", "title": "Get Client Details"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#add-new-scope-to-client", "text": "To the above client, lets append the profile, so the scope attrib should now have value \"openid user_name profile\"`. This new value will be patched onto the client. Obtain an Access Token with scope https://jans.io/oauth/config/openid/clients.write curl -u \"put_client_id_here:put_config_api_client_secret_here\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/openid/clients.write\" Patch the new scope for the client curl -X PATCH -k -H 'Content-Type: application/json-patch+json' \\ -i 'https://my.jans.server/jans-config-api/api/v1/openid/clients/put_client_inum_here' \\ -H \"Authorization: Bearer put_access_token_here\" --data '[ { \"op\": \"add\", \"path\": \"/scope\", \"value\": \"openid user_name profile\" } ]'", "title": "Add New Scope to Client"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#add-openid-scope-and-map-to-database-attribute", "text": "Obtain access token curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scopes.write\" Build json on similar lines { \"dn\": \"string\", \"inum\": \"string\", \"displayName\": \"string\", \"id\": \"string\", \"iconUrl\": \"string\", \"description\": \"string\", \"scopeType\": \"openid\", \"claims\": [ \"string\" ], \"defaultScope\": true, \"groupClaims\": true, \"dynamicScopeScripts\": [ \"string\" ], \"umaAuthorizationPolicies\": [ \"string\" ], \"attributes\": { \"spontaneousClientId\": \"string\", \"spontaneousClientScopes\": [ \"string\" ], \"showInConfigurationEndpoint\": true }, \"umaType\": false, \"deletable\": false, \"expirationDate\": \"2022-07-26\" } Run curl. Note the claims field which maps to the database attrib curl -k -X POST https://jans-ui.jans.io/jans-config-api/api/v1/scopes -H \"Content-Type: application/json\" -H \"Authorization: Bearer use_bearer_token_here\" --data '{ \"dn\": \"inum=AAC1,ou=scopes,o=jans\", \"inum\": \"AAC1\", \"displayName\": \"website\", \"id\": \"website\", \"description\": \"website\", \"scopeType\": \"openid\", \"claims\": [\"website\"], \"umaType\": false, \"deletable\": false }'", "title": "Add OpenID scope and map to database attribute"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#using-the-janssen-server", "text": "", "title": "Using the Janssen server"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#accessing-openid-discovery-endpoint-well-known-endpoint", "text": "curl https://jans-ui.jans.io/.well-known/openid-configuration", "title": "Accessing OpenID Discovery endpoint / Well-known endpoint"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#client-credentials-flow", "text": "curl -k -u \"put_client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/scopes.write\"", "title": "Client Credentials Flow"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#authorization-code-flow", "text": "Steps: On a browser type https://my.jans.server/jans-auth/restv1/authorize?redirect_uri=https://my-redirect-app:8080&client_id=Put_client_id_here&scope=username+openid&response_type=code Based on the default authentication method set, the user will be presented with credentials for login. The OpenID Provider (Gluu Server) verifies the user\u2019s identity and authenticates the user. In the back channel the following steps take place : The OpenID Provider (Gluu Server) sends the user back to the application with an authorization code. The application sends the code to the Token Endpoint to receive an Access Token and ID Token in the response. The application uses the ID Token to authorize the user. At this point the application/RP can access the UserInfo endpoint for claims.", "title": "Authorization code flow"}, {"location": "janssen-server/config-guide/config-tools/curl-guide/#device-authorization-code-flow", "text": "Client_id that is used in the curl command below should have grant_type urn:ietf:params:oauth:grant-type:device_code Call the Device Authorization Endpoint : curl -k -u \"client_id_here:client_secret_here\" https://jans-ui.jans.io/jans-auth/restv1/device_authorization \\ -d scope=openid+profile+email+offline_access\" Response received will be like this { \"user_code\": \"HJDN-BMHQ\", \"device_code\": \"b8a5e5e6b1c10506af4f4bbb5400ca2587dcfe44974d7e62\", \"interval\": 5, \"verification_uri_complete\": \"https://jans-ui.jans.io/device-code?user_code=HJDN-BMHQ\", \"verification_uri\": \"https://jans-ui.jans.io/device-code\", \"expires_in\": 1800 } User should visit the verification_uri link on a browser and enter the user_code . Until the user to activates the device, begin polling token URL to request an Access Token. Use interval from step 2 as the polling interval. curl -k -u \"client_id:put_client_secret\" https://jans-ui.jans.io/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=YOUR_DEVICE_CODE&client_id=YOUR_CLIENT_ID\"", "title": "Device Authorization code flow"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/", "tags": ["administration", "tools", "config-api", "attributes"], "text": "Attributes # Attributes are individual pieces of user data, like uid or email, that are required by applications in order to identify a user and grant access to protected resources. In OpenID Connect, these are called user claims. Listing existing attributes # GET / (gets list of attributes based on search parameters) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|---------------------------------------------------------------------------------| > | limit | query | integer | optional |50 |Search size - max size of the results to return | > | pattern | query | string | optional |N/A |Comma separated search patter. E.g. `pattern=edu`, `pattern=edu,locale,License` | > | status | query | string | optional |all |Search size - max size of the results to return | > | startIndex | query | integer | optional |1 |Index of the first query result | > | sortBy | query | string | optional |inum |Field whose value will be used to order the returned response | > | sortOrder | query | string | optional |ascending |Search size - max size of the results to return | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `200` | `application/json` | `Paginated result` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 697479e0-e6f4-453d-bf7a-ddf31b53efba\" - X GET http : //my.jans.server/jans-config-api/api/v1/attributes?limit=5&pattern=edu,locale,carLicense&startIndex=1 ### Sample Response > { \"start\" : 0 , \"totalEntriesCount\" : 78 , \"entriesCount\" : 2 , \"entries\" : [ { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" }, { \"dn\" : \"inum=0C18,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"0C18\" , \"name\" : \"telephoneNumber\" , \"displayName\" : \"Home Telephone Number\" , \"description\" : \"Home Telephone Number\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"user\" , \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"phone_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:telephoneNumber\" , \"saml2Uri\" : \"urn:oid:2.5.4.20\" , \"urn\" : \"urn:mace:dir:attribute-def:phone_number\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : true , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=0C18,ou=attributes,o=jans\" } } GET /{inum} (gets attribute based on inum) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | `inum` | path | string | required | NA | Attribute unique identifier | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 697479e0-e6f4-453d-bf7a-ddf31b53efba\" - X GET http : //my.jans.server/jans-config-api/api/v1/attributes/08E2 ### Sample Response > { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" } Creating new attribute # POST /{inum} (creates a new attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | None | request | object (JSON) | required | NA | Attribute json | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `201` | `application/json ` | `attribute details json` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X POST - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes' -- data @ post . json ### Sample Request > { \"adminCanAccess\" : true , \"adminCanEdit\" : true , \"adminCanView\" : true , \"custom\" : false , \"dataType\" : \"string\" , \"description\" : \"QAAdded Attribute\" , \"displayName\" : \"QAAdded Attribute\" , \"editType\" : [ \"admin\" , \"user\" ], \"name\" : \"qaattribute\" , \"origin\" : \"jansPerson\" , \"jansMultivaluedAttr\" : false , \"status\" : \"active\" , \"urn\" : \"urn:mace:dir:attribute-def:qaattribute\" , \"userCanAccess\" : true , \"userCanEdit\" : true , \"userCanView\" : true , \"viewType\" : [ \"admin\" , \"user\" ], \"whitePagesCanView\" : false } Updating existing attribute # PUT /{inum} (updates an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | None | request | object (JSON) | required | NA | Attribute json | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X PUT - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes' -- data @ put . json ### Sample Request > { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" } Patching existing attribute # PATCH /{inum} (patches an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|--------------------|-----------|--------------|----------------------------------------| > | inum | path | string | required | NA | Attribute unique identifier | > | None | request | json-patch object | required | NA | json-patch request | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X PATCH - k - H 'Content-Type: application/json-patch+json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes/08E2' -- data @ patch . json ### Sample Request > [ { \"op\" : \"replace\" , \"path\" : \"/displayName\" , \"value\" : \"PatchCustomAttribute123\" } ] Deleting existing attribute # DELETE /{inum} (deletes an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|--------------------|-----------|--------------|----------------------------------------| > | inum | path | string | required | NA | Attribute unique identifier | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `204` | `application/json ` | `No Content` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X DELETE - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes/08E2' ### Sample Request > None", "title": "Attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#attributes", "text": "Attributes are individual pieces of user data, like uid or email, that are required by applications in order to identify a user and grant access to protected resources. In OpenID Connect, these are called user claims.", "title": "Attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#listing-existing-attributes", "text": "GET / (gets list of attributes based on search parameters) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|---------------------------------------------------------------------------------| > | limit | query | integer | optional |50 |Search size - max size of the results to return | > | pattern | query | string | optional |N/A |Comma separated search patter. E.g. `pattern=edu`, `pattern=edu,locale,License` | > | status | query | string | optional |all |Search size - max size of the results to return | > | startIndex | query | integer | optional |1 |Index of the first query result | > | sortBy | query | string | optional |inum |Field whose value will be used to order the returned response | > | sortOrder | query | string | optional |ascending |Search size - max size of the results to return | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `200` | `application/json` | `Paginated result` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 697479e0-e6f4-453d-bf7a-ddf31b53efba\" - X GET http : //my.jans.server/jans-config-api/api/v1/attributes?limit=5&pattern=edu,locale,carLicense&startIndex=1 ### Sample Response > { \"start\" : 0 , \"totalEntriesCount\" : 78 , \"entriesCount\" : 2 , \"entries\" : [ { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" }, { \"dn\" : \"inum=0C18,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"0C18\" , \"name\" : \"telephoneNumber\" , \"displayName\" : \"Home Telephone Number\" , \"description\" : \"Home Telephone Number\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"user\" , \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"phone_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:telephoneNumber\" , \"saml2Uri\" : \"urn:oid:2.5.4.20\" , \"urn\" : \"urn:mace:dir:attribute-def:phone_number\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : true , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=0C18,ou=attributes,o=jans\" } } GET /{inum} (gets attribute based on inum) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | `inum` | path | string | required | NA | Attribute unique identifier | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 697479e0-e6f4-453d-bf7a-ddf31b53efba\" - X GET http : //my.jans.server/jans-config-api/api/v1/attributes/08E2 ### Sample Response > { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" }", "title": "Listing existing attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#creating-new-attribute", "text": "POST /{inum} (creates a new attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | None | request | object (JSON) | required | NA | Attribute json | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|---------------------------------------------------------------------| > | `201` | `application/json ` | `attribute details json` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X POST - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes' -- data @ post . json ### Sample Request > { \"adminCanAccess\" : true , \"adminCanEdit\" : true , \"adminCanView\" : true , \"custom\" : false , \"dataType\" : \"string\" , \"description\" : \"QAAdded Attribute\" , \"displayName\" : \"QAAdded Attribute\" , \"editType\" : [ \"admin\" , \"user\" ], \"name\" : \"qaattribute\" , \"origin\" : \"jansPerson\" , \"jansMultivaluedAttr\" : false , \"status\" : \"active\" , \"urn\" : \"urn:mace:dir:attribute-def:qaattribute\" , \"userCanAccess\" : true , \"userCanEdit\" : true , \"userCanView\" : true , \"viewType\" : [ \"admin\" , \"user\" ], \"whitePagesCanView\" : false }", "title": "Creating new attribute"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#updating-existing-attribute", "text": "PUT /{inum} (updates an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|----------------|-----------|--------------|----------------------------------------| > | None | request | object (JSON) | required | NA | Attribute json | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X PUT - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes' -- data @ put . json ### Sample Request > { \"dn\" : \"inum=08E2,ou=attributes,o=jans\" , \"selected\" : false , \"inum\" : \"08E2\" , \"name\" : \"departmentNumber\" , \"displayName\" : \"Department\" , \"description\" : \"Organizational Department\" , \"origin\" : \"jansCustomPerson\" , \"dataType\" : \"string\" , \"editType\" : [ \"admin\" ], \"viewType\" : [ \"user\" , \"admin\" ], \"claimName\" : \"department_number\" , \"status\" : \"inactive\" , \"saml1Uri\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"saml2Uri\" : \"urn:oid:2.16.840.1.113730.3.1.2\" , \"urn\" : \"urn:mace:dir:attribute-def:departmentNumber\" , \"oxMultiValuedAttribute\" : false , \"custom\" : false , \"whitePagesCanView\" : false , \"adminCanEdit\" : true , \"userCanView\" : true , \"userCanEdit\" : false , \"adminCanAccess\" : true , \"adminCanView\" : true , \"userCanAccess\" : true , \"baseDn\" : \"inum=08E2,ou=attributes,o=jans\" }", "title": "Updating existing attribute"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#patching-existing-attribute", "text": "PATCH /{inum} (patches an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|--------------------|-----------|--------------|----------------------------------------| > | inum | path | string | required | NA | Attribute unique identifier | > | None | request | json-patch object | required | NA | json-patch request | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `200` | `application/json ` | `attribute details` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X PATCH - k - H 'Content-Type: application/json-patch+json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes/08E2' -- data @ patch . json ### Sample Request > [ { \"op\" : \"replace\" , \"path\" : \"/displayName\" , \"value\" : \"PatchCustomAttribute123\" } ]", "title": "Patching existing attribute"}, {"location": "janssen-server/config-guide/config-tools/config-api/attribute/#deleting-existing-attribute", "text": "DELETE /{inum} (deletes an existing attribute) ### Parameters > | name | param type | data type | type |default value | description | > |------------|-------------|--------------------|-----------|--------------|----------------------------------------| > | inum | path | string | required | NA | Attribute unique identifier | ### Responses > | http code | content-type | response | > |---------------|-----------------------------------|------------------------------------------------------------------------| > | `204` | `application/json ` | `No Content` | > | `404` | `application/json` | `{\"code\":\"404\",\"message\":\"The requested doesn't exist\"}` | > | `401` | `application/json` | `{\"code\":\"401\",\"message\":\"Unauthorized\"}` | > | `500` | `application/json` | `{\"code\":\"500\",\"message\":\"Error msg\"}` | ### Example cURL > curl - X DELETE - k - H 'Content-Type: application/json' - H 'Authorization: Bearer ba9b8810-7a2b-4e4a-a18a-689d7eacf7d1' - i 'https://my.jans.server/jans-config-api/api/v1/attributes/08E2' ### Sample Request > None", "title": "Deleting existing attribute"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/", "tags": ["administration", "tools", "configuration", "config-api"], "text": "Janssen Config-API Configuration # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and customize the Config-API Configuration using the command line. To get the details of Janssen command line operations relevant to Config-API Configuration, you can check the operations under ConfigurationConfigApi task using the command below: Command jans tui --info ConfigurationConfigApi It will show the details of the available operation-ids for Config-API. Sample Output Operation ID: get-config-api-properties Description: Gets config-api configuration properties. Operation ID: patch-config-api-properties Description: Partially modifies config-api Configuration properties. Schema: Array of JsonPatch To get sample schema type jans tui --schema-sample <schema>, for example jans tui --schema-sample JsonPatch Get The Current Config-API Configuration # Configuration for Config-API is a set of key-value pairs, called properties. When we retrieve the configuration, these properties and their current values are returned as a JSON document. To get the properties of Janssen Config-API Configuration, run the command below: Command jans tui --operation-id = get-config-api-properties It will return the result as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 { \"serviceName\" : \"jans-config-api\" , \"configOauthEnabled\" : true , \"disableLoggerTimer\" : false , \"disableAuditLogger\" : false , \"customAttributeValidationEnabled\" : true , \"acrValidationEnabled\" : true , \"apiApprovedIssuer\" : [ \"https://example.jans.io\" ], \"apiProtectionType\" : \"oauth2\" , \"apiClientId\" : \"1800.b62cb614-a09d-4163-a6bc-32e38a51c4d2\" , \"apiClientPassword\" : \"CN8ggRUhMkw9K0ocQ+LXbA==\" , \"endpointInjectionEnabled\" : false , \"authIssuerUrl\" : \"https://example.jans.io\" , \"authOpenidConfigurationUrl\" : \"https://example.jans.io/.well-known/openid-configuration\" , \"authOpenidIntrospectionUrl\" : \"https://example.jans.io/jans-auth/restv1/introspection\" , \"authOpenidTokenUrl\" : \"https://example.jans.io/jans-auth/restv1/token\" , \"authOpenidRevokeUrl\" : \"https://example.jans.io/jans-auth/restv1/revoke\" , \"exclusiveAuthScopes\" : [ \"jans_stat\" , \"https://jans.io/scim/users.read\" , \"https://jans.io/scim/users.write\" ], \"corsConfigurationFilters\" : [ { \"filterName\" : \"CorsFilter\" , \"corsEnabled\" : true , \"corsAllowedOrigins\" : \"*\" , \"corsAllowedMethods\" : \"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\" , \"corsSupportCredentials\" : true , \"corsLoggingEnabled\" : false , \"corsPreflightMaxAge\" : 1800 , \"corsRequestDecorate\" : true } ], \"loggingLevel\" : \"INFO\" , \"loggingLayout\" : \"text\" , \"disableJdkLogger\" : true , \"maxCount\" : 200 , \"acrExclusionList\" : [ \"simple_password_auth\" ], \"userExclusionAttributes\" : [ \"userPassword\" ], \"userMandatoryAttributes\" : [ \"mail\" , \"displayName\" , \"status\" , \"userPassword\" , \"givenName\" ], \"agamaConfiguration\" : { \"mandatoryAttributes\" : [ \"qname\" , \"source\" ], \"optionalAttributes\" : [ \"serialVersionUID\" , \"enabled\" ] }, \"auditLogConf\" : { \"enabled\" : true , \"headerAttributes\" : [ \"User-inum\" ] }, \"dataFormatConversionConf\" : { \"enabled\" : true , \"ignoreHttpMethod\" : [ \"@jakarta.ws.rs.GET()\" ] }, \"plugins\" : [ { \"name\" : \"admin\" , \"description\" : \"admin-ui plugin\" , \"className\" : \"io.jans.ca.plugin.adminui.rest.ApiApplication\" }, { \"name\" : \"fido2\" , \"description\" : \"fido2 plugin\" , \"className\" : \"io.jans.configapi.plugin.fido2.rest.ApiApplication\" }, { \"name\" : \"scim\" , \"description\" : \"scim plugin\" , \"className\" : \"io.jans.configapi.plugin.scim.rest.ApiApplication\" }, { \"name\" : \"user-management\" , \"description\" : \"user-management plugin\" , \"className\" : \"io.jans.configapi.plugin.mgt.rest.ApiApplication\" }, { \"name\" : \"jans-link\" , \"description\" : \"jans-link plugin\" , \"className\" : \"io.jans.configapi.plugin.link.rest.ApiApplication\" }, { \"name\" : \"saml\" , \"description\" : \"saml plugin\" , \"className\" : \"io.jans.configapi.plugin.saml.rest.ApiApplication\" }, { \"name\" : \"kc-link\" , \"description\" : \"kc-link plugin\" , \"className\" : \"io.jans.configapi.plugin.kc.link.rest.ApiApplication\" }, { \"name\" : \"lock\" , \"description\" : \"lock plugin\" , \"className\" : \"io.jans.configapi.plugin.lock.rest.ApiApplication\" } ], \"assetMgtConfiguration\" : { \"assetMgtEnabled\" : true , \"assetServerUploadEnabled\" : true , \"fileExtensionValidationEnabled\" : true , \"moduleNameValidationEnabled\" : true , \"assetBaseDirectory\" : \"/opt/jans/jetty/%s/custom\" , \"jansServiceModule\" : [ \"jans-auth\" , \"jans-config-api\" , \"jans-fido2\" , \"jans-scim\" ], \"assetDirMapping\" : [ { \"directory\" : \"i18n\" , \"type\" : [ \"properties\" ], \"description\" : \"Resource bundle file.\" }, { \"directory\" : \"libs\" , \"type\" : [ \"jar\" /op t /ja ns /ja ns - cli/co nf ig - cli.py -- i nf o Co nf igura t io n Co nf igApi ], \"description\" : \"java archive library.\" }, { \"directory\" : \"pages\" , \"type\" : [ \"xhtml\" ], \"description\" : \"Web pages.\" }, { \"directory\" : \"static\" , \"type\" : [ \"js\" , \"css\" , \"png\" , \"gif\" , \"jpg\" , \"jpeg\" ], \"description\" : \"Static resources like Java-script, style-sheet and images.\" } ] } } Update Config-API Configuration Properties # To update the configuration, we will use JSON patch schema as shown below. Let's say we want to stop the file extension validation done by config-api's asset management module. This can be done by setting the fileExtensionValidationEnabled property to false . To do that, write a text file ( config-api-assetmgt-patch.json ) with the content that follows the JSON patch schema. config-api-assetmgt-patch.json 1 2 3 4 5 6 7 [ { \"op\" : \"replace\" , \"path\" : \"/assetMgtConfiguration/fileExtensionValidationEnabled\" , \"value\" : false } ] Now, execute the following command to apply this patch: Command jans tui \\ --operation-id = patch-config-api-properties --data ./config-api-assetmgt-patch.json Upon successful execution of the update, the Janssen Server responds with updated configuration. Updating multi-valued property # Let's say we want to update the configuration property userMandatoryAttributes . This property's value is a list of attributes. We want to remove an attribute from the list. For this, we will have to create a JSON patch file that contains the new list and then run a command to push the update to the Janssen Server. Let's do this step-by-step: Get the current value list for userMandatoryAttributes property using steps mentioned in Get the current configuration section Using the current list of values as a starting point, create a JSON patch file config-api-patch.json as below. Update the list as desired by adding or removing items from the list: Sample Contents 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [ { \"op\" : \"replace\" , \"path\" : \"/userMandatoryAttributes\" , \"value\" : [ \"mail\" , \"displayName\" , \"status\" , \"userPassword\" , \"givenName\" , \"gender\" ] } ] Now, execute the following command to apply this patch: Command jans tui \\ --operation-id = patch-config-api-properties --data ./config-api-patch.json Config API Configuration Parameters: # The table below outlines the key configuration parameters for the Jans Config API. It details settings for OAuth2, security, endpoints, logging, and plugin management. Field named Example Description configOauthEnabled true property can be used to enable or disable the oAuth2 authorization. By default, it is set to true. apiApprovedIssuer [\"https:// ,https:// ,https:// \"] Enables to set more than one authorization servers. By default, the current auth-server is set. You can add more servers separated by commas. apiProtectionType oauth2 Currently support mechanism is OAuth 2.0 tokens. apiClientId 1800.52eb1bed-ab5c-4ba6-b87e-90aad26058d0 Jans Config API Client. apiClientPassword lwI/8mcMkF63mvueYTZ0mQ== Encrypted secret of Jans Config API Client endpointInjectionEnabled false To be used if the endpoint needs to be injected. authIssuerUrl https://my-jans-server.jans.io URL of underlying auth-server. authOpenidConfigurationUrl https://my-jans-server.jans.io/.well-known/openid-configuration Metadata URL of the authorization server. authOpenidIntrospectionUrl https://my-jans-server.jans.io/jans-auth/restv1/introspection Authorization server endpoint to check the state of an OAuth 2.0 token and to determine meta-information about the token. authOpenidTokenUrl https://my-jans-server.jans.io/jans-auth/restv1/token Authorization server endpoint to obtain an Access Token, an ID Token, and optionally a Refresh Token. authOpenidRevokeUrl https://my-jans-server.jans.io/jans-auth/restv1/token Authorization server endpoint to notify an OAuth 2.0 authorization server that a previously obtained refresh or access token is no longer needed, allowing the server to clean up security credentials. smallryeHealthRootPath /health-check Deprecated param for health-check exclusiveAuthScopes [\"jans_stat\",\"https://jans.io/scim/users.read\",\"https://jans.io/scim/users.write\"] Scopes that are only validated against the underlying Jansen Authorization server. corsConfigurationFilters [{\"filterName\":\"CorsFilter\",\"corsEnabled\":true,\"corsAllowedOrigins\":\"*\",\"corsAllowedMethods\":\"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\",\"corsAllowedHeaders\":\"\",\"corsExposedHeaders\":\"\",\"corsSupportCredentials\":true,\"corsLoggingEnabled\":false,\"corsPreflightMaxAge\":1800,\"corsRequestDecorate\":true}] This list specifies the CORS configuration filters. exclusiveAuthScopes [\"jans_stat\",\"https://jans.io/scim/users.read\",\"https://jans.io/scim/users.write\"] Scopes that are only validated against the underlying Jansen Authorization server. loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for Config API. loggingLayout \"text\" Contents of logs as plain text format. externalLoggerConfiguration Path to external log4j2 logging configuration. disableJdkLogger true Boolean to disable JDK loggers. maxCount 200 To be used to set maximum records returned in response. userExclusionAttributes [\"userPassword\"] List of attributes to be excluded in User response. userMandatoryAttributes [\"mail\",\"displayName\",\"jansStatus\",\"userPassword\",\"givenName\"] List of attributes mandatory for creating a User. agamaConfiguration {\"mandatoryAttributes\":[\"qname\",\"source\"],\"optionalAttributes\":[\"serialVersionUID\",\"enabled\"]} Configuration parameters like mandatory, optional, etc for agama flow. auditLogConf {\"enabled\":true,\"ignoreHttpMethod\":[],\"headerAttributes\":[\"User-inum\"]} Audit Log configuration. dataFormatConversionConf {\"enabled\":true,\"ignoreHttpMethod\":[\"@jakarta.ws.rs.GET()\"]} DB specific data format conversion configuration for Date field. plugins [{\"name\":\"admin\",\"description\":\"admin-ui plugin\",\"className\":\"io.jans.ca.plugin.adminui.rest.ApiApplication\"},{\"name\":\"fido2\",\"description\":\"fido2 plugin\",\"className\":\"io.jans.configapi.plugin.fido2.rest.ApiApplication\"},{\"name\":\"scim\",\"description\":\"scim plugin\",\"className\":\"io.jans.configapi.plugin.scim.rest.ApiApplication\"},{\"name\":\"user-management\",\"description\":\"user-management plugin\",\"className\":\"io.jans.configapi.plugin.mgt.rest.ApiApplication\"}] List of configured plugin. Two options to make effect any manual changes done to the configuration # Restart jans-config-api Increment the jansRevision property of the configuration without restarting the application. The timer job will detect the change and fetch the latest configuration from the DB. Locating Config API configuration in the Persistence Layer # While it is not recommended that an administrator directly edits a configuration at the persistence layer, it may be useful information for a developer. MySQL # erDiagram jansAppConf { string doc_id PK \"\" string ou \"jans-config-api\" string jansConfDyn \"json configuration for the app\" } Important attributes # OAuth authorization # configOauthEnabled property can be used to enable or disable the oAuth2 authorization. By default, it is set to true. \"configOauthEnabled\" : true Api protection # apiProtectionType property states the protocol used for API authorization. The currently supported value is oauth2 . \"apiProtectionType\" : \"oauth2\" Api protection auth server # apiApprovedIssuer property enables to set more than one authorization servers. By default, the current auth-server is set. You can add more servers separated by commas. apiApprovedIssuer \": [\" https : //<jans.auth.server>,https://<gluu.server>,https://<anyAuth.server>\"] Logging level # loggingLevel property can be used to change the logging level to the desired values (TRACE, DEBUG, INFO, WARN, ERROR) . By default, the level is set to INFO ```javascript \"loggingLevel\":\"DEBUG\", ``` Scopes other than the one defined by config-api # Config API endpoints are oAuth2 protected. These scopes are created during installation. However, few endpoints require scopes defined by other modules like auth-server. A list of these scopes is maintained in the configuration in order to avoid the creation of these scopes during Config API start-up. exclusiveAuthScopes property can be used to change the logging level to the desired value (TRACE, DEBUG, INFO, WARN, ERROR) . By default, the level is set to INFO \"exclusiveAuthScopes\" : [ \"jans_stat\" , \"https://jans.io/scim/users.read\" , \"https://jans.io/scim/users.write\" ], User - Mandatory and exclusion attributes # MandatoryAttributes # userMandatoryAttributes can be used to define mandatory attributes for User while creating and updating. \"userMandatoryAttributes\" : [ \"mail\" , \"displayName\" , \"jansStatus\" , \"userPassword\" , \"givenName\" ], Exclusion attributes # userExclusionAttributes can be used to define User attributes that are not to be returned in the API response. More attributes that are to be skipped in response can be added to the list. \"userExclusionAttributes\" : [ \"userPassword\" ], Agama flow configuration # agamaConfiguration stores Agama-related configuration used in Agama related endpoints. mandatoryAttributes list defines the required attributes for Agama flow creation and update. optionalAttributes list specifies the optional attributes. \"agamaConfiguration\" : { \"mandatoryAttributes\" : [ \"qname\" , \"source\" ], \"optionalAttributes\" : [ \"serialVersionUID\" , \"enabled\" ] } Using Text-based UI # You can start TUI using the command below: Command jans tui Navigate to Config API section where administrators can update Config-API configurations in six sub-tabs, namely Main , Agama , Plugins , Asset Management , Audit Log Conf , Data Format Conversion Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Config-API Configuration. Endpoint details are published in the Swagger document , see endpoint /api/v1/api-config", "title": "Settings"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#janssen-config-api-configuration", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Janssen Config-API Configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the Config-API Configuration using the command line. To get the details of Janssen command line operations relevant to Config-API Configuration, you can check the operations under ConfigurationConfigApi task using the command below: Command jans tui --info ConfigurationConfigApi It will show the details of the available operation-ids for Config-API. Sample Output Operation ID: get-config-api-properties Description: Gets config-api configuration properties. Operation ID: patch-config-api-properties Description: Partially modifies config-api Configuration properties. Schema: Array of JsonPatch To get sample schema type jans tui --schema-sample <schema>, for example jans tui --schema-sample JsonPatch", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#get-the-current-config-api-configuration", "text": "Configuration for Config-API is a set of key-value pairs, called properties. When we retrieve the configuration, these properties and their current values are returned as a JSON document. To get the properties of Janssen Config-API Configuration, run the command below: Command jans tui --operation-id = get-config-api-properties It will return the result as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 { \"serviceName\" : \"jans-config-api\" , \"configOauthEnabled\" : true , \"disableLoggerTimer\" : false , \"disableAuditLogger\" : false , \"customAttributeValidationEnabled\" : true , \"acrValidationEnabled\" : true , \"apiApprovedIssuer\" : [ \"https://example.jans.io\" ], \"apiProtectionType\" : \"oauth2\" , \"apiClientId\" : \"1800.b62cb614-a09d-4163-a6bc-32e38a51c4d2\" , \"apiClientPassword\" : \"CN8ggRUhMkw9K0ocQ+LXbA==\" , \"endpointInjectionEnabled\" : false , \"authIssuerUrl\" : \"https://example.jans.io\" , \"authOpenidConfigurationUrl\" : \"https://example.jans.io/.well-known/openid-configuration\" , \"authOpenidIntrospectionUrl\" : \"https://example.jans.io/jans-auth/restv1/introspection\" , \"authOpenidTokenUrl\" : \"https://example.jans.io/jans-auth/restv1/token\" , \"authOpenidRevokeUrl\" : \"https://example.jans.io/jans-auth/restv1/revoke\" , \"exclusiveAuthScopes\" : [ \"jans_stat\" , \"https://jans.io/scim/users.read\" , \"https://jans.io/scim/users.write\" ], \"corsConfigurationFilters\" : [ { \"filterName\" : \"CorsFilter\" , \"corsEnabled\" : true , \"corsAllowedOrigins\" : \"*\" , \"corsAllowedMethods\" : \"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\" , \"corsSupportCredentials\" : true , \"corsLoggingEnabled\" : false , \"corsPreflightMaxAge\" : 1800 , \"corsRequestDecorate\" : true } ], \"loggingLevel\" : \"INFO\" , \"loggingLayout\" : \"text\" , \"disableJdkLogger\" : true , \"maxCount\" : 200 , \"acrExclusionList\" : [ \"simple_password_auth\" ], \"userExclusionAttributes\" : [ \"userPassword\" ], \"userMandatoryAttributes\" : [ \"mail\" , \"displayName\" , \"status\" , \"userPassword\" , \"givenName\" ], \"agamaConfiguration\" : { \"mandatoryAttributes\" : [ \"qname\" , \"source\" ], \"optionalAttributes\" : [ \"serialVersionUID\" , \"enabled\" ] }, \"auditLogConf\" : { \"enabled\" : true , \"headerAttributes\" : [ \"User-inum\" ] }, \"dataFormatConversionConf\" : { \"enabled\" : true , \"ignoreHttpMethod\" : [ \"@jakarta.ws.rs.GET()\" ] }, \"plugins\" : [ { \"name\" : \"admin\" , \"description\" : \"admin-ui plugin\" , \"className\" : \"io.jans.ca.plugin.adminui.rest.ApiApplication\" }, { \"name\" : \"fido2\" , \"description\" : \"fido2 plugin\" , \"className\" : \"io.jans.configapi.plugin.fido2.rest.ApiApplication\" }, { \"name\" : \"scim\" , \"description\" : \"scim plugin\" , \"className\" : \"io.jans.configapi.plugin.scim.rest.ApiApplication\" }, { \"name\" : \"user-management\" , \"description\" : \"user-management plugin\" , \"className\" : \"io.jans.configapi.plugin.mgt.rest.ApiApplication\" }, { \"name\" : \"jans-link\" , \"description\" : \"jans-link plugin\" , \"className\" : \"io.jans.configapi.plugin.link.rest.ApiApplication\" }, { \"name\" : \"saml\" , \"description\" : \"saml plugin\" , \"className\" : \"io.jans.configapi.plugin.saml.rest.ApiApplication\" }, { \"name\" : \"kc-link\" , \"description\" : \"kc-link plugin\" , \"className\" : \"io.jans.configapi.plugin.kc.link.rest.ApiApplication\" }, { \"name\" : \"lock\" , \"description\" : \"lock plugin\" , \"className\" : \"io.jans.configapi.plugin.lock.rest.ApiApplication\" } ], \"assetMgtConfiguration\" : { \"assetMgtEnabled\" : true , \"assetServerUploadEnabled\" : true , \"fileExtensionValidationEnabled\" : true , \"moduleNameValidationEnabled\" : true , \"assetBaseDirectory\" : \"/opt/jans/jetty/%s/custom\" , \"jansServiceModule\" : [ \"jans-auth\" , \"jans-config-api\" , \"jans-fido2\" , \"jans-scim\" ], \"assetDirMapping\" : [ { \"directory\" : \"i18n\" , \"type\" : [ \"properties\" ], \"description\" : \"Resource bundle file.\" }, { \"directory\" : \"libs\" , \"type\" : [ \"jar\" /op t /ja ns /ja ns - cli/co nf ig - cli.py -- i nf o Co nf igura t io n Co nf igApi ], \"description\" : \"java archive library.\" }, { \"directory\" : \"pages\" , \"type\" : [ \"xhtml\" ], \"description\" : \"Web pages.\" }, { \"directory\" : \"static\" , \"type\" : [ \"js\" , \"css\" , \"png\" , \"gif\" , \"jpg\" , \"jpeg\" ], \"description\" : \"Static resources like Java-script, style-sheet and images.\" } ] } }", "title": "Get The Current Config-API Configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#update-config-api-configuration-properties", "text": "To update the configuration, we will use JSON patch schema as shown below. Let's say we want to stop the file extension validation done by config-api's asset management module. This can be done by setting the fileExtensionValidationEnabled property to false . To do that, write a text file ( config-api-assetmgt-patch.json ) with the content that follows the JSON patch schema. config-api-assetmgt-patch.json 1 2 3 4 5 6 7 [ { \"op\" : \"replace\" , \"path\" : \"/assetMgtConfiguration/fileExtensionValidationEnabled\" , \"value\" : false } ] Now, execute the following command to apply this patch: Command jans tui \\ --operation-id = patch-config-api-properties --data ./config-api-assetmgt-patch.json Upon successful execution of the update, the Janssen Server responds with updated configuration.", "title": "Update Config-API Configuration Properties"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#updating-multi-valued-property", "text": "Let's say we want to update the configuration property userMandatoryAttributes . This property's value is a list of attributes. We want to remove an attribute from the list. For this, we will have to create a JSON patch file that contains the new list and then run a command to push the update to the Janssen Server. Let's do this step-by-step: Get the current value list for userMandatoryAttributes property using steps mentioned in Get the current configuration section Using the current list of values as a starting point, create a JSON patch file config-api-patch.json as below. Update the list as desired by adding or removing items from the list: Sample Contents 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [ { \"op\" : \"replace\" , \"path\" : \"/userMandatoryAttributes\" , \"value\" : [ \"mail\" , \"displayName\" , \"status\" , \"userPassword\" , \"givenName\" , \"gender\" ] } ] Now, execute the following command to apply this patch: Command jans tui \\ --operation-id = patch-config-api-properties --data ./config-api-patch.json", "title": "Updating multi-valued property"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#config-api-configuration-parameters", "text": "The table below outlines the key configuration parameters for the Jans Config API. It details settings for OAuth2, security, endpoints, logging, and plugin management. Field named Example Description configOauthEnabled true property can be used to enable or disable the oAuth2 authorization. By default, it is set to true. apiApprovedIssuer [\"https:// ,https:// ,https:// \"] Enables to set more than one authorization servers. By default, the current auth-server is set. You can add more servers separated by commas. apiProtectionType oauth2 Currently support mechanism is OAuth 2.0 tokens. apiClientId 1800.52eb1bed-ab5c-4ba6-b87e-90aad26058d0 Jans Config API Client. apiClientPassword lwI/8mcMkF63mvueYTZ0mQ== Encrypted secret of Jans Config API Client endpointInjectionEnabled false To be used if the endpoint needs to be injected. authIssuerUrl https://my-jans-server.jans.io URL of underlying auth-server. authOpenidConfigurationUrl https://my-jans-server.jans.io/.well-known/openid-configuration Metadata URL of the authorization server. authOpenidIntrospectionUrl https://my-jans-server.jans.io/jans-auth/restv1/introspection Authorization server endpoint to check the state of an OAuth 2.0 token and to determine meta-information about the token. authOpenidTokenUrl https://my-jans-server.jans.io/jans-auth/restv1/token Authorization server endpoint to obtain an Access Token, an ID Token, and optionally a Refresh Token. authOpenidRevokeUrl https://my-jans-server.jans.io/jans-auth/restv1/token Authorization server endpoint to notify an OAuth 2.0 authorization server that a previously obtained refresh or access token is no longer needed, allowing the server to clean up security credentials. smallryeHealthRootPath /health-check Deprecated param for health-check exclusiveAuthScopes [\"jans_stat\",\"https://jans.io/scim/users.read\",\"https://jans.io/scim/users.write\"] Scopes that are only validated against the underlying Jansen Authorization server. corsConfigurationFilters [{\"filterName\":\"CorsFilter\",\"corsEnabled\":true,\"corsAllowedOrigins\":\"*\",\"corsAllowedMethods\":\"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\",\"corsAllowedHeaders\":\"\",\"corsExposedHeaders\":\"\",\"corsSupportCredentials\":true,\"corsLoggingEnabled\":false,\"corsPreflightMaxAge\":1800,\"corsRequestDecorate\":true}] This list specifies the CORS configuration filters. exclusiveAuthScopes [\"jans_stat\",\"https://jans.io/scim/users.read\",\"https://jans.io/scim/users.write\"] Scopes that are only validated against the underlying Jansen Authorization server. loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for Config API. loggingLayout \"text\" Contents of logs as plain text format. externalLoggerConfiguration Path to external log4j2 logging configuration. disableJdkLogger true Boolean to disable JDK loggers. maxCount 200 To be used to set maximum records returned in response. userExclusionAttributes [\"userPassword\"] List of attributes to be excluded in User response. userMandatoryAttributes [\"mail\",\"displayName\",\"jansStatus\",\"userPassword\",\"givenName\"] List of attributes mandatory for creating a User. agamaConfiguration {\"mandatoryAttributes\":[\"qname\",\"source\"],\"optionalAttributes\":[\"serialVersionUID\",\"enabled\"]} Configuration parameters like mandatory, optional, etc for agama flow. auditLogConf {\"enabled\":true,\"ignoreHttpMethod\":[],\"headerAttributes\":[\"User-inum\"]} Audit Log configuration. dataFormatConversionConf {\"enabled\":true,\"ignoreHttpMethod\":[\"@jakarta.ws.rs.GET()\"]} DB specific data format conversion configuration for Date field. plugins [{\"name\":\"admin\",\"description\":\"admin-ui plugin\",\"className\":\"io.jans.ca.plugin.adminui.rest.ApiApplication\"},{\"name\":\"fido2\",\"description\":\"fido2 plugin\",\"className\":\"io.jans.configapi.plugin.fido2.rest.ApiApplication\"},{\"name\":\"scim\",\"description\":\"scim plugin\",\"className\":\"io.jans.configapi.plugin.scim.rest.ApiApplication\"},{\"name\":\"user-management\",\"description\":\"user-management plugin\",\"className\":\"io.jans.configapi.plugin.mgt.rest.ApiApplication\"}] List of configured plugin.", "title": "Config API Configuration Parameters:"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#two-options-to-make-effect-any-manual-changes-done-to-the-configuration", "text": "Restart jans-config-api Increment the jansRevision property of the configuration without restarting the application. The timer job will detect the change and fetch the latest configuration from the DB.", "title": "Two options to make effect any manual changes done to the configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#locating-config-api-configuration-in-the-persistence-layer", "text": "While it is not recommended that an administrator directly edits a configuration at the persistence layer, it may be useful information for a developer.", "title": "Locating Config API configuration in the Persistence Layer"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#mysql", "text": "erDiagram jansAppConf { string doc_id PK \"\" string ou \"jans-config-api\" string jansConfDyn \"json configuration for the app\" }", "title": "MySQL"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#important-attributes", "text": "", "title": "Important attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#oauth-authorization", "text": "configOauthEnabled property can be used to enable or disable the oAuth2 authorization. By default, it is set to true. \"configOauthEnabled\" : true", "title": "OAuth authorization"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#api-protection", "text": "apiProtectionType property states the protocol used for API authorization. The currently supported value is oauth2 . \"apiProtectionType\" : \"oauth2\"", "title": "Api protection"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#api-protection-auth-server", "text": "apiApprovedIssuer property enables to set more than one authorization servers. By default, the current auth-server is set. You can add more servers separated by commas. apiApprovedIssuer \": [\" https : //<jans.auth.server>,https://<gluu.server>,https://<anyAuth.server>\"]", "title": "Api protection auth server"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#logging-level", "text": "loggingLevel property can be used to change the logging level to the desired values (TRACE, DEBUG, INFO, WARN, ERROR) . By default, the level is set to INFO ```javascript \"loggingLevel\":\"DEBUG\", ```", "title": "Logging level"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#scopes-other-than-the-one-defined-by-config-api", "text": "Config API endpoints are oAuth2 protected. These scopes are created during installation. However, few endpoints require scopes defined by other modules like auth-server. A list of these scopes is maintained in the configuration in order to avoid the creation of these scopes during Config API start-up. exclusiveAuthScopes property can be used to change the logging level to the desired value (TRACE, DEBUG, INFO, WARN, ERROR) . By default, the level is set to INFO \"exclusiveAuthScopes\" : [ \"jans_stat\" , \"https://jans.io/scim/users.read\" , \"https://jans.io/scim/users.write\" ],", "title": "Scopes other than the one defined by config-api"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#user-mandatory-and-exclusion-attributes", "text": "", "title": "User - Mandatory and exclusion attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#mandatoryattributes", "text": "userMandatoryAttributes can be used to define mandatory attributes for User while creating and updating. \"userMandatoryAttributes\" : [ \"mail\" , \"displayName\" , \"jansStatus\" , \"userPassword\" , \"givenName\" ],", "title": "MandatoryAttributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#exclusion-attributes", "text": "userExclusionAttributes can be used to define User attributes that are not to be returned in the API response. More attributes that are to be skipped in response can be added to the list. \"userExclusionAttributes\" : [ \"userPassword\" ],", "title": "Exclusion attributes"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#agama-flow-configuration", "text": "agamaConfiguration stores Agama-related configuration used in Agama related endpoints. mandatoryAttributes list defines the required attributes for Agama flow creation and update. optionalAttributes list specifies the optional attributes. \"agamaConfiguration\" : { \"mandatoryAttributes\" : [ \"qname\" , \"source\" ], \"optionalAttributes\" : [ \"serialVersionUID\" , \"enabled\" ] }", "title": "Agama flow configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#using-text-based-ui", "text": "You can start TUI using the command below: Command jans tui Navigate to Config API section where administrators can update Config-API configurations in six sub-tabs, namely Main , Agama , Plugins , Asset Management , Audit Log Conf , Data Format Conversion", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/config-tools/config-api/config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the Config-API Configuration. Endpoint details are published in the Swagger document , see endpoint /api/v1/api-config", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/", "tags": ["administration", "tools", "config-api", "logs"], "text": "Config-api logs: # Two types of logs generated by config-api, application logs and audit log . - Application log contains application functionality logs - Audit log contains information of each request received. Logging configuration # Log configuration is stored in DB along with the config-application other configuration javascript { \"configOauthEnabled\": true, \"apiApprovedIssuer\": [\"https://jans.server2\"], \"apiProtectionType\": \"oauth2\", \"apiClientId\": \"1800.c9c0b756-a1fc-4013-9feb-64d531ac2dc1\", \"apiClientPassword\": \"X9q7cAemqyD9LaS1c5YzIA==\", \"endpointInjectionEnabled\": false, \"authIssuerUrl\": \"https://jans.server2\", \"authOpenidConfigurationUrl\": \"https://jans.server2/.well-known/openid-configuration\", \"authOpenidIntrospectionUrl\": \"https://jans.server2/jans-auth/restv1/introspection\", \"authOpenidTokenUrl\": \"https://jans.server2/jans-auth/restv1/token\", \"authOpenidRevokeUrl\": \"https://jans.server2/jans-auth/restv1/revoke\", \"smallryeHealthRootPath\": \"/health-check\", \"disableJdkLogger\":true, \"loggingLevel\":\"INFO\", \"loggingLayout\":\"text\", \"externalLoggerConfiguration\":\"\", \"exclusiveAuthScopes\": [ \"jans_stat\", \"https://jans.io/scim/users.read\", \"https://jans.io/scim/users.write\" ], \"corsConfigurationFilters\": [ { \"filterName\": \"CorsFilter\", \"corsAllowedOrigins\": \"*\", \"corsAllowedMethods\": \"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\", \"corsAllowedHeaders\": \"\", \"corsExposedHeaders\": \"\", \"corsSupportCredentials\": true, \"corsLoggingEnabled\": false, \"corsPreflightMaxAge\": 1800, \"corsRequestDecorate\": true, \"corsEnabled\": true } ], \"userExclusionAttributes\": [ \"userPassword\" ], \"userMandatoryAttributes\": [ \"mail\", \"displayName\", \"jansStatus\", \"userPassword\", \"givenName\" ], \"agamaConfiguration\": { \"mandatoryAttributes\": [ \"qname\", \"source\" ], \"optionalAttributes\": [ \"serialVersionUID\", \"enabled\" ] }, \"auditLogConf\": { \"enabled\": true, \"ignoreHttpMethod\": [], \"headerAttributes\": [ \"User-inum\" ] }, \"dataFormatConversionConf\": { \"enabled\": true, \"ignoreHttpMethod\": [ \"@jakarta.ws.rs.GET()\" ] }, \"plugins\": [ { \"name\": \"admin\", \"description\": \"admin-ui plugin\", \"className\": \"io.jans.ca.plugin.adminui.rest.ApiApplication\" }, { \"name\": \"fido2\", \"description\": \"fido2 plugin\", \"className\": \"io.jans.configapi.plugin.fido2.rest.ApiApplication\" }, { \"name\": \"scim\", \"description\": \"scim plugin\", \"className\": \"io.jans.configapi.plugin.scim.rest.ApiApplication\" }, { \"name\": \"user-management\", \"description\": \"user-management plugin\", \"className\": \"io.jans.configapi.plugin.mgt.rest.ApiApplication\" } ] } Audit log # Configuration # ... auditLogConf \": { \" enabled \": true, \" ignoreHttpMethod \": [], \" headerAttributes \": [ \" User - inum \" ] ... Field Description Example enabled Flag to enable and disable audit log true , default value is true, to enable audit logging ignoreHttpMethod HTTP methods for which audit is disabled @jakarta.ws.rs.GET(), @jakarta.ws.rs.PATCH(), @jakarta.ws.rs.PATCH(), etc headerAttributes List of HTTP header attributes whose value is to be logged User-inum File name and location on server # Log name: configapi-audit.log Log location: /opt/jans/jetty/jans-config-api/logs Application Logs # Config-api uses log4j to generate application execution logs for each endpoint invocation. These can be used to debug the application. Configuration # DB: ``javascript ... \"loggingLevel\":\"DEBUG\", \"loggingLayout\":\"text\" ... log4j file: https://github.com/JanssenProject/jans/blob/main/jans-config-api/server/src/main/resources/log4j2.xml DB configuration # Fetch configuration curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 3114e010-fd4d-4e62-b5e2-a51b7d6dd231\" - X GET https : //jans.server/jans-config-api/api/v1/api-config Patch configuration curl - X PATCH - k - H 'Content-Type: application/json-patch+json' - H 'Authorization:Bearer 3114e010-fd4d-4e62-b5e2-a51b7d6dd231' - i 'https://jans.server/jans-config-api/api/v1/api-config' -- data '[{\"op\": \"replace\", \"path\": \"/loggingLevel\", \"value\":\"ERROR\"}, {\"op\": \"replace\", \"path\": \"/loggingLayout\", \"value\":\"json\"}, {\"op\": \"replace\", \"path\": \"/auditLogConf/enabled\", \"value\":false} , {\"op\": \"replace\", \"path\": \"/auditLogConf/headerAttributes\", \"value\":[\"User-inum\",\"city\"]}]'", "title": "Logs"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#config-api-logs", "text": "Two types of logs generated by config-api, application logs and audit log . - Application log contains application functionality logs - Audit log contains information of each request received.", "title": "Config-api logs:"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#logging-configuration", "text": "Log configuration is stored in DB along with the config-application other configuration javascript { \"configOauthEnabled\": true, \"apiApprovedIssuer\": [\"https://jans.server2\"], \"apiProtectionType\": \"oauth2\", \"apiClientId\": \"1800.c9c0b756-a1fc-4013-9feb-64d531ac2dc1\", \"apiClientPassword\": \"X9q7cAemqyD9LaS1c5YzIA==\", \"endpointInjectionEnabled\": false, \"authIssuerUrl\": \"https://jans.server2\", \"authOpenidConfigurationUrl\": \"https://jans.server2/.well-known/openid-configuration\", \"authOpenidIntrospectionUrl\": \"https://jans.server2/jans-auth/restv1/introspection\", \"authOpenidTokenUrl\": \"https://jans.server2/jans-auth/restv1/token\", \"authOpenidRevokeUrl\": \"https://jans.server2/jans-auth/restv1/revoke\", \"smallryeHealthRootPath\": \"/health-check\", \"disableJdkLogger\":true, \"loggingLevel\":\"INFO\", \"loggingLayout\":\"text\", \"externalLoggerConfiguration\":\"\", \"exclusiveAuthScopes\": [ \"jans_stat\", \"https://jans.io/scim/users.read\", \"https://jans.io/scim/users.write\" ], \"corsConfigurationFilters\": [ { \"filterName\": \"CorsFilter\", \"corsAllowedOrigins\": \"*\", \"corsAllowedMethods\": \"GET,PUT,POST,DELETE,PATCH,HEAD,OPTIONS\", \"corsAllowedHeaders\": \"\", \"corsExposedHeaders\": \"\", \"corsSupportCredentials\": true, \"corsLoggingEnabled\": false, \"corsPreflightMaxAge\": 1800, \"corsRequestDecorate\": true, \"corsEnabled\": true } ], \"userExclusionAttributes\": [ \"userPassword\" ], \"userMandatoryAttributes\": [ \"mail\", \"displayName\", \"jansStatus\", \"userPassword\", \"givenName\" ], \"agamaConfiguration\": { \"mandatoryAttributes\": [ \"qname\", \"source\" ], \"optionalAttributes\": [ \"serialVersionUID\", \"enabled\" ] }, \"auditLogConf\": { \"enabled\": true, \"ignoreHttpMethod\": [], \"headerAttributes\": [ \"User-inum\" ] }, \"dataFormatConversionConf\": { \"enabled\": true, \"ignoreHttpMethod\": [ \"@jakarta.ws.rs.GET()\" ] }, \"plugins\": [ { \"name\": \"admin\", \"description\": \"admin-ui plugin\", \"className\": \"io.jans.ca.plugin.adminui.rest.ApiApplication\" }, { \"name\": \"fido2\", \"description\": \"fido2 plugin\", \"className\": \"io.jans.configapi.plugin.fido2.rest.ApiApplication\" }, { \"name\": \"scim\", \"description\": \"scim plugin\", \"className\": \"io.jans.configapi.plugin.scim.rest.ApiApplication\" }, { \"name\": \"user-management\", \"description\": \"user-management plugin\", \"className\": \"io.jans.configapi.plugin.mgt.rest.ApiApplication\" } ] }", "title": "Logging configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#audit-log", "text": "", "title": "Audit log"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#configuration", "text": "... auditLogConf \": { \" enabled \": true, \" ignoreHttpMethod \": [], \" headerAttributes \": [ \" User - inum \" ] ... Field Description Example enabled Flag to enable and disable audit log true , default value is true, to enable audit logging ignoreHttpMethod HTTP methods for which audit is disabled @jakarta.ws.rs.GET(), @jakarta.ws.rs.PATCH(), @jakarta.ws.rs.PATCH(), etc headerAttributes List of HTTP header attributes whose value is to be logged User-inum", "title": "Configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#file-name-and-location-on-server", "text": "Log name: configapi-audit.log Log location: /opt/jans/jetty/jans-config-api/logs", "title": "File name and location on server"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#application-logs", "text": "Config-api uses log4j to generate application execution logs for each endpoint invocation. These can be used to debug the application.", "title": "Application Logs"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#configuration_1", "text": "DB: ``javascript ... \"loggingLevel\":\"DEBUG\", \"loggingLayout\":\"text\" ... log4j file: https://github.com/JanssenProject/jans/blob/main/jans-config-api/server/src/main/resources/log4j2.xml", "title": "Configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/logs/#db-configuration", "text": "Fetch configuration curl - k - i - H \"Accept: application/json\" - H \"Content-Type: application/json\" - H \"Authorization:Bearer 3114e010-fd4d-4e62-b5e2-a51b7d6dd231\" - X GET https : //jans.server/jans-config-api/api/v1/api-config Patch configuration curl - X PATCH - k - H 'Content-Type: application/json-patch+json' - H 'Authorization:Bearer 3114e010-fd4d-4e62-b5e2-a51b7d6dd231' - i 'https://jans.server/jans-config-api/api/v1/api-config' -- data '[{\"op\": \"replace\", \"path\": \"/loggingLevel\", \"value\":\"ERROR\"}, {\"op\": \"replace\", \"path\": \"/loggingLayout\", \"value\":\"json\"}, {\"op\": \"replace\", \"path\": \"/auditLogConf/enabled\", \"value\":false} , {\"op\": \"replace\", \"path\": \"/auditLogConf/headerAttributes\", \"value\":[\"User-inum\",\"city\"]}]'", "title": "DB configuration"}, {"location": "janssen-server/config-guide/config-tools/config-api/monitoring/", "tags": ["administration", "tools", "config-api", "monitoring"], "text": "Health - Check endpoints # /api/v1/health - Returns application consolidated health status - liveness and readiness /api/v1/health/live - Returns application liveness status /api/v1/health/ready -Returns application readiness status /api/v1/health/server-stat - Returns application server status and stats metric like memoryfree , uptime , free_disk_space , etc Sample health response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n [ { \"name\" : \"jans-config-api liveness\" , \"status\" : \"UP\" }, { \"name\" : \"jans-config-api readiness\" , \"status\" : \"UP\" } ] Sample liveness response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"name\" : \"jans-config-api liveness\" , \"status\" : \"UP\" } Sample readiness response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"name\" : \"jans-config-api readiness\" , \"status\" : \"UP\" } Sample server status response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"dbType\" : \"MySQL\" , \"lastUpdate\" : \"2023-03-16T03:17:44\" , \"facterData\" : { \"memoryfree\" : \"7.1%\" , \"swapfree\" : \"60.1%\" , \"hostname\" : \"jans.server2\" , \"ipaddress\" : \"192.168.0.102\" , \"uptime\" : \"3:03\" , \"free_disk_space\" : \"65.0%\" , \"load_average\" : \"0.77\" } } Application logs # Application log can be verified if application is started properly. Refer here for more details.", "title": "Monitoring"}, {"location": "janssen-server/config-guide/config-tools/config-api/monitoring/#health-check-endpoints", "text": "/api/v1/health - Returns application consolidated health status - liveness and readiness /api/v1/health/live - Returns application liveness status /api/v1/health/ready -Returns application readiness status /api/v1/health/server-stat - Returns application server status and stats metric like memoryfree , uptime , free_disk_space , etc Sample health response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n [ { \"name\" : \"jans-config-api liveness\" , \"status\" : \"UP\" }, { \"name\" : \"jans-config-api readiness\" , \"status\" : \"UP\" } ] Sample liveness response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"name\" : \"jans-config-api liveness\" , \"status\" : \"UP\" } Sample readiness response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"name\" : \"jans-config-api readiness\" , \"status\" : \"UP\" } Sample server status response HTTP/ 1.1 200 OK Co ntent - Type : applica t io n /jso n { \"dbType\" : \"MySQL\" , \"lastUpdate\" : \"2023-03-16T03:17:44\" , \"facterData\" : { \"memoryfree\" : \"7.1%\" , \"swapfree\" : \"60.1%\" , \"hostname\" : \"jans.server2\" , \"ipaddress\" : \"192.168.0.102\" , \"uptime\" : \"3:03\" , \"free_disk_space\" : \"65.0%\" , \"load_average\" : \"0.77\" } }", "title": "Health - Check endpoints"}, {"location": "janssen-server/config-guide/config-tools/config-api/monitoring/#application-logs", "text": "Application log can be verified if application is started properly. Refer here for more details.", "title": "Application logs"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/", "tags": ["administration", "tools", "config-api", "plugins"], "text": "Overview # Jans Config Api is a REST application that is developed using Weld 4.x (JSR-365) and JAX-RS. Its endpoint can be used to manage configuration and other properties of Jans Auth Server . Jans Config API Plugins # Jans Config API follow a flexible plugin architecture in which the new features can be added using extensions called plugins without altering the application itself. In this section, we will discuss the steps to develop and add plugins in Jans Config API. The plugin architecture implemented in Jans Config API allows the deployer to add/remove new rest APIs (plugin) without changing the core application. A plugin contains one or more Rest API(s) packaged in a Java ARchive (jar file). It is added to Jans Config API by adding the plugin jar file path in the external extraClasspath of the jetty context file. Pre-requisites # The plugin developer should have an understanding of the following: Jakarta EE Platform : The plugin developer should know the Java programming language Weld : Weld is the reference implementation of CDI: Contexts and Dependency Injection for the Java EE Platform JAX-RS : JAX-RS for creating RESTful web services. Maven : Maven to build projects and manage dependencies. Web application container (Jetty) Sample plugin # To help bootstrap the plugin development, we have put together a sample plugin. Clone the Jans Config API project from here . Navigate under the plugins/sample folder. This folder contains the sample plugins for reference. helloworld folder for example contains the code for a basic plugin with GET endpoint sending Hello World! string response. Take the time to explore helloworld which is a minimalistic plugin that showcases very basic aspects of plugin development. Exploring Hello World Plugin # beans.xml # The resources/META-INF/beans.xml is the CDI deployment descriptor required in bean archive . Deployment descriptor helps WELD to explore beans, interceptors, decorators, etc in the bean archive . Refer to the WELD docs to learn more about deployment descriptors. HelloWorldExtension.java # A CDI portable extension is a mechanism by which we can implement additional functionalities on top of the CDI container. In this sample plugin, we have created an extension called HelloWorldExtension.java , implementing jakarta.enterprise.inject.spi.Extension . An extension can observe lifecycle events and also can modify the container\u2019s metamodel. Please refer to the WELD documentation for details. We need to register our extension as a service provider by creating a file named resources/META-INF/services/jakarta.enterprise.inject.spi.Extension (as shown below). com.spl.plugin.helloworld.ext.HelloWorldExtension HelloWorldApplication.java # The com.spl.plugin.helloworld.rest.HelloWorldApplication.java class is annotated with the @ApplicationPath annotation which identifies the application path that serves as the base URI for all resources of the plugin and is used to register JAX-RS resources and providers. HelloWorldResource.java # This is a sample JAX-RS resource with an endpoint returning Hello World! string as http response. Plugin Deployment # Jans Config API is offered as one of the several components of the Jans Auth Server. A plugin jar can be added to Jans Config API by following below steps. On an installed Jans Auth Server with Jans Config API (as component) copy plugin jar to /opt/jans/jetty/jans-config-api/custom/libs location. Add the location of plugin jar inside tag with name extraClasspath (multiple plugins can be added comma separated) of /opt/jans/jetty/jans-config-api/webapps/jans-config-api.xml file. <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"http://www.eclipse.org/jetty/configure_9_0.dtd\"> <Configure class=\"org.eclipse.jetty.webapp.WebAppContext\"> <Set name=\"contextPath\">/jans-config-api</Set> <Set name=\"war\"> <Property name=\"jetty.webapps\" default=\".\" />/jans-config-api.war </Set> <Set name=\"extractWAR\">true</Set> <Set name=\"extraClasspath\">/opt/jans/jetty/jans-config-api/custom/libs/helloWorldjar</Set> </Configure> Restart jans-config-api service. systemctl restart jans-config-api.service", "title": "Plugins"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#overview", "text": "Jans Config Api is a REST application that is developed using Weld 4.x (JSR-365) and JAX-RS. Its endpoint can be used to manage configuration and other properties of Jans Auth Server .", "title": "Overview"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#jans-config-api-plugins", "text": "Jans Config API follow a flexible plugin architecture in which the new features can be added using extensions called plugins without altering the application itself. In this section, we will discuss the steps to develop and add plugins in Jans Config API. The plugin architecture implemented in Jans Config API allows the deployer to add/remove new rest APIs (plugin) without changing the core application. A plugin contains one or more Rest API(s) packaged in a Java ARchive (jar file). It is added to Jans Config API by adding the plugin jar file path in the external extraClasspath of the jetty context file.", "title": "Jans Config API Plugins"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#pre-requisites", "text": "The plugin developer should have an understanding of the following: Jakarta EE Platform : The plugin developer should know the Java programming language Weld : Weld is the reference implementation of CDI: Contexts and Dependency Injection for the Java EE Platform JAX-RS : JAX-RS for creating RESTful web services. Maven : Maven to build projects and manage dependencies. Web application container (Jetty)", "title": "Pre-requisites"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#sample-plugin", "text": "To help bootstrap the plugin development, we have put together a sample plugin. Clone the Jans Config API project from here . Navigate under the plugins/sample folder. This folder contains the sample plugins for reference. helloworld folder for example contains the code for a basic plugin with GET endpoint sending Hello World! string response. Take the time to explore helloworld which is a minimalistic plugin that showcases very basic aspects of plugin development.", "title": "Sample plugin"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#exploring-hello-world-plugin", "text": "", "title": "Exploring Hello World Plugin"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#beansxml", "text": "The resources/META-INF/beans.xml is the CDI deployment descriptor required in bean archive . Deployment descriptor helps WELD to explore beans, interceptors, decorators, etc in the bean archive . Refer to the WELD docs to learn more about deployment descriptors.", "title": "beans.xml"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#helloworldextensionjava", "text": "A CDI portable extension is a mechanism by which we can implement additional functionalities on top of the CDI container. In this sample plugin, we have created an extension called HelloWorldExtension.java , implementing jakarta.enterprise.inject.spi.Extension . An extension can observe lifecycle events and also can modify the container\u2019s metamodel. Please refer to the WELD documentation for details. We need to register our extension as a service provider by creating a file named resources/META-INF/services/jakarta.enterprise.inject.spi.Extension (as shown below). com.spl.plugin.helloworld.ext.HelloWorldExtension", "title": "HelloWorldExtension.java"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#helloworldapplicationjava", "text": "The com.spl.plugin.helloworld.rest.HelloWorldApplication.java class is annotated with the @ApplicationPath annotation which identifies the application path that serves as the base URI for all resources of the plugin and is used to register JAX-RS resources and providers.", "title": "HelloWorldApplication.java"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#helloworldresourcejava", "text": "This is a sample JAX-RS resource with an endpoint returning Hello World! string as http response.", "title": "HelloWorldResource.java"}, {"location": "janssen-server/config-guide/config-tools/config-api/plugins/#plugin-deployment", "text": "Jans Config API is offered as one of the several components of the Jans Auth Server. A plugin jar can be added to Jans Config API by following below steps. On an installed Jans Auth Server with Jans Config API (as component) copy plugin jar to /opt/jans/jetty/jans-config-api/custom/libs location. Add the location of plugin jar inside tag with name extraClasspath (multiple plugins can be added comma separated) of /opt/jans/jetty/jans-config-api/webapps/jans-config-api.xml file. <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"http://www.eclipse.org/jetty/configure_9_0.dtd\"> <Configure class=\"org.eclipse.jetty.webapp.WebAppContext\"> <Set name=\"contextPath\">/jans-config-api</Set> <Set name=\"war\"> <Property name=\"jetty.webapps\" default=\".\" />/jans-config-api.war </Set> <Set name=\"extractWAR\">true</Set> <Set name=\"extraClasspath\">/opt/jans/jetty/jans-config-api/custom/libs/helloWorldjar</Set> </Configure> Restart jans-config-api service. systemctl restart jans-config-api.service", "title": "Plugin Deployment"}, {"location": "janssen-server/config-guide/config-tools/config-api/security/", "tags": ["administration", "tools", "config-api", "security"], "text": "Security # Disclosing vulnerabilities # If you think you found a security vulnerability, please refrain from posting it publicly on the forums, the chat, or GitHub. Instead, email us on security@jans.io. Refer to Janssen Security Policy", "title": "Security"}, {"location": "janssen-server/config-guide/config-tools/config-api/security/#security", "text": "", "title": "Security"}, {"location": "janssen-server/config-guide/config-tools/config-api/security/#disclosing-vulnerabilities", "text": "If you think you found a security vulnerability, please refrain from posting it publicly on the forums, the chat, or GitHub. Instead, email us on security@jans.io. Refer to Janssen Security Policy", "title": "Disclosing vulnerabilities"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/", "tags": ["administration", "configuration", "tools", "tui", "text base UI", "navigation"], "text": "TUI Navigation Guide # General Structure: # The TUI consists of many tabs, each tab may or may not contain nested tabs. The TUI consists of one main navigation bar which contains (Auth Server, FIDO, SCIM, Scripts, Users, and Jans CLI) The tab currently in focus is highlighted at the top. ex: Note: in the image provided below SCIM is focused We can notice that there is a cursor mark on the first of the Navigation bar line, which indicates that the focus currently in this widget General Purpose shortcuts # f1 : Open help dialog (currently, help dialog is static, in the near future it will dynamically change according to the current position inside the TUI ) ESC : Close any dialog or even nested dialog Ctrl+c (Terminate) : Terminate the program (SIGINT) Navigation Shortcuts # General Navigation shortcuts # tab (Next): focus on the next field or widget. shift + tab (Previous): focus on the previous field or widget PageUp (Next tab): Jump to the next tab in dialogs (ex: Client dialog) Note: the focus must be inside the current tab In the Gif provided, the focus was inside the tab itself before we can press the PageUp key * If the focus is on the tab name itself, we can navigate to other tabs by the Up key and Down key PageDown (Previous tab) : Jump to the previous tab in dialogs (ex: Client dialog) Note: the focus must be inside the current tab In the Gif provided, the focus was inside the tab itself before we can press the PageDown key If the focus is on the tab name itself, we can navigate to other tabs by the Up key and Down key Main tabs Navigation shortcuts # Alt + key You can navigate to any tab inside the TUI by using the Alt key followed by a certain letter from the tab you want to navigate too Note: the colored character inside each Tab name is the specified letter for the navigation. you can't navigate from a tab in the main top navigation bar to a nested navigation bar inside another tab, you must navigate to it first. examples on the navigation letters for the main navigation bar: Auth Server -> A FIDO -> F SCIM -> C Scripts -> r Users -> U Jans CLI -> J Custom widget shortcuts # Note: * This section contains any widgets with special shortcuts and behavior Lists (Vertical Nav bar) # currently, we have about 6 List widgets Note: Any list widget can be navigated between its items by the Up key and Down key There are some shortcuts here that can be used in most but not all List widgets delete : can be used to delete a certain item d : can be used to view all the selected item data in the JSON format Enter : can be used to edit the current item ex: p : can be used to update user's password. Date Widgets # The date widget can be used to select a date and time. ex (Client Expiration Date) tab , shift + tab : can be used to navigate between date and time Up , Down , Right , and Left arrows: can be used to change the date and time Note: * in the date section, if you navigate to the right border and then pressed Right , the year will be increased. in the date section, if you navigate to the left border and then pressed Left , the year will be decreased. in the date section, if you navigate to the up border and then pressed Up , the month will be decreased. * in the date section, if you navigate to the down border and then pressed Down , the month will be increased. in the time section, you can navigate between hour, minute, and second by the Right key and the Left key. in the time section, you can increase the time (hour, minute, or second) by the Up key and the Down key. Label Widgets # The label widget is used with scopes to show certain items instead of a long one, it is similar to the list widget tab , shift + tab : can be used to navigate between the button and the labels Right key and Left key can be used to navigate between the labels d : can be used to view all the data of the selected label delete : can be used to delete a certain label Logout and Exit # Exit will close the TUI screen while logout will force re-authentication of TUI using device-code. Navigate to Jans TUI on upper right corner of the screen and hit enter.", "title": "Navigation Guide"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#tui-navigation-guide", "text": "", "title": "TUI Navigation Guide"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#general-structure", "text": "The TUI consists of many tabs, each tab may or may not contain nested tabs. The TUI consists of one main navigation bar which contains (Auth Server, FIDO, SCIM, Scripts, Users, and Jans CLI) The tab currently in focus is highlighted at the top. ex: Note: in the image provided below SCIM is focused We can notice that there is a cursor mark on the first of the Navigation bar line, which indicates that the focus currently in this widget", "title": "General Structure:"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#general-purpose-shortcuts", "text": "f1 : Open help dialog (currently, help dialog is static, in the near future it will dynamically change according to the current position inside the TUI ) ESC : Close any dialog or even nested dialog Ctrl+c (Terminate) : Terminate the program (SIGINT)", "title": "General Purpose shortcuts"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#navigation-shortcuts", "text": "", "title": "Navigation Shortcuts"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#general-navigation-shortcuts", "text": "tab (Next): focus on the next field or widget. shift + tab (Previous): focus on the previous field or widget PageUp (Next tab): Jump to the next tab in dialogs (ex: Client dialog) Note: the focus must be inside the current tab In the Gif provided, the focus was inside the tab itself before we can press the PageUp key * If the focus is on the tab name itself, we can navigate to other tabs by the Up key and Down key PageDown (Previous tab) : Jump to the previous tab in dialogs (ex: Client dialog) Note: the focus must be inside the current tab In the Gif provided, the focus was inside the tab itself before we can press the PageDown key If the focus is on the tab name itself, we can navigate to other tabs by the Up key and Down key", "title": "General Navigation shortcuts"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#main-tabs-navigation-shortcuts", "text": "Alt + key You can navigate to any tab inside the TUI by using the Alt key followed by a certain letter from the tab you want to navigate too Note: the colored character inside each Tab name is the specified letter for the navigation. you can't navigate from a tab in the main top navigation bar to a nested navigation bar inside another tab, you must navigate to it first. examples on the navigation letters for the main navigation bar: Auth Server -> A FIDO -> F SCIM -> C Scripts -> r Users -> U Jans CLI -> J", "title": "Main tabs Navigation shortcuts"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#custom-widget-shortcuts", "text": "Note: * This section contains any widgets with special shortcuts and behavior", "title": "Custom widget shortcuts"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#lists-vertical-nav-bar", "text": "currently, we have about 6 List widgets Note: Any list widget can be navigated between its items by the Up key and Down key There are some shortcuts here that can be used in most but not all List widgets delete : can be used to delete a certain item d : can be used to view all the selected item data in the JSON format Enter : can be used to edit the current item ex: p : can be used to update user's password.", "title": "Lists (Vertical Nav bar)"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#date-widgets", "text": "The date widget can be used to select a date and time. ex (Client Expiration Date) tab , shift + tab : can be used to navigate between date and time Up , Down , Right , and Left arrows: can be used to change the date and time Note: * in the date section, if you navigate to the right border and then pressed Right , the year will be increased. in the date section, if you navigate to the left border and then pressed Left , the year will be decreased. in the date section, if you navigate to the up border and then pressed Up , the month will be decreased. * in the date section, if you navigate to the down border and then pressed Down , the month will be increased. in the time section, you can navigate between hour, minute, and second by the Right key and the Left key. in the time section, you can increase the time (hour, minute, or second) by the Up key and the Down key.", "title": "Date Widgets"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#label-widgets", "text": "The label widget is used with scopes to show certain items instead of a long one, it is similar to the list widget tab , shift + tab : can be used to navigate between the button and the labels Right key and Left key can be used to navigate between the labels d : can be used to view all the data of the selected label delete : can be used to delete a certain label", "title": "Label Widgets"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/navigation-guide/#logout-and-exit", "text": "Exit will close the TUI screen while logout will force re-authentication of TUI using device-code. Navigate to Jans TUI on upper right corner of the screen and hit enter.", "title": "Logout and Exit"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/using-command-line-log/", "tags": ["administration", "configuration", "tools", "cli", "tui", "commandline", "logging"], "text": "Using TUI Command Line Log # When you do a write operation (post/put/patch) with Jans TUI, it logs activities to file <log-dir>/cli_cmd.log ,default log-dir is home directory. Consider you created a user with TUI and have the following line in cli_cmd.log : /usr/bin/python3 /opt/jans/jans-cli/cli/config_cli.py --operation-id post-user --data '{\"customObjectClasses\": [\"top\", \"jansPerson\"], \"customAttributes\": [{\"name\": \"middleName\", \"multiValued\": false, \"values\": [\"\"]}, {\"name\": \"sn\", \"multiValued\": false, \"values\": [\"Watts\"]}, {\"name\": \"nickname\", \"multiValued\": false, \"values\": [\"\"]}], \"mail\": \"ewatts@foo.org\", \"userId\": \"ewatts\", \"displayName\": \"Emelia Watts\", \"givenName\": \"Emelia\", \"userPassword\": \"TopSecret\", \"jansStatus\": \"active\"}' You can modify this line to create another user, let us change the followings: userId padilla userPassword NewSecret sn Padilla givenName Reggie displayName Padilla Reggie mail reggie.padilla@egg.org New command will become: /usr/bin/python3 /opt/jans/jans-cli/cli/config_cli.py --operation-id post-user --data '{\"customObjectClasses\": [\"top\", \"jansPerson\"], \"customAttributes\": [{\"name\": \"middleName\", \"multiValued\": false, \"values\": [\"\"]}, {\"name\": \"sn\", \"multiValued\": false, \"values\": [\"Padilla\"]}, {\"name\": \"nickname\", \"multiValued\": false, \"values\": [\"\"]}], \"mail\": \"reggie.padilla@egg.org\", \"userId\": \"padilla\", \"displayName\": \"Padilla Reggie\", \"givenName\": \"Reggie\", \"userPassword\": \"NewSecret\", \"jansStatus\": \"active\"}' When you execute this command, user will be created: Server Response: { \"dn\": \"inum=65a5a60c-d314-426d-a8f4-8c36325a1024,ou=people,o=jans\", \"userId\": \"padilla\", \"createdAt\": \"2023-05-30T09:48:58\", \"customAttributes\": [ { \"name\": \"sn\", \"multiValued\": false, \"values\": [ \"Padilla\" ], \"displayValue\": \"Padilla\", \"value\": \"Padilla\" } ], \"customObjectClasses\": [ \"top\", \"jansCustomPerson\" ], \"inum\": \"65a5a60c-d314-426d-a8f4-8c36325a1024\", \"mail\": \"reggie.padilla@egg.org\", \"displayName\": \"Padilla Reggie\", \"jansStatus\": \"active\", \"givenName\": \"Reggie\", \"baseDn\": \"inum=65a5a60c-d314-426d-a8f4-8c36325a1024,ou=people,o=jans\" }", "title": "Using Logs"}, {"location": "janssen-server/config-guide/config-tools/jans-tui/using-command-line-log/#using-tui-command-line-log", "text": "When you do a write operation (post/put/patch) with Jans TUI, it logs activities to file <log-dir>/cli_cmd.log ,default log-dir is home directory. Consider you created a user with TUI and have the following line in cli_cmd.log : /usr/bin/python3 /opt/jans/jans-cli/cli/config_cli.py --operation-id post-user --data '{\"customObjectClasses\": [\"top\", \"jansPerson\"], \"customAttributes\": [{\"name\": \"middleName\", \"multiValued\": false, \"values\": [\"\"]}, {\"name\": \"sn\", \"multiValued\": false, \"values\": [\"Watts\"]}, {\"name\": \"nickname\", \"multiValued\": false, \"values\": [\"\"]}], \"mail\": \"ewatts@foo.org\", \"userId\": \"ewatts\", \"displayName\": \"Emelia Watts\", \"givenName\": \"Emelia\", \"userPassword\": \"TopSecret\", \"jansStatus\": \"active\"}' You can modify this line to create another user, let us change the followings: userId padilla userPassword NewSecret sn Padilla givenName Reggie displayName Padilla Reggie mail reggie.padilla@egg.org New command will become: /usr/bin/python3 /opt/jans/jans-cli/cli/config_cli.py --operation-id post-user --data '{\"customObjectClasses\": [\"top\", \"jansPerson\"], \"customAttributes\": [{\"name\": \"middleName\", \"multiValued\": false, \"values\": [\"\"]}, {\"name\": \"sn\", \"multiValued\": false, \"values\": [\"Padilla\"]}, {\"name\": \"nickname\", \"multiValued\": false, \"values\": [\"\"]}], \"mail\": \"reggie.padilla@egg.org\", \"userId\": \"padilla\", \"displayName\": \"Padilla Reggie\", \"givenName\": \"Reggie\", \"userPassword\": \"NewSecret\", \"jansStatus\": \"active\"}' When you execute this command, user will be created: Server Response: { \"dn\": \"inum=65a5a60c-d314-426d-a8f4-8c36325a1024,ou=people,o=jans\", \"userId\": \"padilla\", \"createdAt\": \"2023-05-30T09:48:58\", \"customAttributes\": [ { \"name\": \"sn\", \"multiValued\": false, \"values\": [ \"Padilla\" ], \"displayValue\": \"Padilla\", \"value\": \"Padilla\" } ], \"customObjectClasses\": [ \"top\", \"jansCustomPerson\" ], \"inum\": \"65a5a60c-d314-426d-a8f4-8c36325a1024\", \"mail\": \"reggie.padilla@egg.org\", \"displayName\": \"Padilla Reggie\", \"jansStatus\": \"active\", \"givenName\": \"Reggie\", \"baseDn\": \"inum=65a5a60c-d314-426d-a8f4-8c36325a1024,ou=people,o=jans\" }", "title": "Using TUI Command Line Log"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/", "tags": ["administration", "configuration", "fido2"], "text": "Janssen FIDO2 Configuration # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can deploy and customize the FIDO2 Configuration using the command line. To get the details of Janssen command line operations relevant to FIDO2 Configuration, you can check the operations under Fido2Configuration task using the command below: Command jans cli --info Fido2Configuration It will show the details of the available operation-ids for Fido2. Sample Output Operation ID: get-properties-fido2 Description: Gets Jans Authorization Server Fido2 configuration properties Operation ID: put-properties-fido2 Description: Updates Fido2 configuration properties Schema: Fido2:AppConfiguration To get sample schema type jans cli --schema <schema>, for example jans cli --schema Fido2:AppConfiguration Get The Current Fido2 Configuration # To get the properties of Janssen Fido2 Configuration, run the command below: Command jans cli --operation-id get-properties-fido2 It will return the result as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 { \"issuer\" : \"https://jans-project.lxd\" , \"baseEndpoint\" : \"https://jans-project.lxd/jans-fido2/restv1\" , \"cleanServiceInterval\" : 60 , \"cleanServiceBatchChunkSize\" : 10000 , \"useLocalCache\" : true , \"disableJdkLogger\" : true , \"loggingLevel\" : \"INFO\" , \"loggingLayout\" : \"text\" , \"metricReporterInterval\" : 300 , \"metricReporterKeepDataDays\" : 15 , \"metricReporterEnabled\" : true , \"personCustomObjectClassList\" : [ \"jansCustomPerson\" , \"jansPerson\" ], \"sessionIdPersistInCache\" : false , \"errorReasonEnabled\" : false , \"fido2Configuration\" : { \"authenticatorCertsFolder\" : \"/etc/jans/conf/fido2/authenticator_cert\" , \"mdsCertsFolder\" : \"/etc/jans/conf/fido2/mds/cert\" , \"mdsTocsFolder\" : \"/etc/jans/conf/fido2/mds/toc\" , \"checkU2fAttestations\" : false , \"debugUserAutoEnrollment\" : false , \"unfinishedRequestExpiration\" : 180 , \"authenticationHistoryExpiration\" : 1296000 , \"serverMetadataFolder\" : \"/etc/jans/conf/fido2/server_metadata\" , \"enabledFidoAlgorithms\" : [ \"RS256\" , \"ES256\" ], \"rp\" : [ { \"id\" : \"https://jans-project.lxd\" , \"origins\" : [ \"jans-project.lxd\" ] } ], \"disableMetadataService\" : false , \"attestationMode\" : \"monitor\" , \"assertionOptionsGenerateEndpointEnabled\" : true } } Update FIDO2 Configuration Properties # To update the configuration follow the steps below. Get the current configuration and store it into a file for editing Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Fido2:AppConfiguration schema as mentioned here . The schema details can be retrieved using the command below. The schema defines what values and datatypes are acceptable for each property value. Command jans cli --schema Fido2:AppConfiguration Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-properties-fido2 --data /tmp/conf-data.json Upon successful execution of the update, the Janssen Server responds with updated configuration. Using Text-based UI # In the Janssen Server, You can manage FIDO2 Configuration using the Text-Based UI also. You can start TUI using the command below: Command jans tui Navigate to FIDO section where administrators can update dynamic and static configurations. Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the FIDO2 Configuration. Endpoint details are published in the Swagger document .", "title": "FIDO2 Configuration"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#janssen-fido2-configuration", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Janssen FIDO2 Configuration"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#using-command-line", "text": "In the Janssen Server, you can deploy and customize the FIDO2 Configuration using the command line. To get the details of Janssen command line operations relevant to FIDO2 Configuration, you can check the operations under Fido2Configuration task using the command below: Command jans cli --info Fido2Configuration It will show the details of the available operation-ids for Fido2. Sample Output Operation ID: get-properties-fido2 Description: Gets Jans Authorization Server Fido2 configuration properties Operation ID: put-properties-fido2 Description: Updates Fido2 configuration properties Schema: Fido2:AppConfiguration To get sample schema type jans cli --schema <schema>, for example jans cli --schema Fido2:AppConfiguration", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#get-the-current-fido2-configuration", "text": "To get the properties of Janssen Fido2 Configuration, run the command below: Command jans cli --operation-id get-properties-fido2 It will return the result as below: Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 { \"issuer\" : \"https://jans-project.lxd\" , \"baseEndpoint\" : \"https://jans-project.lxd/jans-fido2/restv1\" , \"cleanServiceInterval\" : 60 , \"cleanServiceBatchChunkSize\" : 10000 , \"useLocalCache\" : true , \"disableJdkLogger\" : true , \"loggingLevel\" : \"INFO\" , \"loggingLayout\" : \"text\" , \"metricReporterInterval\" : 300 , \"metricReporterKeepDataDays\" : 15 , \"metricReporterEnabled\" : true , \"personCustomObjectClassList\" : [ \"jansCustomPerson\" , \"jansPerson\" ], \"sessionIdPersistInCache\" : false , \"errorReasonEnabled\" : false , \"fido2Configuration\" : { \"authenticatorCertsFolder\" : \"/etc/jans/conf/fido2/authenticator_cert\" , \"mdsCertsFolder\" : \"/etc/jans/conf/fido2/mds/cert\" , \"mdsTocsFolder\" : \"/etc/jans/conf/fido2/mds/toc\" , \"checkU2fAttestations\" : false , \"debugUserAutoEnrollment\" : false , \"unfinishedRequestExpiration\" : 180 , \"authenticationHistoryExpiration\" : 1296000 , \"serverMetadataFolder\" : \"/etc/jans/conf/fido2/server_metadata\" , \"enabledFidoAlgorithms\" : [ \"RS256\" , \"ES256\" ], \"rp\" : [ { \"id\" : \"https://jans-project.lxd\" , \"origins\" : [ \"jans-project.lxd\" ] } ], \"disableMetadataService\" : false , \"attestationMode\" : \"monitor\" , \"assertionOptionsGenerateEndpointEnabled\" : true } }", "title": "Get The Current Fido2 Configuration"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#update-fido2-configuration-properties", "text": "To update the configuration follow the steps below. Get the current configuration and store it into a file for editing Edit and update the desired configuration values in the file while keeping other properties and values unchanged. Updates must adhere to the Fido2:AppConfiguration schema as mentioned here . The schema details can be retrieved using the command below. The schema defines what values and datatypes are acceptable for each property value. Command jans cli --schema Fido2:AppConfiguration Use the updated file to send the update to the Janssen Server using the command below Command jans cli --operation-id put-properties-fido2 --data /tmp/conf-data.json Upon successful execution of the update, the Janssen Server responds with updated configuration.", "title": "Update FIDO2 Configuration Properties"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#using-text-based-ui", "text": "In the Janssen Server, You can manage FIDO2 Configuration using the Text-Based UI also. You can start TUI using the command below: Command jans tui Navigate to FIDO section where administrators can update dynamic and static configurations.", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/fido2-config/janssen-fido2-configuration/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the FIDO2 Configuration. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/", "tags": ["administration", "configuration", "group"], "text": "Group Management # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # Command jans cli -scim --info Group Command Output Operation ID: get-groups Description: Query Group resources (see section 3.4.2 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] filter: An expression specifying the search criteria. See section 3.4.2.2 of RFC 7644 [string] startIndex: The 1-based index of the first query result [integer] count: Specifies the desired maximum number of query results per page [integer] sortBy: The attribute whose value will be used to order the returned responses [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] Operation ID: create-group Description: Allows creating a Group resource via POST (see section 3.3 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] Schema: GroupResource Schema: GroupResource Operation ID: get-group-by-id Description: Retrieves a Group resource by Id (see section 3.4.1 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Operation ID: update-group-by-id Description: Updates a Group resource (see section 3.5.1 of RFC 7644). Update works in a replacement fashion&#58; every attribute value found in the payload sent will replace the one in the existing resource representation. Attributes not passed in the payload will be left intact. Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: GroupResource Schema: GroupResource Operation ID: delete-group-by-id Description: Deletes a group resource (see section 3.6 of RFC 7644) Parameters: id: Identifier of the resource to delete [string] Operation ID: patch-group-by-id Description: Updates one or more attributes of a Group resource using a sequence of additions, removals, and replacements operations. See section 3.5.2 of RFC 7644 Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: PatchRequest Schema: PatchRequest Operation ID: search-group Description: Query Group resources (see section 3.4.2 of RFC 7644) Schema: SearchRequest Schema: SearchRequest To get sample schema type jans cli -scim --schema-sample <schema>, for example jans cli -scim --schema-sample SearchRequest Get Groups # This operation can be used to get list of groups. To get the list of groups, run the following command: Command jans cli -scim --operation-id get-groups It will show the list of groups with all the members linked with each of these groups. Sample Output { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"60B7\" , \"meta\" : { \"resourceType\" : \"Group\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/60B7\" }, \"displayName\" : \"Janssen Manager Group\" , \"members\" : [ { \"value\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"type\" : \"User\" , \"display\" : \"Default Admin User\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/f764391d-56de-4b74-b0a2-f32814706dcc\" } ] } ] } You can filter for the advanced search with some of its properties: attributes excludeAttributes filter count [define maximum number of query] sortBy [attribute] sortOrder ['ascending', 'descending'] Create Group # Using create-group operation, we can create groups into Janssen Server. As we have seen in the output of --info command, this operation requires GroupResource schema. To know the details of schema, run the following command: Command jans cli -scim --schema GroupResource The Janssen server also provides sample schema. To get the sample schema of GroupResource : Command jans cli -scim --schema-sample GroupResource According to schema, let's put all the details into a json file /tmp/create-group.json to create a group. sample { \"displayName\" : \"New Group\" } Now let's run the following command to add group into the server: Command jans cli -scim --operation-id create-group --data /tmp/create-group.json Command Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"2024-09-06T03:46:31.224Z\" , \"lastModified\" : \"2024-09-06T03:46:31.224Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" } Get Group by ID # We can view the specific group details through its id using get-group-by-id operation. For example, We can put the above created group id:7a20464c-3651-48a0-9c9c-6b59373df60c with --url-suffix to get the groupe details. The following command as below: Command jans cli -scim --operation-id get-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" Command Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"lastModified\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" , \"members\" : [] } We see members is empty since we did not associate any user with this group yet. We will add members into this gorup in the next operation. Update Group by ID # The update-group-by-id operation can be used to update group name and adding members into the group. Let's create a json file /tmp/update-group.json according to the GroupResource schema: Sample { \"members\" : [ { \"value\" : \"4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" , \"type\" : \"user\" } ] } We can get the value which is actually the id of specific users from user management section. Let's run the following command to update empty members properties with a member into the group we created above . Command jans cli -scim --operation-id update-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" --data /tmp/update-group.json Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"lastModified\" : \"2024-09-06T05:15:53.227Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" , \"members\" : [ { \"value\" : \"4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" , \"type\" : \"User\" , \"display\" : \"Test User\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" } ] } Please remember one thing, this update method just replace the data. If you want to add members instead of replacing then you must try patch-group-by-id . Delete Group by ID # You can delete a group by its ID. The command line looks like: Command jans cli -scim --operation-id delete-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" It will delete the group and all of its associated data if match with the unique group ID. Patch Group # This is also an option to update any existing group resources. The only difference between update-group-by-id and patch-group is that the first one just replace new data with previous one. It won't add any new data into the group. With patch-group-by-id operation, we can add , remove , and replace properties of group. According to the output of --info command, we can see patch-group-by-id requires PatchRequest schema. [ { \"op\": \"add\", \"path\": \"members\", \"value\": { \"value\": \"f764391d-56de-4b74-b0a2-f32814706dcc\", \"type\": \"user\" } } ] Let's run the following command: Command jans cli -scim --operation-id patch-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" --data /tmp/patch-user.json Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document .", "title": "SCIM Group Management"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#group-management", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "Group Management"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#using-command-line", "text": "Command jans cli -scim --info Group Command Output Operation ID: get-groups Description: Query Group resources (see section 3.4.2 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] filter: An expression specifying the search criteria. See section 3.4.2.2 of RFC 7644 [string] startIndex: The 1-based index of the first query result [integer] count: Specifies the desired maximum number of query results per page [integer] sortBy: The attribute whose value will be used to order the returned responses [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] Operation ID: create-group Description: Allows creating a Group resource via POST (see section 3.3 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] Schema: GroupResource Schema: GroupResource Operation ID: get-group-by-id Description: Retrieves a Group resource by Id (see section 3.4.1 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Operation ID: update-group-by-id Description: Updates a Group resource (see section 3.5.1 of RFC 7644). Update works in a replacement fashion&#58; every attribute value found in the payload sent will replace the one in the existing resource representation. Attributes not passed in the payload will be left intact. Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: GroupResource Schema: GroupResource Operation ID: delete-group-by-id Description: Deletes a group resource (see section 3.6 of RFC 7644) Parameters: id: Identifier of the resource to delete [string] Operation ID: patch-group-by-id Description: Updates one or more attributes of a Group resource using a sequence of additions, removals, and replacements operations. See section 3.5.2 of RFC 7644 Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: PatchRequest Schema: PatchRequest Operation ID: search-group Description: Query Group resources (see section 3.4.2 of RFC 7644) Schema: SearchRequest Schema: SearchRequest To get sample schema type jans cli -scim --schema-sample <schema>, for example jans cli -scim --schema-sample SearchRequest", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#get-groups", "text": "This operation can be used to get list of groups. To get the list of groups, run the following command: Command jans cli -scim --operation-id get-groups It will show the list of groups with all the members linked with each of these groups. Sample Output { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"60B7\" , \"meta\" : { \"resourceType\" : \"Group\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/60B7\" }, \"displayName\" : \"Janssen Manager Group\" , \"members\" : [ { \"value\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"type\" : \"User\" , \"display\" : \"Default Admin User\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/f764391d-56de-4b74-b0a2-f32814706dcc\" } ] } ] } You can filter for the advanced search with some of its properties: attributes excludeAttributes filter count [define maximum number of query] sortBy [attribute] sortOrder ['ascending', 'descending']", "title": "Get Groups"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#create-group", "text": "Using create-group operation, we can create groups into Janssen Server. As we have seen in the output of --info command, this operation requires GroupResource schema. To know the details of schema, run the following command: Command jans cli -scim --schema GroupResource The Janssen server also provides sample schema. To get the sample schema of GroupResource : Command jans cli -scim --schema-sample GroupResource According to schema, let's put all the details into a json file /tmp/create-group.json to create a group. sample { \"displayName\" : \"New Group\" } Now let's run the following command to add group into the server: Command jans cli -scim --operation-id create-group --data /tmp/create-group.json Command Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"2024-09-06T03:46:31.224Z\" , \"lastModified\" : \"2024-09-06T03:46:31.224Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" }", "title": "Create Group"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#get-group-by-id", "text": "We can view the specific group details through its id using get-group-by-id operation. For example, We can put the above created group id:7a20464c-3651-48a0-9c9c-6b59373df60c with --url-suffix to get the groupe details. The following command as below: Command jans cli -scim --operation-id get-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" Command Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"lastModified\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" , \"members\" : [] } We see members is empty since we did not associate any user with this group yet. We will add members into this gorup in the next operation.", "title": "Get Group by ID"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#update-group-by-id", "text": "The update-group-by-id operation can be used to update group name and adding members into the group. Let's create a json file /tmp/update-group.json according to the GroupResource schema: Sample { \"members\" : [ { \"value\" : \"4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" , \"type\" : \"user\" } ] } We can get the value which is actually the id of specific users from user management section. Let's run the following command to update empty members properties with a member into the group we created above . Command jans cli -scim --operation-id update-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" --data /tmp/update-group.json Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:Group\" ], \"id\" : \"7a20464c-3651-48a0-9c9c-6b59373df60c\" , \"meta\" : { \"resourceType\" : \"Group\" , \"created\" : \"Fri Sep 06 03:46:31 UTC 2024\" , \"lastModified\" : \"2024-09-06T05:15:53.227Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/7a20464c-3651-48a0-9c9c-6b59373df60c\" }, \"displayName\" : \"New Group\" , \"members\" : [ { \"value\" : \"4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" , \"type\" : \"User\" , \"display\" : \"Test User\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/4ed288be-4d1c-4e05-a3af-7a8935fc7f4c\" } ] } Please remember one thing, this update method just replace the data. If you want to add members instead of replacing then you must try patch-group-by-id .", "title": "Update Group by ID"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#delete-group-by-id", "text": "You can delete a group by its ID. The command line looks like: Command jans cli -scim --operation-id delete-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" It will delete the group and all of its associated data if match with the unique group ID.", "title": "Delete Group by ID"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#patch-group", "text": "This is also an option to update any existing group resources. The only difference between update-group-by-id and patch-group is that the first one just replace new data with previous one. It won't add any new data into the group. With patch-group-by-id operation, we can add , remove , and replace properties of group. According to the output of --info command, we can see patch-group-by-id requires PatchRequest schema. [ { \"op\": \"add\", \"path\": \"members\", \"value\": { \"value\": \"f764391d-56de-4b74-b0a2-f32814706dcc\", \"type\": \"user\" } } ] Let's run the following command: Command jans cli -scim --operation-id patch-group-by-id \\ --url-suffix = \"id:7a20464c-3651-48a0-9c9c-6b59373df60c\" --data /tmp/patch-user.json", "title": "Patch Group"}, {"location": "janssen-server/config-guide/scim-config/scim-group-config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/scim-config/user-config/", "tags": ["administration", "configuration", "user"], "text": "User Management # The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API Using Command Line # In the Janssen Server, you can do CRUD operations for user management using its command line tool. To get the details of command line for CRUD operations relevant to User Management, you can find the operation-id under the User task using the Jans CLI in scim mode. The following command line: Command jans cli -scim --info User Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 Operation ID: get-users Description: Query User resources (see section 3.4.2 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] filter: An expression specifying the search criteria. See section 3.4.2.2 of RFC 7644 [string] startIndex: The 1-based index of the first query result [integer] count: Specifies the desired maximum number of query results per page [integer] sortBy: The attribute whose value will be used to order the returned responses [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] Operation ID: create-user Description: Allows creating a User resource via POST (see section 3.3 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] Schema: UserResource Schema: UserResource Operation ID: get-user-by-id Description: Retrieves a User resource by Id (see section 3.4.1 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Operation ID: update-user-by-id Description: Updates a User resource (see section 3.5.1 of RFC 7644). Update works in a replacement fashion; every attribute value found in the payload sent will replace the one in the existing resource representation. Attributes not passed in the payload will be left intact. Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: UserResource Schema: UserResource Operation ID: delete-user-by-id Description: Deletes a user resource Parameters: id: Identifier of the resource to delete [string] Operation ID: patch-user-by-id Description: Updates one or more attributes of a User resource using a sequence of additions, removals, and replacements operations. See section 3.5.2 of RFC 7644 Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: PatchRequest Schema: PatchRequest Operation ID: search-user Description: Query User resources (see section 3.4.2 of RFC 7644) Schema: SearchRequest Schema: SearchRequest To get sample schema type jans cli -scim --schema-sample <schema>, for example jans cli -scim --schema-sample SearchRequest Get Users List # This operation is used to get list of the users and its properties. The following command line: Command jans cli -scim --operation-id get-users Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"meta\" : { \"resourceType\" : \"User\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/f764391d-56de-4b74-b0a2-f32814706dcc\" }, \"userName\" : \"admin\" , \"name\" : { \"familyName\" : \"User\" , \"givenName\" : \"Admin\" , \"middleName\" : \"Admin\" , \"formatted\" : \"Admin Admin User\" }, \"displayName\" : \"Default Admin User\" , \"nickName\" : \"Admin\" , \"active\" : true , \"emails\" : [ { \"value\" : \"admin@imshakil-boss-guppy.gluu.info\" , \"primary\" : false } ], \"groups\" : [ { \"value\" : \"60B7\" , \"display\" : \"Janssen Manager Group\" , \"type\" : \"direct\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/60B7\" } ] } ] } As shown in the output for --info command, get-users operation-id also supports parameters for the advanced search. Those parameters are: 1. attributes 2. excludeAttributes 3. filter 4. count [ define maximum number of query ] 5. sortBy [ attribute ] 6. sortOrder [ 'ascending', 'descending' ] This is an example with endpoint-args : Command jans cli -scim --operation-id get-users --endpoint-args attributes:emails Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"emails\" : [ { \"value\" : \"admin@imshakil-boss-guppy.gluu.info\" , \"primary\" : false } ] } ] } Creating a New User # To create a new user using Jans CLI, we can use create-user operation-id. As shown in the output for --info command, the create-user operation requires data to be sent according to UserResource schema. To see the schema, use the command as below: Command jans cli -scim --schema UserResource The Janssen Server also provides sample data for the above schema. Let's run the following command to get the sample schema: Command jans cli -scim --schema-sample UserResource From the above example of schema file, we can fill required values in a data file /tmp/user.json . As we have seen in the sample schema there are lot of properties, but we are going to fill minimum to create a test user : user.json 1 2 3 4 5 6 7 8 9 10 11 12 13 { \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"password\" : \"pass@word\" , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] } Let's run the following command to create user in Janssen Server: Command jans cli -scim --operation-id create-user --data /tmp/user.json Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-04T06:36:00.882Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] } Find User by Id # We can retrieve user details using user's id . For example in the above created user id is e24c1479-4a61-4f1f-aa30-2ccc13c0b130 . To get the user details by user id, We can use the get-user-by-id operation as below: Command jans cli -scim --operation-id get-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-04T06:36:00.882Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] } Update User by Id # Using Jans CLI, We can update user information. As shown in the output command, the update-user-by-id operation requires user data that needs to be changed. You can find details of user properties in schema . Let's change the nickname for the above Test user . First,we need to put the update data into a json file /tmp/update-user.json : ```json title='update-user.json { \"nickName\": \"testuser\" } Let's run the following command: ```bash title=\"Command\" jans cli -scim --operation-id update-user-by-id \\ --url-suffix=\"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" --data /tmp/update-user.json Sample Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-05T05:38:31.491Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testuser\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] } Patch User by Id # Using patch-user-by-id operation, We can modify user properties partially. As we have seen in the Output of --info command, patch-user-by-id operation requires PatchRequest schema definition for payload data. To get the sample PatchRequest schema, run the followwing command: ```bash titl=\"Command\" jans cli -scim --schema-sample PatchRequest For example, In the above `test user`, we are going to `add` one more email, `remove` nickName and `replace` displayName. Let's put all the operations in a json file `/tmp/patch-user.json`: ```json title=\"patch-user.json\" { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"path\": \"displayName\", \"value\": \"Test User\" }, { \"op\": \"add\", \"path\": \"emails\", \"value\": [ { \"value\": \"test.user@example.jans.io\", \"primary\": true } ] }, { \"op\": \"remove\", \"path\": \"nickName\" } ] } The command line to run all of these operations: Command jans cli -scim --operation patch-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" \\ --data /tmp/patch-user.json Delete User by ID # To delete the, run the following command with the specific user ID as --url-suffix=id:user-id . For example, let's delete the test user we have created earlier: Command jans cli -scim --operation-id delete-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" Using Text-based UI # Using TUI, We can add, update and deleter users in the Janssen Server. To do that, Let's start TUI using the command below: Command /opt/jans/jans-cli/jans_cli_tui.py Navigate to Users to open the users tab as shown in the image below: We can see the list of users from search option To get the list of users available in the Janssen Server, bring the control to Search box (using tab key) and press Enter key. Let's see at a glance of available user attributes. Attributes Description Username ... Password ... First Name ... Middle Name ... Last Name ... Display Name ... Email ... Active ... Nickname ... CIBA Device Registration Token ... CIBA User code ... Locale ... Website URL ... IMAP Data ... jansAdminUIRole ... Enrollment code ... User Permission ... Preferred Language ... Profile URL ... Secret Question ... Email Verified ... Birthdate ... Time zone info ... Phone Number verified ... Preferred Username ... TransientId ... PersistentId ... Country ... Secret Answer ... OpenID Connect JSON formatted address ... User certificate ... Organization ... Picture URL ... Add User # Let's add an user by selecting Add Users tab. Initially we can provide bellow attributes value, We can add extra claims simply by slecting Add Claim Finally save and exit. We will get an unique inum Update User # To modify any user properties, find the user from search box and hit Enter to pop-up user details, update user details and finally hit on Save button to update the changes. Delete User # To delete user, bring the control on the specific user row and press delete or d key from keyboard. It will show a pop-up for confirmation as below: Using Configuration REST API # Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document . Get SCIM Client # Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. To see in JSON formate please press d . From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE . Get Access token # Let's get a token, curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type=client_credentials -d scope='https://jans.io/scim/users.read https://jans.io/scim/users write' https://<jans-server>/jans-auth/restv1/token > /tmp/token.json In response token.json we will get access_token { \"access_token\":\"11a76589-7955-4247-9ca5-f3ad7884305...\", \"scope\":\"https://jans.io/scim/users.read\", \"token_type\":\"Bearer\", \"expires_in\":299 } Retrive existing User # To get an existing user curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://<jans-server>/jans-scim/restv1/v2/Users > /tmp/user.json In response user.json we will get { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\": 1, \"startIndex\": 1, \"itemsPerPage\": 1, \"Resources\": [ { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"5fdbb720-a1fd-477f-af92-b7c054f02c98\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-12T14:54:09.531Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/5fdbb720-a1fd-477f-af92-b7c054f02c98\" }, \"userName\": \"admin\", \"name\": { \"familyName\": \"...\", \"givenName\": \"...\", \"middleName\": \"...\", \"formatted\": \"...\" }, \"displayName\": \"Admin\", \"active\": true, \"emails\": [ { \"value\": \"example@gluu.org\", \"primary\": false } ], \"groups\": [ { \"value\": \"60B7\", \"display\": \"Jannsen Manager Group\", \"type\": \"direct\", \"$ref\": \"https://raju.jans13.me/jans-scim/restv1/v2/Groups/60B7\" } ] } ] } Create an User # Let's start creating a dummy user. A client sends a POST request containing a \"User\" to the \"/Users\" endpoint. POST /Users HTTP/1.1 Host: example.com Accept: application/scim+json Content-Type: application/scim+json Authorization: Bearer h480djs93hd8.. Content-Length: ... { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" } } Open a text editor and copy paste the json body, name as input.json . Hit on your terminal with bellow command. curl -k -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users response looks like { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T19:43:32.945Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Barbara\", \"formatted\": \"Ms. Barbara J Jensen III\" } } This new user has been given an id . If possible, inspect your ou=people branch and find the entry whose inum matches the id given. An easier option would be to via Jans TUI and go to Users and search \"bjensen\" to see the recently created user. Updating a User(PUT) # Overwrite your input.json with the following. Replace content in angle brackets accordingly: { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" }, \"displayName\": \"Jensen Barbara\", \"emails\": [ { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": true } ] } PUT with curl : curl -k -X PUT -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Response (output.json) will show the same contents of a full retrieval. Please verify changes were applied whether by inspecting LDAP or issuing a GET. If you have followed the steps properly, you should notice a new e-mail added and the change in displayName attribute Updating a User (PATCH) # With patching, you can be very precise about the modifications you want to apply. Patching syntax follows JSON Patch spec (RFC 6902) closely. While it's not a must to read the RFC to learn how patch works, see section 3.5.2 of SCIM protocol (RFC 7644) to get the grasp. If you prefer reading code, patch test cases found in the Java scim-client project are worth to look at. The following is a simple example that illustrates the kind of modifications developers can achieve via PATCH . Overwrite your input.json with the following: { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"value\": { \"name\": { \"givenName\": \"Joey\" } } }, { \"op\": \"replace\", \"path\": \"emails[type eq \\\"work\\\" or primary eq false].value\", \"value\": \"jensen@example.com\" }, { \"op\": \"add\", \"value\": { \"name\": { \"middleName\": \"Jhon\" } } }, { \"op\": \"add\", \"value\": { \"emails\": [ { \"primary\": true, \"value\": \"my@own.mail\" } ], \"phoneNumbers\": [ { \"type\": \"home\", \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } }, { \"op\": \"remove\", \"path\": \"name.middleName\" }, { \"op\": \"remove\", \"path\": \"phoneNumbers[value ew \\\"01\\\"].type\" } ] } A collection of modification are provided under \"Operations\". They are processed in order of appearance. Also, every operation has a type; patching supports add, remove and replace. The first operations states the following: replace the value of givenName subattribute (that belongs to complex attribute name ) with the string \"Joey\". Operations are easier to understand when using a \"path\". The second operation replaces the value subattribute inside the complex multi-valued attribute emails. Inside the square brackets, we find a filter expression, so the replacement does not apply to all emails in the list but only to those matching the criterion. So the second operation can be read as \"set the value of value subattribute to string jensen@example.com where the type subattribute of the email equals to string \"work\" or if primary attribute is false\". The third operation is similar to the first. It sets the value of a subattribute which was unassigned (null). You could have used \"replace\" operation in this case and results would have been identical. The fourth operation is more interesting. It adds to the current list of emails a new one. It supplies a couple of subattributes for the email to include: primary and value. Additionally, we set the value of (previously unassigned) phoneNumbers multi-valued attribute passing a list of elements. In the fifth operation, we remove the middleName attribute that was set in operation three. Note how we make explicit the path of data to nullify: \"name.middleName\". The sixth operation allows us to remove a specific subattribute of phoneNumbers . The aim is to nullify the \"type\" of the item whose phone number value ends with \"01\". The remove operation can also be used to remove a complete item from a list, or empty the whole list by providing a suitable value for \"path\". Now let's see it in action: curl -k -X PATCH -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> So far our resource look like this { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T22:34:27.465Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Joey\", \"formatted\": \"Ms. Barbara J Jensen III\" }, \"displayName\": \"Jensen Barbara\", \"active\": false, \"emails\": [ { \"value\": \"my@own.mail\", \"primary\": true }, { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": false } ], \"phoneNumbers\": [ { \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } Note the primary subattribute accompanying email \"my@own.mail\" is false but when inserted we provided true . This is because the SCIM specification states that after modifications are applied to resources (PUT or PATCH) , there cannot be more than one item in a multi-valued attribute with primary value set as true . To see more sample JSON payloads, check the .json files used by the scim-client test cases referenced above. Deleting Users # For deleting, the DELETE method of HTTP is used. No input file is used in this case. A delete request could be the following: curl -k -X DELETE -H 'Authorization: Bearer ACCESS_TOKEN' https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Use the inum of our dummy user, Jensen Barbara . Check your LDAP or via Jans TUI to see that Bjensen is gone.", "title": "SCIM User Resources"}, {"location": "janssen-server/config-guide/scim-config/user-config/#user-management", "text": "The Janssen Server provides multiple configuration tools to perform these tasks. Use Command-line Use Text-based UI Use REST API Use the command line to perform actions from the terminal. Learn how to use Jans CLI here or jump straight to the Using Command Line Use a fully functional text-based user interface from the terminal. Learn how to use Jans Text-based UI (TUI) here or jump straight to the Using Text-based UI Use REST API for programmatic access or invoke via tools like CURL or Postman. Learn how to use Janssen Server Config API here or Jump straight to the Using Configuration REST API", "title": "User Management"}, {"location": "janssen-server/config-guide/scim-config/user-config/#using-command-line", "text": "In the Janssen Server, you can do CRUD operations for user management using its command line tool. To get the details of command line for CRUD operations relevant to User Management, you can find the operation-id under the User task using the Jans CLI in scim mode. The following command line: Command jans cli -scim --info User Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 Operation ID: get-users Description: Query User resources (see section 3.4.2 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] filter: An expression specifying the search criteria. See section 3.4.2.2 of RFC 7644 [string] startIndex: The 1-based index of the first query result [integer] count: Specifies the desired maximum number of query results per page [integer] sortBy: The attribute whose value will be used to order the returned responses [string] sortOrder: Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\" [string] Operation ID: create-user Description: Allows creating a User resource via POST (see section 3.3 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] Schema: UserResource Schema: UserResource Operation ID: get-user-by-id Description: Retrieves a User resource by Id (see section 3.4.1 of RFC 7644) Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Operation ID: update-user-by-id Description: Updates a User resource (see section 3.5.1 of RFC 7644). Update works in a replacement fashion; every attribute value found in the payload sent will replace the one in the existing resource representation. Attributes not passed in the payload will be left intact. Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: UserResource Schema: UserResource Operation ID: delete-user-by-id Description: Deletes a user resource Parameters: id: Identifier of the resource to delete [string] Operation ID: patch-user-by-id Description: Updates one or more attributes of a User resource using a sequence of additions, removals, and replacements operations. See section 3.5.2 of RFC 7644 Parameters: attributes: A comma-separated list of attribute names to return in the response [string] excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] id: No description is provided for this parameter [string] Schema: PatchRequest Schema: PatchRequest Operation ID: search-user Description: Query User resources (see section 3.4.2 of RFC 7644) Schema: SearchRequest Schema: SearchRequest To get sample schema type jans cli -scim --schema-sample <schema>, for example jans cli -scim --schema-sample SearchRequest", "title": "Using Command Line"}, {"location": "janssen-server/config-guide/scim-config/user-config/#get-users-list", "text": "This operation is used to get list of the users and its properties. The following command line: Command jans cli -scim --operation-id get-users Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"meta\" : { \"resourceType\" : \"User\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/f764391d-56de-4b74-b0a2-f32814706dcc\" }, \"userName\" : \"admin\" , \"name\" : { \"familyName\" : \"User\" , \"givenName\" : \"Admin\" , \"middleName\" : \"Admin\" , \"formatted\" : \"Admin Admin User\" }, \"displayName\" : \"Default Admin User\" , \"nickName\" : \"Admin\" , \"active\" : true , \"emails\" : [ { \"value\" : \"admin@imshakil-boss-guppy.gluu.info\" , \"primary\" : false } ], \"groups\" : [ { \"value\" : \"60B7\" , \"display\" : \"Janssen Manager Group\" , \"type\" : \"direct\" , \"$ref\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Groups/60B7\" } ] } ] } As shown in the output for --info command, get-users operation-id also supports parameters for the advanced search. Those parameters are: 1. attributes 2. excludeAttributes 3. filter 4. count [ define maximum number of query ] 5. sortBy [ attribute ] 6. sortOrder [ 'ascending', 'descending' ] This is an example with endpoint-args : Command jans cli -scim --operation-id get-users --endpoint-args attributes:emails Sample Output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 { \"schemas\" : [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\" : 1 , \"startIndex\" : 1 , \"itemsPerPage\" : 1 , \"Resources\" : [ { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"f764391d-56de-4b74-b0a2-f32814706dcc\" , \"emails\" : [ { \"value\" : \"admin@imshakil-boss-guppy.gluu.info\" , \"primary\" : false } ] } ] }", "title": "Get Users List"}, {"location": "janssen-server/config-guide/scim-config/user-config/#creating-a-new-user", "text": "To create a new user using Jans CLI, we can use create-user operation-id. As shown in the output for --info command, the create-user operation requires data to be sent according to UserResource schema. To see the schema, use the command as below: Command jans cli -scim --schema UserResource The Janssen Server also provides sample data for the above schema. Let's run the following command to get the sample schema: Command jans cli -scim --schema-sample UserResource From the above example of schema file, we can fill required values in a data file /tmp/user.json . As we have seen in the sample schema there are lot of properties, but we are going to fill minimum to create a test user : user.json 1 2 3 4 5 6 7 8 9 10 11 12 13 { \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"password\" : \"pass@word\" , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] } Let's run the following command to create user in Janssen Server: Command jans cli -scim --operation-id create-user --data /tmp/user.json Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-04T06:36:00.882Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] }", "title": "Creating a New User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#find-user-by-id", "text": "We can retrieve user details using user's id . For example in the above created user id is e24c1479-4a61-4f1f-aa30-2ccc13c0b130 . To get the user details by user id, We can use the get-user-by-id operation as below: Command jans cli -scim --operation-id get-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-04T06:36:00.882Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testu\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] }", "title": "Find User by Id"}, {"location": "janssen-server/config-guide/scim-config/user-config/#update-user-by-id", "text": "Using Jans CLI, We can update user information. As shown in the output command, the update-user-by-id operation requires user data that needs to be changed. You can find details of user properties in schema . Let's change the nickname for the above Test user . First,we need to put the update data into a json file /tmp/update-user.json : ```json title='update-user.json { \"nickName\": \"testuser\" } Let's run the following command: ```bash title=\"Command\" jans cli -scim --operation-id update-user-by-id \\ --url-suffix=\"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" --data /tmp/update-user.json Sample Output { \"schemas\" : [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\" : \"e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" , \"meta\" : { \"resourceType\" : \"User\" , \"created\" : \"2024-09-04T06:36:00.882Z\" , \"lastModified\" : \"2024-09-05T05:38:31.491Z\" , \"location\" : \"https://imshakil-boss-guppy.gluu.info/jans-scim/restv1/v2/Users/e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" }, \"userName\" : \"test.user\" , \"displayName\" : \"Test User\" , \"nickName\" : \"testuser\" , \"active\" : true , \"emails\" : [ { \"value\" : \"testuser@maildomain.net\" , \"primary\" : true } ] }", "title": "Update User by Id"}, {"location": "janssen-server/config-guide/scim-config/user-config/#patch-user-by-id", "text": "Using patch-user-by-id operation, We can modify user properties partially. As we have seen in the Output of --info command, patch-user-by-id operation requires PatchRequest schema definition for payload data. To get the sample PatchRequest schema, run the followwing command: ```bash titl=\"Command\" jans cli -scim --schema-sample PatchRequest For example, In the above `test user`, we are going to `add` one more email, `remove` nickName and `replace` displayName. Let's put all the operations in a json file `/tmp/patch-user.json`: ```json title=\"patch-user.json\" { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"path\": \"displayName\", \"value\": \"Test User\" }, { \"op\": \"add\", \"path\": \"emails\", \"value\": [ { \"value\": \"test.user@example.jans.io\", \"primary\": true } ] }, { \"op\": \"remove\", \"path\": \"nickName\" } ] } The command line to run all of these operations: Command jans cli -scim --operation patch-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\" \\ --data /tmp/patch-user.json", "title": "Patch User by Id"}, {"location": "janssen-server/config-guide/scim-config/user-config/#delete-user-by-id", "text": "To delete the, run the following command with the specific user ID as --url-suffix=id:user-id . For example, let's delete the test user we have created earlier: Command jans cli -scim --operation-id delete-user-by-id \\ --url-suffix = \"id:e24c1479-4a61-4f1f-aa30-2ccc13c0b130\"", "title": "Delete User by ID"}, {"location": "janssen-server/config-guide/scim-config/user-config/#using-text-based-ui", "text": "Using TUI, We can add, update and deleter users in the Janssen Server. To do that, Let's start TUI using the command below: Command /opt/jans/jans-cli/jans_cli_tui.py Navigate to Users to open the users tab as shown in the image below: We can see the list of users from search option To get the list of users available in the Janssen Server, bring the control to Search box (using tab key) and press Enter key. Let's see at a glance of available user attributes. Attributes Description Username ... Password ... First Name ... Middle Name ... Last Name ... Display Name ... Email ... Active ... Nickname ... CIBA Device Registration Token ... CIBA User code ... Locale ... Website URL ... IMAP Data ... jansAdminUIRole ... Enrollment code ... User Permission ... Preferred Language ... Profile URL ... Secret Question ... Email Verified ... Birthdate ... Time zone info ... Phone Number verified ... Preferred Username ... TransientId ... PersistentId ... Country ... Secret Answer ... OpenID Connect JSON formatted address ... User certificate ... Organization ... Picture URL ...", "title": "Using Text-based UI"}, {"location": "janssen-server/config-guide/scim-config/user-config/#add-user", "text": "Let's add an user by selecting Add Users tab. Initially we can provide bellow attributes value, We can add extra claims simply by slecting Add Claim Finally save and exit. We will get an unique inum", "title": "Add User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#update-user", "text": "To modify any user properties, find the user from search box and hit Enter to pop-up user details, update user details and finally hit on Save button to update the changes.", "title": "Update User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#delete-user", "text": "To delete user, bring the control on the specific user row and press delete or d key from keyboard. It will show a pop-up for confirmation as below:", "title": "Delete User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#using-configuration-rest-api", "text": "Janssen Server Configuration REST API exposes relevant endpoints for managing and configuring the OpenID Connect Client. Endpoint details are published in the Swagger document .", "title": "Using Configuration REST API"}, {"location": "janssen-server/config-guide/scim-config/user-config/#get-scim-client", "text": "Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. To see in JSON formate please press d . From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE .", "title": "Get SCIM Client"}, {"location": "janssen-server/config-guide/scim-config/user-config/#get-access-token", "text": "Let's get a token, curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type=client_credentials -d scope='https://jans.io/scim/users.read https://jans.io/scim/users write' https://<jans-server>/jans-auth/restv1/token > /tmp/token.json In response token.json we will get access_token { \"access_token\":\"11a76589-7955-4247-9ca5-f3ad7884305...\", \"scope\":\"https://jans.io/scim/users.read\", \"token_type\":\"Bearer\", \"expires_in\":299 }", "title": "Get Access token"}, {"location": "janssen-server/config-guide/scim-config/user-config/#retrive-existing-user", "text": "To get an existing user curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://<jans-server>/jans-scim/restv1/v2/Users > /tmp/user.json In response user.json we will get { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\": 1, \"startIndex\": 1, \"itemsPerPage\": 1, \"Resources\": [ { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"5fdbb720-a1fd-477f-af92-b7c054f02c98\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-12T14:54:09.531Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/5fdbb720-a1fd-477f-af92-b7c054f02c98\" }, \"userName\": \"admin\", \"name\": { \"familyName\": \"...\", \"givenName\": \"...\", \"middleName\": \"...\", \"formatted\": \"...\" }, \"displayName\": \"Admin\", \"active\": true, \"emails\": [ { \"value\": \"example@gluu.org\", \"primary\": false } ], \"groups\": [ { \"value\": \"60B7\", \"display\": \"Jannsen Manager Group\", \"type\": \"direct\", \"$ref\": \"https://raju.jans13.me/jans-scim/restv1/v2/Groups/60B7\" } ] } ] }", "title": "Retrive existing User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#create-an-user", "text": "Let's start creating a dummy user. A client sends a POST request containing a \"User\" to the \"/Users\" endpoint. POST /Users HTTP/1.1 Host: example.com Accept: application/scim+json Content-Type: application/scim+json Authorization: Bearer h480djs93hd8.. Content-Length: ... { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" } } Open a text editor and copy paste the json body, name as input.json . Hit on your terminal with bellow command. curl -k -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users response looks like { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T19:43:32.945Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Barbara\", \"formatted\": \"Ms. Barbara J Jensen III\" } } This new user has been given an id . If possible, inspect your ou=people branch and find the entry whose inum matches the id given. An easier option would be to via Jans TUI and go to Users and search \"bjensen\" to see the recently created user.", "title": "Create an User"}, {"location": "janssen-server/config-guide/scim-config/user-config/#updating-a-userput", "text": "Overwrite your input.json with the following. Replace content in angle brackets accordingly: { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" }, \"displayName\": \"Jensen Barbara\", \"emails\": [ { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": true } ] } PUT with curl : curl -k -X PUT -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Response (output.json) will show the same contents of a full retrieval. Please verify changes were applied whether by inspecting LDAP or issuing a GET. If you have followed the steps properly, you should notice a new e-mail added and the change in displayName attribute", "title": "Updating a User(PUT)"}, {"location": "janssen-server/config-guide/scim-config/user-config/#updating-a-user-patch", "text": "With patching, you can be very precise about the modifications you want to apply. Patching syntax follows JSON Patch spec (RFC 6902) closely. While it's not a must to read the RFC to learn how patch works, see section 3.5.2 of SCIM protocol (RFC 7644) to get the grasp. If you prefer reading code, patch test cases found in the Java scim-client project are worth to look at. The following is a simple example that illustrates the kind of modifications developers can achieve via PATCH . Overwrite your input.json with the following: { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"value\": { \"name\": { \"givenName\": \"Joey\" } } }, { \"op\": \"replace\", \"path\": \"emails[type eq \\\"work\\\" or primary eq false].value\", \"value\": \"jensen@example.com\" }, { \"op\": \"add\", \"value\": { \"name\": { \"middleName\": \"Jhon\" } } }, { \"op\": \"add\", \"value\": { \"emails\": [ { \"primary\": true, \"value\": \"my@own.mail\" } ], \"phoneNumbers\": [ { \"type\": \"home\", \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } }, { \"op\": \"remove\", \"path\": \"name.middleName\" }, { \"op\": \"remove\", \"path\": \"phoneNumbers[value ew \\\"01\\\"].type\" } ] } A collection of modification are provided under \"Operations\". They are processed in order of appearance. Also, every operation has a type; patching supports add, remove and replace. The first operations states the following: replace the value of givenName subattribute (that belongs to complex attribute name ) with the string \"Joey\". Operations are easier to understand when using a \"path\". The second operation replaces the value subattribute inside the complex multi-valued attribute emails. Inside the square brackets, we find a filter expression, so the replacement does not apply to all emails in the list but only to those matching the criterion. So the second operation can be read as \"set the value of value subattribute to string jensen@example.com where the type subattribute of the email equals to string \"work\" or if primary attribute is false\". The third operation is similar to the first. It sets the value of a subattribute which was unassigned (null). You could have used \"replace\" operation in this case and results would have been identical. The fourth operation is more interesting. It adds to the current list of emails a new one. It supplies a couple of subattributes for the email to include: primary and value. Additionally, we set the value of (previously unassigned) phoneNumbers multi-valued attribute passing a list of elements. In the fifth operation, we remove the middleName attribute that was set in operation three. Note how we make explicit the path of data to nullify: \"name.middleName\". The sixth operation allows us to remove a specific subattribute of phoneNumbers . The aim is to nullify the \"type\" of the item whose phone number value ends with \"01\". The remove operation can also be used to remove a complete item from a list, or empty the whole list by providing a suitable value for \"path\". Now let's see it in action: curl -k -X PATCH -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> So far our resource look like this { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T22:34:27.465Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Joey\", \"formatted\": \"Ms. Barbara J Jensen III\" }, \"displayName\": \"Jensen Barbara\", \"active\": false, \"emails\": [ { \"value\": \"my@own.mail\", \"primary\": true }, { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": false } ], \"phoneNumbers\": [ { \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } Note the primary subattribute accompanying email \"my@own.mail\" is false but when inserted we provided true . This is because the SCIM specification states that after modifications are applied to resources (PUT or PATCH) , there cannot be more than one item in a multi-valued attribute with primary value set as true . To see more sample JSON payloads, check the .json files used by the scim-client test cases referenced above.", "title": "Updating a User (PATCH)"}, {"location": "janssen-server/config-guide/scim-config/user-config/#deleting-users", "text": "For deleting, the DELETE method of HTTP is used. No input file is used in this case. A delete request could be the following: curl -k -X DELETE -H 'Authorization: Bearer ACCESS_TOKEN' https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Use the inum of our dummy user, Jensen Barbara . Check your LDAP or via Jans TUI to see that Bjensen is gone.", "title": "Deleting Users"}, {"location": "janssen-server/developer/cors/", "tags": ["administration", "installation"], "text": "CORS Filter # Overview # CORS Filter is an implementation of the W3C's Cross-Origin Resource Sharing (CORS) specification . The CORS Filter works by adding required Access-Control-* headers to the HttpServletResponse object. The filter also protects against HTTP response splitting. If a request is invalid or not permitted, the request is rejected with HTTP status code 403 (Forbidden). The minimal configuration required to use the CORS Filter is shown below, and is already added to the web.xml in jans-auth.war . The filter name is io.jans.as.server.filter.CorsFilter . <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern /> </filter-mapping> Configure CORS # CORS can be configured in Jans Server using Jans TUI . Follow these steps: Open Jans TUI using jans tui command. Go to Auth Server > Properties and select corsConfigurationFilters This will display the CORS Configuration Filter parameters, as shown below: Define and configure the parameters. Click save at the bottom of the page. Parameters supported by CORS Filters # CORS Filter supports the following initialization parameters: Attribute Description corsAllowedOrigins A list of origins that are allowed to access the resource. A * can be specified to enable access to resource from any origin. Otherwise, a whitelist of comma separated origins can be provided. Eg: http://www.w3.org , https://www.apache.org. Defaults: * (Any origin is allowed to access the resource). corsAllowedMethods A comma separated list of HTTP methods that can be used to access the resource, using cross-origin requests. These are the methods which will also be included as part of Access-Control-Allow-Methods header in pre-flight response. Eg: GET , POST . Defaults: GET , POST , HEAD , OPTIONS corsExposedHeaders A comma separated list of request headers that can be used when making an actual request. These headers will also be returned as part of Access-Control-Allow-Headers header in a pre-flight response. Eg: Origin, Accept . Defaults: Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers corsSupportCredentials A flag that indicates whether the resource supports user credentials. This flag is exposed as part of Access-Control-Allow-Credentials header in a pre-flight response. It helps browser determine whether or not an actual request can be made using credentials. Defaults: true corsLoggingEnabled Value to enable logging, Setting the value to False will disable logging. Defaults: true corsPreflightMaxAge The duration in seconds the browser is allowed to cache the result of the pre-flight request. This will be included as part of the Access-Control-Max-Age header in the pre-flight response. A negative value will prevent the CORS Filter from adding this response header to the pre-flight response. Defaults: 1800 corsRequestDecorate A flag to control if CORS specific attributes should be added to the HttpServletRequest object. Defaults: true", "title": "CORS"}, {"location": "janssen-server/developer/cors/#cors-filter", "text": "", "title": "CORS Filter"}, {"location": "janssen-server/developer/cors/#overview", "text": "CORS Filter is an implementation of the W3C's Cross-Origin Resource Sharing (CORS) specification . The CORS Filter works by adding required Access-Control-* headers to the HttpServletResponse object. The filter also protects against HTTP response splitting. If a request is invalid or not permitted, the request is rejected with HTTP status code 403 (Forbidden). The minimal configuration required to use the CORS Filter is shown below, and is already added to the web.xml in jans-auth.war . The filter name is io.jans.as.server.filter.CorsFilter . <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern /> </filter-mapping>", "title": "Overview"}, {"location": "janssen-server/developer/cors/#configure-cors", "text": "CORS can be configured in Jans Server using Jans TUI . Follow these steps: Open Jans TUI using jans tui command. Go to Auth Server > Properties and select corsConfigurationFilters This will display the CORS Configuration Filter parameters, as shown below: Define and configure the parameters. Click save at the bottom of the page.", "title": "Configure CORS"}, {"location": "janssen-server/developer/cors/#parameters-supported-by-cors-filters", "text": "CORS Filter supports the following initialization parameters: Attribute Description corsAllowedOrigins A list of origins that are allowed to access the resource. A * can be specified to enable access to resource from any origin. Otherwise, a whitelist of comma separated origins can be provided. Eg: http://www.w3.org , https://www.apache.org. Defaults: * (Any origin is allowed to access the resource). corsAllowedMethods A comma separated list of HTTP methods that can be used to access the resource, using cross-origin requests. These are the methods which will also be included as part of Access-Control-Allow-Methods header in pre-flight response. Eg: GET , POST . Defaults: GET , POST , HEAD , OPTIONS corsExposedHeaders A comma separated list of request headers that can be used when making an actual request. These headers will also be returned as part of Access-Control-Allow-Headers header in a pre-flight response. Eg: Origin, Accept . Defaults: Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers corsSupportCredentials A flag that indicates whether the resource supports user credentials. This flag is exposed as part of Access-Control-Allow-Credentials header in a pre-flight response. It helps browser determine whether or not an actual request can be made using credentials. Defaults: true corsLoggingEnabled Value to enable logging, Setting the value to False will disable logging. Defaults: true corsPreflightMaxAge The duration in seconds the browser is allowed to cache the result of the pre-flight request. This will be included as part of the Access-Control-Max-Age header in the pre-flight response. A negative value will prevent the CORS Filter from adding this response header to the pre-flight response. Defaults: 1800 corsRequestDecorate A flag to control if CORS specific attributes should be added to the HttpServletRequest object. Defaults: true", "title": "Parameters supported by CORS Filters"}, {"location": "janssen-server/developer/external-libraries/", "tags": ["administration", "developer", "external", "libraries"], "text": "Using External Libraries In Interception Scripts # Janssen Server Interception script is a very powerful tool that enables developers to control many different aspects of the authentication process. It is possible to use external libraries in interception scripts. It is possible to use external libraries Java libraries in pure Java based interception script. If the interception script is implemented in Jython then it is possible to use external Java libraries as well as external Python libraries .", "title": "External Libraries"}, {"location": "janssen-server/developer/external-libraries/#using-external-libraries-in-interception-scripts", "text": "Janssen Server Interception script is a very powerful tool that enables developers to control many different aspects of the authentication process. It is possible to use external libraries in interception scripts. It is possible to use external libraries Java libraries in pure Java based interception script. If the interception script is implemented in Jython then it is possible to use external Java libraries as well as external Python libraries .", "title": "Using External Libraries In Interception Scripts"}, {"location": "janssen-server/developer/managed-beans/", "tags": ["administration", "developer", "bean", "CdiUtil"], "text": "Ready-to-use code in Custom script: # Jans-auth server uses Weld 3.0 (JSR-365 aka CDI 2.0) for managed beans. The most useful functions are implemented through a set of beans which can be re-used in all custom scripts. Obtaining a bean inside a custom script: # CdiUtil used to obtain managed beans inside a custom script. Relevant methods: Signature Description T bean(Class clazz) Gets the managed bean belonging to the class passed as parameter Usage (jython code): Suppose UserService and AuthenticationService beans have to be referenced in the code, it can be done as below: from io.jans.as.server.service import UserService from io.jans.as.server.service import AuthenticationService ... userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) Commonly used beans: # 1. AuthenticationService # Allows to authenticate a user or obtain the current authenticated user Relevant methods: Signature Description boolean authenticate(String userName) Performs authentication for the user whose identifier ( userName ) is passed as parameter boolean authenticate(String userName, String password) Performs authentication for the user whose identifier ( userName ) is passed as parameter. The password supplied must be the correct password of the user in question User getAuthenticatedUser() Returns a representation of the currently authenticated user. null if no user is currently authenticated. See User data object Usage: from io.jans.as.server.service import AuthenticationService ... #1. authenticate a user using username and password authenticationService = CdiUtil.bean(AuthenticationService) logged_in = authenticationService.authenticate(user_name, user_password) # 2. authenticate method without passing password parameter logged_in = authenticationService.authenticate(user_name) #3. obtain an authenticated user user = authenticationService.getAuthenticatedUser() userName = user.getUserId() emailIds = user.getAttribute(\"oxEmailAlternate\") 2. UserService # Allows CRUD operations for users to the local persistence. Relevant methods: Signature Description User addUser(User user, boolean active) Creates a new user based on the representation passed as parameter. active parameter denotes whether user status ( gluuStatus attribute) will be active or register User addUserAttribute(String userId, String attributeName, String attributeValue) Adds an attribute to the user identified by userId in the database with the name and value passed. Returns a representation of the modified user or null in case of failure or if such name/attribute is already part of such user boolean addUserAttribute(User user, String attributeName, String attributeValue) Adds an attribute to the user object with the name and value passed. This method only alters the user argument and does not persist changes. Returns false if such name/attribute is already part of user User addUserAttributeByUserInum(String userInum, String attributeName, String attributeValue) Adds an attribute to the user whose inum attribute (in the database) equals to userInum using the name and value passed. Returns a representation of the modified user or null in case of failure or if such name/attribute is already part of such user CustomAttribute getCustomAttribute(User user, String attributeName) Gets a representation of the attribute whose name is passed for the user in question ( user ). Returns null if no such attribute is populated String getDnForUser(String inum) Obtains the DN (distinguished name) of the user whose inum attribute equals to userInum (no check that such user may exist is actually made) User getUser(String userId, String... returnAttributes) Retrieves a user representation for the user identified with userId containing only the attributes requested ( returnAttributes ). null is returned if no such user exists User getUserByAttribute(String attributeName, String attributeValue) Retrieves a user (first available) such that the attribute referenced ( attributeName ) has the value passed ( attributeValue ). null is returned if no such user exists String getUserInum(String userId) Retrieves the inum database attribute for the user identified with userId . null is returned if no such user exists User removeUserAttribute(String userId, String attributeName, String attributeValue) Removes attributeValue from the values of the attribute whose name is passed ( attributeName ) for the user identified with userId User replaceUserAttribute(String userId, String attributeName, String oldAttributeValue, String newAttributeValue) Updates the user identified with userId by replacing the value of the attribute attributeName with the value passed. null is returned if no such user exists void setCustomAttribute(User user, String attributeName, String attributeValue) Sets the value of the attribute attributeName with the single value attributeValue for the user representation passes as parameter. This method does not persist changes User updateUser(User user) Updates the user represented by user object in the database Usage # a. Add a user # from io.jans.as.common.service.common import UserService from io.jans.orm.model.base import CustomObjectAttribute; ... new_user = User() found_user.getCustomAttributes().add(new CustomObjectAttribute(\"address\", Arrays.asList(\"London\", \"Texas\", \"Kiev\"))); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"birthdate\", new Date())); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"scimCustomThird\", 18)); found_user.setUserRole(UserRole.ADMIN); found_user.setMemberOf(Arrays.asList(\"group_1\", \"group_2\", \"group_3\")); CustomObjectAttribute multiValuedSingleValue = new CustomObjectAttribute(\"oxExternalUid\", \"multivalued_single_valued\"); multiValuedSingleValue.setMultiValued(true); foundUser.getCustomAttributes().add(multiValuedSingleValue); new_user = CdiUtil.bean(UserService).addUser(new_user, True) b. Add user attributes # userObject = userService.addUserAttribute(user_name, \"oxExternalUid\", cert_user_external_uid, true) c. Get User # # example 1 - get User by userId user = userService.getUser(user_name) # example 2 - get User by User-Id only if attribute oxExternalUid is populated user = userService.getUser(user_name, \"oxExternalUid\") customAttributeValue = userService.getCustomAttribute(user, \"oxExternalUid\") d. Get specific User attribute # status_attribute_value = userService.getCustomAttribute(find_user_by_uid, \"gluuStatus\") e. Replace user attributes # userService.replaceUserAttribute(user_name, \"oxOTPCache\", cachedOTP, localTotpKey) f. Remove user attribute # userService.removeUserAttribute(user.getUserId(),\"oxTrustExternalId\", \"wwpass:%s\"%puid) g. Update users # found_user = userService.getUser(user_name) found_user.getCustomAttributes().add(new CustomObjectAttribute(\"address\", Arrays.asList(\"London\", \"Texas\", \"Kiev\"))); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"birthdate\", new Date())); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"scimCustomThird\", 18)); found_user.setUserRole(UserRole.ADMIN); found_user.setMemberOf(Arrays.asList(\"group_1\", \"group_2\", \"group_3\")); userService.updateUser(found_user) 4. User # A class employed to represent a user entry in the persistence. Provides getters and setters to retrieve and assign value(s) for attributes 5. CustomAttribute # A class that models an attribute. An attribute has a name and a collection of associated values 6. Identity # The authentication flow in jans-auth server is stateless and the instance is preserved because the Identity parameters (another name for session parameters) are persisted in databases. A function in the PersonAuthenticationType script called getExtraParametersForStep should be overridden to include any new session variable. The underlying Jans-auth server takes care of retrieving it, persisting it etc. def getExtraParametersForStep(self, configurationAttributes, step): return Arrays.asList(\"sessionParamName1\", \"sessionParamName2\", \"sessionParamName3\") Bean details: |Signature|Description| |-|-| | Object getWorkingParameter(String name) |Retrieves a working parameter by name previously set via setWorkingParameter | | void setWorkingParameter(String name, Object value) |Binds data to a name for further use in an authentication flow. Recommended values to store are String s| | SessionId getSessionId() |Retrieves a reference to the associated server session object, see SessionId | Usage from io.jans.as.server.security import Identity identity = CdiUtil.bean(Identity) #1. newExpDate = identity.getWorkingParameter(\"expDate\") #2. identity.setWorkingParameter(\"expDate\", expDate) #3. session_attributes = identity.getSessionId().getSessionAttributes() session_attributes.containsKey(\"remote_ip\") 8. SessionIdService # #1. get session sessionIdservice = CdiUtil.bean(SessionIdService).getSessionId() #2. update session sessionIdservice.getSessionAttributes().put(key, value) sessionIdservice.updateSessionId(session) 9. GrantService # 10. ClientService : Provides operations with clients. # Usage: from io.jans.as.server.service import ClientService clientService = CdiUtil.bean(ClientService) client = clientService.getClient(clientId) 7. HttpService: HttpService # Provides utility methods to execute HTTP requests, manipulate responses, etc Relevant methods: Signature Description HttpClient getHttpsClient() Returns an instance of org.apache.http.client.HttpClient (see oxcore-util class SslDefaultHttpClient ) HttpServiceResponse executeGet(HttpClient httpClient, String requestUri) Perform a GET on the URI requested. Returns an instance of io.jans.as.server.model.net.HttpServiceResponse (a wrapper on org.apache.http.HttpResponse ) byte[] getResponseContent(HttpResponse httpResponse) Consumes the bytes of the associated response. Returns null if the response status code is not 200 (OK) 8. CacheService # Provides a unified means to interact with the underlying cache provider configured in the Jans-auth Server Relevant methods: Signature Description void clear() Flushes the whole cache Object get(String key) Retrieves the value of key in the cache. null if there is no such key present void put(int expirationInSeconds, String key, Object object) Puts an object in the cache associated to the key passed. An expiration in seconds can be provided put(String key, Object object) Puts an object in the cache associated to the key passed. The expiration used is the default expiration configured in Gluu void remove(String key) Removes an entry from the cache 9. FacesService : Provides utilities to properly build encoded URLs and make redirections. This class is used a great deal in custom scripts # Relevant methods: Signature Description void redirectToExternalURL(String url) Redirects the user's browser to the URL passed as parameter String encodeParameters(String url, Map<String, Object> parameters) Builds a URL by appending query parameters as supplied in parameters map. Every value in the map is properly URL-encoded 10. FacesMessages # Allows manipulation of JSF context messages Relevant methods: Signature Description void add(Severity severity, String message) Adds a message to the JSF context with the severity ( javax.faces.application.FacesMessage.Severity ) specified void clear() Clears the messages of the JSF context String evalAsString(String expression) Evaluates an EL expression using the JSF context and returns the result as a String void setKeepMessages() Sets the \"keep messages\" property of the JSF flash 11. StringHelper # Provides many utility methods that often arise in the manipulation of Strings Usage: from io.jans.util import StringHelper isNotEmptyString # if StringHelper.isNotEmptyString(user_name): # do something equalsIgnoreCase # if StringHelper.equalsIgnoreCase(authentication_mode, \"one_step\"): # do something isEmpty # if StringHelper.isEmpty(auth_method): # do something split # allowedClientsListArray = StringHelper.split(allowedClientsList, \",\") toLowerCase # remoteAttribute = StringHelper.toLowerCase(remoteAttributesListArray[i]) base64urlencode # StringUtils.base64urlencode(input); 13. EncryptionService # Allows to encrypt/decrypt strings using a 3DES cipher whose salt is found in /etc/jans/conf/salt Relevant methods: Signature Description String decrypt(String encryptedString) Decrypts the encrypted string supplied Properties decryptAllProperties(Properties connectionProperties) Returns a java.util.Properties object with all decrypted values found in connectionProperties String encrypt(String unencryptedString) Encrypts the string supplied Usage: # from io.jans.as.common.service.common import EncryptionService .... encryptionService = CdiUtil.bean(EncryptionService) pwd_decrypted = encryptionService.decrypt(\"stringtobedecrypted\") 14. Base64Util # Usage: from io.jans.as.model.util import Base64Util .... Base64Util.base64urldecodeToString(input_string) Base64Util.base64urlencode(input_string.encode('utf-8')));", "title": "Managed Beans"}, {"location": "janssen-server/developer/managed-beans/#ready-to-use-code-in-custom-script", "text": "Jans-auth server uses Weld 3.0 (JSR-365 aka CDI 2.0) for managed beans. The most useful functions are implemented through a set of beans which can be re-used in all custom scripts.", "title": "Ready-to-use code in Custom script:"}, {"location": "janssen-server/developer/managed-beans/#obtaining-a-bean-inside-a-custom-script", "text": "CdiUtil used to obtain managed beans inside a custom script. Relevant methods: Signature Description T bean(Class clazz) Gets the managed bean belonging to the class passed as parameter Usage (jython code): Suppose UserService and AuthenticationService beans have to be referenced in the code, it can be done as below: from io.jans.as.server.service import UserService from io.jans.as.server.service import AuthenticationService ... userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService)", "title": "Obtaining a bean inside a custom script:"}, {"location": "janssen-server/developer/managed-beans/#commonly-used-beans", "text": "", "title": "Commonly used beans:"}, {"location": "janssen-server/developer/managed-beans/#1-authenticationservice", "text": "Allows to authenticate a user or obtain the current authenticated user Relevant methods: Signature Description boolean authenticate(String userName) Performs authentication for the user whose identifier ( userName ) is passed as parameter boolean authenticate(String userName, String password) Performs authentication for the user whose identifier ( userName ) is passed as parameter. The password supplied must be the correct password of the user in question User getAuthenticatedUser() Returns a representation of the currently authenticated user. null if no user is currently authenticated. See User data object Usage: from io.jans.as.server.service import AuthenticationService ... #1. authenticate a user using username and password authenticationService = CdiUtil.bean(AuthenticationService) logged_in = authenticationService.authenticate(user_name, user_password) # 2. authenticate method without passing password parameter logged_in = authenticationService.authenticate(user_name) #3. obtain an authenticated user user = authenticationService.getAuthenticatedUser() userName = user.getUserId() emailIds = user.getAttribute(\"oxEmailAlternate\")", "title": "1. AuthenticationService"}, {"location": "janssen-server/developer/managed-beans/#2-userservice", "text": "Allows CRUD operations for users to the local persistence. Relevant methods: Signature Description User addUser(User user, boolean active) Creates a new user based on the representation passed as parameter. active parameter denotes whether user status ( gluuStatus attribute) will be active or register User addUserAttribute(String userId, String attributeName, String attributeValue) Adds an attribute to the user identified by userId in the database with the name and value passed. Returns a representation of the modified user or null in case of failure or if such name/attribute is already part of such user boolean addUserAttribute(User user, String attributeName, String attributeValue) Adds an attribute to the user object with the name and value passed. This method only alters the user argument and does not persist changes. Returns false if such name/attribute is already part of user User addUserAttributeByUserInum(String userInum, String attributeName, String attributeValue) Adds an attribute to the user whose inum attribute (in the database) equals to userInum using the name and value passed. Returns a representation of the modified user or null in case of failure or if such name/attribute is already part of such user CustomAttribute getCustomAttribute(User user, String attributeName) Gets a representation of the attribute whose name is passed for the user in question ( user ). Returns null if no such attribute is populated String getDnForUser(String inum) Obtains the DN (distinguished name) of the user whose inum attribute equals to userInum (no check that such user may exist is actually made) User getUser(String userId, String... returnAttributes) Retrieves a user representation for the user identified with userId containing only the attributes requested ( returnAttributes ). null is returned if no such user exists User getUserByAttribute(String attributeName, String attributeValue) Retrieves a user (first available) such that the attribute referenced ( attributeName ) has the value passed ( attributeValue ). null is returned if no such user exists String getUserInum(String userId) Retrieves the inum database attribute for the user identified with userId . null is returned if no such user exists User removeUserAttribute(String userId, String attributeName, String attributeValue) Removes attributeValue from the values of the attribute whose name is passed ( attributeName ) for the user identified with userId User replaceUserAttribute(String userId, String attributeName, String oldAttributeValue, String newAttributeValue) Updates the user identified with userId by replacing the value of the attribute attributeName with the value passed. null is returned if no such user exists void setCustomAttribute(User user, String attributeName, String attributeValue) Sets the value of the attribute attributeName with the single value attributeValue for the user representation passes as parameter. This method does not persist changes User updateUser(User user) Updates the user represented by user object in the database", "title": "2. UserService"}, {"location": "janssen-server/developer/managed-beans/#usage", "text": "", "title": "Usage"}, {"location": "janssen-server/developer/managed-beans/#a-add-a-user", "text": "from io.jans.as.common.service.common import UserService from io.jans.orm.model.base import CustomObjectAttribute; ... new_user = User() found_user.getCustomAttributes().add(new CustomObjectAttribute(\"address\", Arrays.asList(\"London\", \"Texas\", \"Kiev\"))); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"birthdate\", new Date())); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"scimCustomThird\", 18)); found_user.setUserRole(UserRole.ADMIN); found_user.setMemberOf(Arrays.asList(\"group_1\", \"group_2\", \"group_3\")); CustomObjectAttribute multiValuedSingleValue = new CustomObjectAttribute(\"oxExternalUid\", \"multivalued_single_valued\"); multiValuedSingleValue.setMultiValued(true); foundUser.getCustomAttributes().add(multiValuedSingleValue); new_user = CdiUtil.bean(UserService).addUser(new_user, True)", "title": "a. Add a user"}, {"location": "janssen-server/developer/managed-beans/#b-add-user-attributes", "text": "userObject = userService.addUserAttribute(user_name, \"oxExternalUid\", cert_user_external_uid, true)", "title": "b. Add user attributes"}, {"location": "janssen-server/developer/managed-beans/#c-get-user", "text": "# example 1 - get User by userId user = userService.getUser(user_name) # example 2 - get User by User-Id only if attribute oxExternalUid is populated user = userService.getUser(user_name, \"oxExternalUid\") customAttributeValue = userService.getCustomAttribute(user, \"oxExternalUid\")", "title": "c. Get User"}, {"location": "janssen-server/developer/managed-beans/#d-get-specific-user-attribute", "text": "status_attribute_value = userService.getCustomAttribute(find_user_by_uid, \"gluuStatus\")", "title": "d. Get specific User attribute"}, {"location": "janssen-server/developer/managed-beans/#e-replace-user-attributes", "text": "userService.replaceUserAttribute(user_name, \"oxOTPCache\", cachedOTP, localTotpKey)", "title": "e. Replace user attributes"}, {"location": "janssen-server/developer/managed-beans/#f-remove-user-attribute", "text": "userService.removeUserAttribute(user.getUserId(),\"oxTrustExternalId\", \"wwpass:%s\"%puid)", "title": "f. Remove user attribute"}, {"location": "janssen-server/developer/managed-beans/#g-update-users", "text": "found_user = userService.getUser(user_name) found_user.getCustomAttributes().add(new CustomObjectAttribute(\"address\", Arrays.asList(\"London\", \"Texas\", \"Kiev\"))); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"birthdate\", new Date())); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"jansActive\", false)); found_user.getCustomAttributes().add(new CustomObjectAttribute(\"scimCustomThird\", 18)); found_user.setUserRole(UserRole.ADMIN); found_user.setMemberOf(Arrays.asList(\"group_1\", \"group_2\", \"group_3\")); userService.updateUser(found_user)", "title": "g. Update users"}, {"location": "janssen-server/developer/managed-beans/#4-user", "text": "A class employed to represent a user entry in the persistence. Provides getters and setters to retrieve and assign value(s) for attributes", "title": "4. User"}, {"location": "janssen-server/developer/managed-beans/#5-customattribute", "text": "A class that models an attribute. An attribute has a name and a collection of associated values", "title": "5. CustomAttribute"}, {"location": "janssen-server/developer/managed-beans/#6-identity", "text": "The authentication flow in jans-auth server is stateless and the instance is preserved because the Identity parameters (another name for session parameters) are persisted in databases. A function in the PersonAuthenticationType script called getExtraParametersForStep should be overridden to include any new session variable. The underlying Jans-auth server takes care of retrieving it, persisting it etc. def getExtraParametersForStep(self, configurationAttributes, step): return Arrays.asList(\"sessionParamName1\", \"sessionParamName2\", \"sessionParamName3\") Bean details: |Signature|Description| |-|-| | Object getWorkingParameter(String name) |Retrieves a working parameter by name previously set via setWorkingParameter | | void setWorkingParameter(String name, Object value) |Binds data to a name for further use in an authentication flow. Recommended values to store are String s| | SessionId getSessionId() |Retrieves a reference to the associated server session object, see SessionId | Usage from io.jans.as.server.security import Identity identity = CdiUtil.bean(Identity) #1. newExpDate = identity.getWorkingParameter(\"expDate\") #2. identity.setWorkingParameter(\"expDate\", expDate) #3. session_attributes = identity.getSessionId().getSessionAttributes() session_attributes.containsKey(\"remote_ip\")", "title": "6. Identity"}, {"location": "janssen-server/developer/managed-beans/#8-sessionidservice", "text": "#1. get session sessionIdservice = CdiUtil.bean(SessionIdService).getSessionId() #2. update session sessionIdservice.getSessionAttributes().put(key, value) sessionIdservice.updateSessionId(session)", "title": "8. SessionIdService"}, {"location": "janssen-server/developer/managed-beans/#9-grantservice", "text": "", "title": "9. GrantService"}, {"location": "janssen-server/developer/managed-beans/#10-clientservice-provides-operations-with-clients", "text": "Usage: from io.jans.as.server.service import ClientService clientService = CdiUtil.bean(ClientService) client = clientService.getClient(clientId)", "title": "10. ClientService : Provides operations with clients."}, {"location": "janssen-server/developer/managed-beans/#7-httpservice-httpservice", "text": "Provides utility methods to execute HTTP requests, manipulate responses, etc Relevant methods: Signature Description HttpClient getHttpsClient() Returns an instance of org.apache.http.client.HttpClient (see oxcore-util class SslDefaultHttpClient ) HttpServiceResponse executeGet(HttpClient httpClient, String requestUri) Perform a GET on the URI requested. Returns an instance of io.jans.as.server.model.net.HttpServiceResponse (a wrapper on org.apache.http.HttpResponse ) byte[] getResponseContent(HttpResponse httpResponse) Consumes the bytes of the associated response. Returns null if the response status code is not 200 (OK)", "title": "7. HttpService: HttpService"}, {"location": "janssen-server/developer/managed-beans/#8-cacheservice", "text": "Provides a unified means to interact with the underlying cache provider configured in the Jans-auth Server Relevant methods: Signature Description void clear() Flushes the whole cache Object get(String key) Retrieves the value of key in the cache. null if there is no such key present void put(int expirationInSeconds, String key, Object object) Puts an object in the cache associated to the key passed. An expiration in seconds can be provided put(String key, Object object) Puts an object in the cache associated to the key passed. The expiration used is the default expiration configured in Gluu void remove(String key) Removes an entry from the cache", "title": "8. CacheService"}, {"location": "janssen-server/developer/managed-beans/#9-facesservice-provides-utilities-to-properly-build-encoded-urls-and-make-redirections-this-class-is-used-a-great-deal-in-custom-scripts", "text": "Relevant methods: Signature Description void redirectToExternalURL(String url) Redirects the user's browser to the URL passed as parameter String encodeParameters(String url, Map<String, Object> parameters) Builds a URL by appending query parameters as supplied in parameters map. Every value in the map is properly URL-encoded", "title": "9. FacesService : Provides utilities to properly build encoded URLs and make redirections. This class is used a great deal in custom scripts"}, {"location": "janssen-server/developer/managed-beans/#10-facesmessages", "text": "Allows manipulation of JSF context messages Relevant methods: Signature Description void add(Severity severity, String message) Adds a message to the JSF context with the severity ( javax.faces.application.FacesMessage.Severity ) specified void clear() Clears the messages of the JSF context String evalAsString(String expression) Evaluates an EL expression using the JSF context and returns the result as a String void setKeepMessages() Sets the \"keep messages\" property of the JSF flash", "title": "10. FacesMessages"}, {"location": "janssen-server/developer/managed-beans/#11-stringhelper", "text": "Provides many utility methods that often arise in the manipulation of Strings Usage: from io.jans.util import StringHelper", "title": "11. StringHelper"}, {"location": "janssen-server/developer/managed-beans/#isnotemptystring", "text": "if StringHelper.isNotEmptyString(user_name): # do something", "title": "isNotEmptyString"}, {"location": "janssen-server/developer/managed-beans/#equalsignorecase", "text": "if StringHelper.equalsIgnoreCase(authentication_mode, \"one_step\"): # do something", "title": "equalsIgnoreCase"}, {"location": "janssen-server/developer/managed-beans/#isempty", "text": "if StringHelper.isEmpty(auth_method): # do something", "title": "isEmpty"}, {"location": "janssen-server/developer/managed-beans/#split", "text": "allowedClientsListArray = StringHelper.split(allowedClientsList, \",\")", "title": "split"}, {"location": "janssen-server/developer/managed-beans/#tolowercase", "text": "remoteAttribute = StringHelper.toLowerCase(remoteAttributesListArray[i])", "title": "toLowerCase"}, {"location": "janssen-server/developer/managed-beans/#base64urlencode", "text": "StringUtils.base64urlencode(input);", "title": "base64urlencode"}, {"location": "janssen-server/developer/managed-beans/#13-encryptionservice", "text": "Allows to encrypt/decrypt strings using a 3DES cipher whose salt is found in /etc/jans/conf/salt Relevant methods: Signature Description String decrypt(String encryptedString) Decrypts the encrypted string supplied Properties decryptAllProperties(Properties connectionProperties) Returns a java.util.Properties object with all decrypted values found in connectionProperties String encrypt(String unencryptedString) Encrypts the string supplied", "title": "13. EncryptionService"}, {"location": "janssen-server/developer/managed-beans/#usage_1", "text": "from io.jans.as.common.service.common import EncryptionService .... encryptionService = CdiUtil.bean(EncryptionService) pwd_decrypted = encryptionService.decrypt(\"stringtobedecrypted\")", "title": "Usage:"}, {"location": "janssen-server/developer/managed-beans/#14-base64util", "text": "Usage: from io.jans.as.model.util import Base64Util .... Base64Util.base64urldecodeToString(input_string) Base64Util.base64urlencode(input_string.encode('utf-8')));", "title": "14. Base64Util"}, {"location": "janssen-server/developer/xframe/", "tags": ["administration", "installation"], "text": "X-Frame-Options Header # Overview # AS has io.jans.as.server.filter.HeadersFilter which is responsible for attaching headers to server responses. <filter-mapping> <filter-name>HeadersFilter</filter-name> <url-pattern /> </filter-mapping> Configure X-Frame-Options Header # The X-Frame-Options HTTP response header can be used to indicate whether a browser should be allowed to render a page in a , , or . Sites can use this to avoid click-jacking attacks, by ensuring that their content is not embedded into other sites. There are two AS configuration properties related to X-Frame-Options : xframeOptionsHeaderValue - sets value of X-Frame-Options header. Default value is SAMEORIGIN . Possible values are: SAMEORIGIN or DENY . applyXFrameOptionsHeaderIfUriContainsAny - array of strings. If incoming request contains any string from this array it will attach X-Frame-Options header to response. By default AS attaches X-Frame-Options header to all responses where request uri contains .htm . It means for all AS pages.", "title": "X-Frame-Options"}, {"location": "janssen-server/developer/xframe/#x-frame-options-header", "text": "", "title": "X-Frame-Options Header"}, {"location": "janssen-server/developer/xframe/#overview", "text": "AS has io.jans.as.server.filter.HeadersFilter which is responsible for attaching headers to server responses. <filter-mapping> <filter-name>HeadersFilter</filter-name> <url-pattern /> </filter-mapping>", "title": "Overview"}, {"location": "janssen-server/developer/xframe/#configure-x-frame-options-header", "text": "The X-Frame-Options HTTP response header can be used to indicate whether a browser should be allowed to render a page in a , , or . Sites can use this to avoid click-jacking attacks, by ensuring that their content is not embedded into other sites. There are two AS configuration properties related to X-Frame-Options : xframeOptionsHeaderValue - sets value of X-Frame-Options header. Default value is SAMEORIGIN . Possible values are: SAMEORIGIN or DENY . applyXFrameOptionsHeaderIfUriContainsAny - array of strings. If incoming request contains any string from this array it will attach X-Frame-Options header to response. By default AS attaches X-Frame-Options header to all responses where request uri contains .htm . It means for all AS pages.", "title": "Configure X-Frame-Options Header"}, {"location": "janssen-server/developer/agama/advanced-usages/", "tags": ["developer", "agama"], "text": "Advanced usages # UI templates # Template overrides # Template overrides is a mechanism that allows templates customization and promotes flows reuse. If an existing flow serves well the needs of a new flow you are writing, with this feature you can homogenize your UI for a more pleasant user experience. To start, use Trigger to play around with the existing flow - as is - from the flow you are creating. Collect the URLs of the pages you are not comfortable with: grab them directly from the browser's address bar. Then proceed as follows with every URL to locate the actual templates physically: Remove the https://.../fl/ portion of the URL Split the URL obtained into two pieces: a folder name and a remainder . The remainder starts after the last slash found in the URL, and usually ends in .fls In your Janssen server, locate the directory /opt/jans/jetty/jans-auth/agama/ftl cd to the directory specified by the folder List the contents of the directory and pick the filename that best matches the remainder Save a copy of every selected file in the directory associated to your flow ( basePath directive) or in a subdirectory of it. Rename the files if desired too. Now, build the Override templates directive passing several pairs of strings separated by lines or spaces. Every pair consists of a string specifying the original template location, that is, <folder>/<filename> followed by the path to the new template version relative to the base path of your flow. Output encoding # By default, the engine sends rendered pages using UTF-8 character encoding. To specify a different encoding the ftl directive can be used in pages, for instance, <#ftl encoding=\"ISO-8859-5\"> . Always place this at the top of a template. Localization and internationalization # To allow templates render text according to users' language or country, you can add a file named labels.txt to the web directory of a project. There you can place the so-called \"internationalization labels\" (common UI-related messages) as per your needs. The file is expected to have a structure as follows: key = value ... more key/value pairs [ locale ID 1 ] key/value pairs for this locale [ locale ID 2 ] key/value pairs for this locale ... [ locale ID n ] key/value pairs for this locale Note how the file is split into sections for every locale to support. The first section (no locale) will contain the \"default\" labels - more on this later. One locale conveys mostly the same concept of a Java locale (class java.util.Locale ). In this case, a locale represents a language, country/region, and variant combination. Examples of locale IDs are: de_CH : German as used in Switzerland ca_ES_VALENCIA : Catalan as used in Spain (province of Valencia) th_TH_TH : Thai as used in Thailand together with Thai digits ja : Japanese (in general) There may be several sections regarding the same language, like de_CH , de_DE , de_LU , and plain de . Agama engine will pick the text from the section that best maches the settings of the end-user browser (normally, this is supplied through the Accept-Language HTTP header). As an example, if the browser's preferred language is German from Luxembourg, the lookup is made in de_LU section. If no text is found there, the de section is tried. The opening \"no locale\" section is used as a last resort - that's why it is said to contain the \"default\" labels. To reference a label from a template an expression like ${labels(\"<KEY>\")} can be used. This will retrieve the proper text using the rules just described. When the lookup fails thoroughly (no way to found a label matching the key), the four character string null is returned. This helps to easily locate template issues if any. A value (message) associated to a key can contain placeholders where data can be injected. Suppose the following key/value pair: disk.count = The disk {1} contains {0} file(s) Using ${labels(\"disk.count\")} will just retrieve the message as is, however, positional arguments can be passed. As an example, ${labels(\"disk.count\", 7, \"SSD-NVME-123\")} will generate The disk SSD-NVME-123 contains 7 file(s) . Note parameters are not restricted to literals (fixed values) like 0 , false , or \"world\" . Variables can also be used. It is recommended to employ literals/variables whose data types are string, number, date, or boolean only. Labels are global: not only can they be accessed from the project where they are originally defined but from any other project. This allows template overrides to work smoothly, however, it brings the possibility of key collisions, that is, two or more projects defining labels with the same keys. To mitigate this problem, it is recommended to prefix all keys with the name/identifier of the originating project, like: myproject.salutation = hello! [es] myproject.salutation = hola! [it] myproject.salutation = ciao! When leaving salutation alone, it is likely other projects added to the server in the future may contain their own version of salutation leading to unexpected results. Additional notes: Language codes should follow the ISO 639 alpha-2 standard Country/region codes should be driven by ISO 3166 alpha-2 or UN M.49 numeric-3 area code Except for the locale section headings, the syntax of labels.txt adheres to that of Java properties files. This is a human-friendly, low-surpise format: a label key starts a line and its value comes after an equal sign or a colon. For readability one or more empty lines can be used between contiguous key/value pairs. Any line starting with ! or # is ignored and thus can be used as a comment or note When positional arguments are passed, Java class java.text.MessageFormat is internally employed. This allows powerful formatting and proper handling of plurals. If for some reason, formatting fails, the resulting string will be error! . Check the server logs and try to simplify your message in this case Access to AS labels # The jans-auth server comes with a series of files known as \"resource bundles\" that follow the naming jans-auth_xx.properties where xx represents an ISO 639 language code. Bundles can be added or overridden by placing suitable properties files in directory /opt/jans/jetty/jans-auth/custom/i18n . Strings stored in these bundles can be accessed from templates using expressions like ${msgs.<KEY>} . As most keys in resource bundles contain dot characters, the alternative notation ${msgs[\"KEY\"]} works better for FreeMarker, for example ${msgs[\"login.errorMessage\"]} . Whenever possible, it is recommended to place your internationalization labels in the web folder of the project and use the ${labels(... notation instead. Note msgs has no support for parameterized placeholders: strings are all static. Reusable templates # A widespread practice in web page authoring is to compose pages based on reusable pieces. As an example, the need for a common header and footer is ubiquitous in HTML projects. With FreeMarker, composition can be achieved by means of macros . These are the equivalent to functions in programming, they can generate output based on parameters passed and can be called anywhere in a template. Agama already makes use of macros for this purpose. Take a look at the ftlh files found at /opt/jans/jetty/jans-auth/agama . These templates are used to present errors, like timeouts, flow crashes, etc. Example: Here, two pages will be built to demonstrate the concept of composition in FreeMarker templates: a homepage and an \"about us\" page. These will be made up of a header, a sidebar, and their respective main content. Assume the sidebar should be shown only for the home page. Note FreeMarker comments are of the form <#-- This won't be printed in the output --> One way to structure the solution is the following: <#-- aside.ftlh --> <#macro sidebar> <aside> <h2>Recommended tracks</h2> <nav> <ul> <li><a href=\"#\">Efilnikufesin</a></li> <li><a href=\"#\">P.O.N.X.</a></li> <!--li><a href=\"#\">Planet caravan</a></li--> </ul> </nav> </aside> </#macro> aside.ftlh has static markup for a sidebar. It is defined inside a macro called sidebar . <#-- commons.ftlh --> <#import \"aside.ftlh\" as sbar> <#macro header> <header> <h1>Welcome</h1> <nav> <ul> <li><a href=\"#\">Home</a></li> <li><a href=\"#\">About</a></li> <li><a href=\"#\">Sign Up</a></li> </ul> </nav> </header> </#macro> <#macro main useSidebar=false> <!DOCTYPE html> <html> <body> <@header/> <#if useSidebar> <@sbar.sidebar/> </#if> <#nested> </body> </html> </#macro> commons.ftlh template imports aside.ftlh associating it with the shortname sbar . Additionally: It defines two macros: header and main . The macro header generates a static navigation menu main macro is the skeleton of a very simple HTML page main has a parameter named useSidebar whose default is false The sidebar macro is called using <@sbar.sidebar/> while header with <@header/> (local macro) <#-- index.ftlh --> <#import \"commons.ftlh\" as com> <@com.main useSidebar=true> <article> <h1>This is the index page!</h1> <p>Temporibus ut nisi quibusdam iusto vitae similique laudantium. Minima cumque ducimus sit ut dolores. Autem quam soluta illo et omnis expedita voluptas magnam. Sit aperiam laboriosam magnam et amet deleniti. Sit et velit unde quibusdam esse ullam voluptatem. Enim sint blanditiis dolores. Laborum velit eos dolor ad quaerat. Quo tempora excepturi enim dolor harum sunt ipsa. Quis sit dolorem harum ipsa fuga voluptatem commodi. </p> </article> </@com.main> index.ftlh is the homepage: Template commons.ftlh is imported and its macro main called passing true for useSidebar The markup inside <@com.main... tag is the content to be \"inserted\" when the <#nested> directive is reached <#-- about.ftlh --> <#import \"commons.ftlh\" as com> <@com.main> <article> <h1>About us</h1> <p>We don't know ourselves very well.</p> </article> </@com.main> about.ftlh is the \"about us\" page. It works like the homepage except the sidebar will not be shown. Cancellation # Important Ensure you have previously gone through the contents of this page before proceeding This is a feature that in conjuction with template overrides allows developers to implement alternative routing and backtracking. Suppose a flow is designed to reuse two or more existing subflows. As expected these subflows are neither aware of each other nor of its parent. How can the parent make so that once the user has landed at a page belonging to a given subflow A be presented the alternative to take another route, say, to subflow B? Clearly a page at flow A can be overriden, however, how to abort A and make it jump to B? The answer is cancellation. Through flow cancellation, a running flow can be aborted and the control returned to one of its parents for further processing. This can achieved by overriding a template so that the POST to the current URL includes a form field named _abort . POSTing this way will provoke the associated Trigger call to return a value like { aborted: true, data: ..., url: ... } where data is a map consisting of the payload (form fields) sent with the POST. Thus, developers can build custom pages and add for example a button to provoke the cancellation. Then, back in the flow implementation take the user to the desired path. The url property will hold the URL where cancellation took place relative to https://your-server/jans-auth/fl/ . As an example, suppose there exists two flows that allow users to enter and validate a one-time passcode (OTP), one flow sends the OTP via e-mail while the other through an SMS. Assume these flows receive a user identifier as input and render a single UI page each to enter the received OTP. If we are interested in building a flow that prompts for username/password credentials and use the SMS-based OTP flow with a customization that consists of showing a link like \"Didn't get an SMS?, send the passcode to my e-mail\", the following is a sketch of an implementation: ... //validate username/password ... result = Trigger co.acme.SmsOTP userId Override templates \"path/to/enter_otp.ftlh\" \"cust_enter_otp.ftlh\" When result.aborted is true //The user clicked on \"send the passcode to my e-mail\" result = Trigger co.acme.EmailOTP userId When result.success is true result.data = { userId: userId } Finish result The overriden template cust_enter_otp.ftlh would have a form like: ... <form method=\"post\" enctype=\"application/x-www-form-urlencoded\"> <button type=\"submit\" name=\"_abort\"> Didn't get an SMS?, send the passcode to my e-mail</button> </form> Note you cannot make cancellation occur at an arbitrary point of a flow. It can only happen when a page has been rendered, that is, an RRF directive is in execution. When a flow is aborted and the control returned back to a parent, there is no way to \"resume\" execution of the flow target of the cancellation. Cancellation bubble-up # In order to override a page, the path to the corresponding template can be easily derived from the URL seen at the browser's address bar when the subflow is Trigger ed. Note the page may not necessarily belong directly to the subflow triggered but probably to another flow lying deep in a chain of Trigger invocations. As an example suppose you are interested in building a flow A that reuses flow B. You identify a page shown that needs to be overriden. It might happen this page is actually rendered by C - a flow that B in turn reuses. In scenarios like this cancellation still works transparently and developers need not be aware of flows dependencies. In practice, when cancellation occurs at C, it bubbles up to B and then to A, which is the target of this process. Note that even flow B (as is) may also be overriding C's templates. Resolution of a template path takes place from the inner to the outer flow, so it occurs this way in the example: path is as found in C's RRF instruction path is looked up on the list provided in B's Override templates . If a match is found, path is updated accordingly path is looked up on the list provided in A's Override templates . If a match is found, path is updated accordingly The page referenced by path is rendered Engine internals # Here we provide insight on some behavioral aspects of the engine that may result of interest to developers. Flow advance and navigation # Once a web page (or a response in general) is replied to a client (e.g. web browser), a POST is required to make the flow proceed . The POST is expected to be sent to the current URL only, otherwise, a 404 error will be thrown. The engine will then respond with a redirect (usually 301) so the client will GET the next URL to be rendered. This pattern of navigation is known as \"POST-REDIRECT-GET\". There is a clear correspondence of the \"current URL\" with the physical path of the template rendered. As an example, if the browser location shows https://<your-host>/jans-auth/fl/foo/bar.fls , the involved template is stored at /opt/jans/jetty/jans-auth/agama/ftl/foo and has name bar . This makes flows more predictable and easier to reason about. Note however URLs are not manipulable: an attempt to set the browser location to a URL corresponding to a different template will not make that template be rendered or provoke any unexpected jump in the flow control. Instead, an error page is shown that allows users to re-take where they left off or to restart from scratch. In other words, navigation honors the \"current flow URL\" avoiding attempts to re-visit past stages or make unexpected moves to future ones. Additionally, the engine by default sends responses with proper HTTP headers so page contents are not cached. This is key to prevent manipulation and allows a safe usage of the browser's back button, where it will not be possible to visit past stages. Code transpilation # The engine has some timers running in the background. One of them transpiles code when a change is detected in a given flow's source (written in Agama language). The transpilation process generates vanilla Javascript code runnable through Mozilla Rhino by using a transformation chain like (DSL) flow code -> (ANTLR4) parse tree -> (XML) abstract syntax tree -> JS. The transformation chain guarantees that a flow written in Agama DSL cannot: Access Java classes/instances not specified in the original flow code (i.e. the only bridge to Java world is via Call s) Access/modify the standard javascript built-in objects directly Conflict with javascript keywords Notes You can find the (ANTLR4) DSL grammar here . The last step of the transformation chain is carried out by means of this Freemarker transformer Other engine characteristics # Some interesting facts for the curious: The engine does not use asynchronous paradigms: no events, callbacks, extra threads, etc. All computations remain in the classic request/response servlet lifecycle familiar to most Java developers Continuations allow to express a flow as if it were a straight sequence of commands despite there are actual pauses in the middle: the gaps between an HTTP response and the next request Currently Mozilla Rhino seems to be the only mechanism that brings continuations into the Java language In order to preserve server statelessness, continuations are persisted to storage at every flow pause. This way the proper state can be restored when the continuation is resumed in the upcoming HTTP request", "title": "Advanced usages"}, {"location": "janssen-server/developer/agama/advanced-usages/#advanced-usages", "text": "", "title": "Advanced usages"}, {"location": "janssen-server/developer/agama/advanced-usages/#ui-templates", "text": "", "title": "UI templates"}, {"location": "janssen-server/developer/agama/advanced-usages/#template-overrides", "text": "Template overrides is a mechanism that allows templates customization and promotes flows reuse. If an existing flow serves well the needs of a new flow you are writing, with this feature you can homogenize your UI for a more pleasant user experience. To start, use Trigger to play around with the existing flow - as is - from the flow you are creating. Collect the URLs of the pages you are not comfortable with: grab them directly from the browser's address bar. Then proceed as follows with every URL to locate the actual templates physically: Remove the https://.../fl/ portion of the URL Split the URL obtained into two pieces: a folder name and a remainder . The remainder starts after the last slash found in the URL, and usually ends in .fls In your Janssen server, locate the directory /opt/jans/jetty/jans-auth/agama/ftl cd to the directory specified by the folder List the contents of the directory and pick the filename that best matches the remainder Save a copy of every selected file in the directory associated to your flow ( basePath directive) or in a subdirectory of it. Rename the files if desired too. Now, build the Override templates directive passing several pairs of strings separated by lines or spaces. Every pair consists of a string specifying the original template location, that is, <folder>/<filename> followed by the path to the new template version relative to the base path of your flow.", "title": "Template overrides"}, {"location": "janssen-server/developer/agama/advanced-usages/#output-encoding", "text": "By default, the engine sends rendered pages using UTF-8 character encoding. To specify a different encoding the ftl directive can be used in pages, for instance, <#ftl encoding=\"ISO-8859-5\"> . Always place this at the top of a template.", "title": "Output encoding"}, {"location": "janssen-server/developer/agama/advanced-usages/#localization-and-internationalization", "text": "To allow templates render text according to users' language or country, you can add a file named labels.txt to the web directory of a project. There you can place the so-called \"internationalization labels\" (common UI-related messages) as per your needs. The file is expected to have a structure as follows: key = value ... more key/value pairs [ locale ID 1 ] key/value pairs for this locale [ locale ID 2 ] key/value pairs for this locale ... [ locale ID n ] key/value pairs for this locale Note how the file is split into sections for every locale to support. The first section (no locale) will contain the \"default\" labels - more on this later. One locale conveys mostly the same concept of a Java locale (class java.util.Locale ). In this case, a locale represents a language, country/region, and variant combination. Examples of locale IDs are: de_CH : German as used in Switzerland ca_ES_VALENCIA : Catalan as used in Spain (province of Valencia) th_TH_TH : Thai as used in Thailand together with Thai digits ja : Japanese (in general) There may be several sections regarding the same language, like de_CH , de_DE , de_LU , and plain de . Agama engine will pick the text from the section that best maches the settings of the end-user browser (normally, this is supplied through the Accept-Language HTTP header). As an example, if the browser's preferred language is German from Luxembourg, the lookup is made in de_LU section. If no text is found there, the de section is tried. The opening \"no locale\" section is used as a last resort - that's why it is said to contain the \"default\" labels. To reference a label from a template an expression like ${labels(\"<KEY>\")} can be used. This will retrieve the proper text using the rules just described. When the lookup fails thoroughly (no way to found a label matching the key), the four character string null is returned. This helps to easily locate template issues if any. A value (message) associated to a key can contain placeholders where data can be injected. Suppose the following key/value pair: disk.count = The disk {1} contains {0} file(s) Using ${labels(\"disk.count\")} will just retrieve the message as is, however, positional arguments can be passed. As an example, ${labels(\"disk.count\", 7, \"SSD-NVME-123\")} will generate The disk SSD-NVME-123 contains 7 file(s) . Note parameters are not restricted to literals (fixed values) like 0 , false , or \"world\" . Variables can also be used. It is recommended to employ literals/variables whose data types are string, number, date, or boolean only. Labels are global: not only can they be accessed from the project where they are originally defined but from any other project. This allows template overrides to work smoothly, however, it brings the possibility of key collisions, that is, two or more projects defining labels with the same keys. To mitigate this problem, it is recommended to prefix all keys with the name/identifier of the originating project, like: myproject.salutation = hello! [es] myproject.salutation = hola! [it] myproject.salutation = ciao! When leaving salutation alone, it is likely other projects added to the server in the future may contain their own version of salutation leading to unexpected results. Additional notes: Language codes should follow the ISO 639 alpha-2 standard Country/region codes should be driven by ISO 3166 alpha-2 or UN M.49 numeric-3 area code Except for the locale section headings, the syntax of labels.txt adheres to that of Java properties files. This is a human-friendly, low-surpise format: a label key starts a line and its value comes after an equal sign or a colon. For readability one or more empty lines can be used between contiguous key/value pairs. Any line starting with ! or # is ignored and thus can be used as a comment or note When positional arguments are passed, Java class java.text.MessageFormat is internally employed. This allows powerful formatting and proper handling of plurals. If for some reason, formatting fails, the resulting string will be error! . Check the server logs and try to simplify your message in this case", "title": "Localization and internationalization"}, {"location": "janssen-server/developer/agama/advanced-usages/#access-to-as-labels", "text": "The jans-auth server comes with a series of files known as \"resource bundles\" that follow the naming jans-auth_xx.properties where xx represents an ISO 639 language code. Bundles can be added or overridden by placing suitable properties files in directory /opt/jans/jetty/jans-auth/custom/i18n . Strings stored in these bundles can be accessed from templates using expressions like ${msgs.<KEY>} . As most keys in resource bundles contain dot characters, the alternative notation ${msgs[\"KEY\"]} works better for FreeMarker, for example ${msgs[\"login.errorMessage\"]} . Whenever possible, it is recommended to place your internationalization labels in the web folder of the project and use the ${labels(... notation instead. Note msgs has no support for parameterized placeholders: strings are all static.", "title": "Access to AS labels"}, {"location": "janssen-server/developer/agama/advanced-usages/#reusable-templates", "text": "A widespread practice in web page authoring is to compose pages based on reusable pieces. As an example, the need for a common header and footer is ubiquitous in HTML projects. With FreeMarker, composition can be achieved by means of macros . These are the equivalent to functions in programming, they can generate output based on parameters passed and can be called anywhere in a template. Agama already makes use of macros for this purpose. Take a look at the ftlh files found at /opt/jans/jetty/jans-auth/agama . These templates are used to present errors, like timeouts, flow crashes, etc. Example: Here, two pages will be built to demonstrate the concept of composition in FreeMarker templates: a homepage and an \"about us\" page. These will be made up of a header, a sidebar, and their respective main content. Assume the sidebar should be shown only for the home page. Note FreeMarker comments are of the form <#-- This won't be printed in the output --> One way to structure the solution is the following: <#-- aside.ftlh --> <#macro sidebar> <aside> <h2>Recommended tracks</h2> <nav> <ul> <li><a href=\"#\">Efilnikufesin</a></li> <li><a href=\"#\">P.O.N.X.</a></li> <!--li><a href=\"#\">Planet caravan</a></li--> </ul> </nav> </aside> </#macro> aside.ftlh has static markup for a sidebar. It is defined inside a macro called sidebar . <#-- commons.ftlh --> <#import \"aside.ftlh\" as sbar> <#macro header> <header> <h1>Welcome</h1> <nav> <ul> <li><a href=\"#\">Home</a></li> <li><a href=\"#\">About</a></li> <li><a href=\"#\">Sign Up</a></li> </ul> </nav> </header> </#macro> <#macro main useSidebar=false> <!DOCTYPE html> <html> <body> <@header/> <#if useSidebar> <@sbar.sidebar/> </#if> <#nested> </body> </html> </#macro> commons.ftlh template imports aside.ftlh associating it with the shortname sbar . Additionally: It defines two macros: header and main . The macro header generates a static navigation menu main macro is the skeleton of a very simple HTML page main has a parameter named useSidebar whose default is false The sidebar macro is called using <@sbar.sidebar/> while header with <@header/> (local macro) <#-- index.ftlh --> <#import \"commons.ftlh\" as com> <@com.main useSidebar=true> <article> <h1>This is the index page!</h1> <p>Temporibus ut nisi quibusdam iusto vitae similique laudantium. Minima cumque ducimus sit ut dolores. Autem quam soluta illo et omnis expedita voluptas magnam. Sit aperiam laboriosam magnam et amet deleniti. Sit et velit unde quibusdam esse ullam voluptatem. Enim sint blanditiis dolores. Laborum velit eos dolor ad quaerat. Quo tempora excepturi enim dolor harum sunt ipsa. Quis sit dolorem harum ipsa fuga voluptatem commodi. </p> </article> </@com.main> index.ftlh is the homepage: Template commons.ftlh is imported and its macro main called passing true for useSidebar The markup inside <@com.main... tag is the content to be \"inserted\" when the <#nested> directive is reached <#-- about.ftlh --> <#import \"commons.ftlh\" as com> <@com.main> <article> <h1>About us</h1> <p>We don't know ourselves very well.</p> </article> </@com.main> about.ftlh is the \"about us\" page. It works like the homepage except the sidebar will not be shown.", "title": "Reusable templates"}, {"location": "janssen-server/developer/agama/advanced-usages/#cancellation", "text": "Important Ensure you have previously gone through the contents of this page before proceeding This is a feature that in conjuction with template overrides allows developers to implement alternative routing and backtracking. Suppose a flow is designed to reuse two or more existing subflows. As expected these subflows are neither aware of each other nor of its parent. How can the parent make so that once the user has landed at a page belonging to a given subflow A be presented the alternative to take another route, say, to subflow B? Clearly a page at flow A can be overriden, however, how to abort A and make it jump to B? The answer is cancellation. Through flow cancellation, a running flow can be aborted and the control returned to one of its parents for further processing. This can achieved by overriding a template so that the POST to the current URL includes a form field named _abort . POSTing this way will provoke the associated Trigger call to return a value like { aborted: true, data: ..., url: ... } where data is a map consisting of the payload (form fields) sent with the POST. Thus, developers can build custom pages and add for example a button to provoke the cancellation. Then, back in the flow implementation take the user to the desired path. The url property will hold the URL where cancellation took place relative to https://your-server/jans-auth/fl/ . As an example, suppose there exists two flows that allow users to enter and validate a one-time passcode (OTP), one flow sends the OTP via e-mail while the other through an SMS. Assume these flows receive a user identifier as input and render a single UI page each to enter the received OTP. If we are interested in building a flow that prompts for username/password credentials and use the SMS-based OTP flow with a customization that consists of showing a link like \"Didn't get an SMS?, send the passcode to my e-mail\", the following is a sketch of an implementation: ... //validate username/password ... result = Trigger co.acme.SmsOTP userId Override templates \"path/to/enter_otp.ftlh\" \"cust_enter_otp.ftlh\" When result.aborted is true //The user clicked on \"send the passcode to my e-mail\" result = Trigger co.acme.EmailOTP userId When result.success is true result.data = { userId: userId } Finish result The overriden template cust_enter_otp.ftlh would have a form like: ... <form method=\"post\" enctype=\"application/x-www-form-urlencoded\"> <button type=\"submit\" name=\"_abort\"> Didn't get an SMS?, send the passcode to my e-mail</button> </form> Note you cannot make cancellation occur at an arbitrary point of a flow. It can only happen when a page has been rendered, that is, an RRF directive is in execution. When a flow is aborted and the control returned back to a parent, there is no way to \"resume\" execution of the flow target of the cancellation.", "title": "Cancellation"}, {"location": "janssen-server/developer/agama/advanced-usages/#cancellation-bubble-up", "text": "In order to override a page, the path to the corresponding template can be easily derived from the URL seen at the browser's address bar when the subflow is Trigger ed. Note the page may not necessarily belong directly to the subflow triggered but probably to another flow lying deep in a chain of Trigger invocations. As an example suppose you are interested in building a flow A that reuses flow B. You identify a page shown that needs to be overriden. It might happen this page is actually rendered by C - a flow that B in turn reuses. In scenarios like this cancellation still works transparently and developers need not be aware of flows dependencies. In practice, when cancellation occurs at C, it bubbles up to B and then to A, which is the target of this process. Note that even flow B (as is) may also be overriding C's templates. Resolution of a template path takes place from the inner to the outer flow, so it occurs this way in the example: path is as found in C's RRF instruction path is looked up on the list provided in B's Override templates . If a match is found, path is updated accordingly path is looked up on the list provided in A's Override templates . If a match is found, path is updated accordingly The page referenced by path is rendered", "title": "Cancellation bubble-up"}, {"location": "janssen-server/developer/agama/advanced-usages/#engine-internals", "text": "Here we provide insight on some behavioral aspects of the engine that may result of interest to developers.", "title": "Engine internals"}, {"location": "janssen-server/developer/agama/advanced-usages/#flow-advance-and-navigation", "text": "Once a web page (or a response in general) is replied to a client (e.g. web browser), a POST is required to make the flow proceed . The POST is expected to be sent to the current URL only, otherwise, a 404 error will be thrown. The engine will then respond with a redirect (usually 301) so the client will GET the next URL to be rendered. This pattern of navigation is known as \"POST-REDIRECT-GET\". There is a clear correspondence of the \"current URL\" with the physical path of the template rendered. As an example, if the browser location shows https://<your-host>/jans-auth/fl/foo/bar.fls , the involved template is stored at /opt/jans/jetty/jans-auth/agama/ftl/foo and has name bar . This makes flows more predictable and easier to reason about. Note however URLs are not manipulable: an attempt to set the browser location to a URL corresponding to a different template will not make that template be rendered or provoke any unexpected jump in the flow control. Instead, an error page is shown that allows users to re-take where they left off or to restart from scratch. In other words, navigation honors the \"current flow URL\" avoiding attempts to re-visit past stages or make unexpected moves to future ones. Additionally, the engine by default sends responses with proper HTTP headers so page contents are not cached. This is key to prevent manipulation and allows a safe usage of the browser's back button, where it will not be possible to visit past stages.", "title": "Flow advance and navigation"}, {"location": "janssen-server/developer/agama/advanced-usages/#code-transpilation", "text": "The engine has some timers running in the background. One of them transpiles code when a change is detected in a given flow's source (written in Agama language). The transpilation process generates vanilla Javascript code runnable through Mozilla Rhino by using a transformation chain like (DSL) flow code -> (ANTLR4) parse tree -> (XML) abstract syntax tree -> JS. The transformation chain guarantees that a flow written in Agama DSL cannot: Access Java classes/instances not specified in the original flow code (i.e. the only bridge to Java world is via Call s) Access/modify the standard javascript built-in objects directly Conflict with javascript keywords Notes You can find the (ANTLR4) DSL grammar here . The last step of the transformation chain is carried out by means of this Freemarker transformer", "title": "Code transpilation"}, {"location": "janssen-server/developer/agama/advanced-usages/#other-engine-characteristics", "text": "Some interesting facts for the curious: The engine does not use asynchronous paradigms: no events, callbacks, extra threads, etc. All computations remain in the classic request/response servlet lifecycle familiar to most Java developers Continuations allow to express a flow as if it were a straight sequence of commands despite there are actual pauses in the middle: the gaps between an HTTP response and the next request Currently Mozilla Rhino seems to be the only mechanism that brings continuations into the Java language In order to preserve server statelessness, continuations are persisted to storage at every flow pause. This way the proper state can be restored when the continuation is resumed in the upcoming HTTP request", "title": "Other engine characteristics"}, {"location": "janssen-server/developer/agama/agama-best-practices/", "tags": ["administration", "developer", "agama"], "text": "Recommended practices in Agama development # Project reuse and customizations # Agama was designed with reusability in mind. If a project provides functionalities of your interest but you find it does not quite achieve what you want, do not try to modify the project. Instead, create a new separate project reusing the flows and code found in the original project. It might be tempting to just take an Agama project archive, apply some editions, add files to it, repack, and redeploy it. This practice is not recommended. Think of a project as a library used to develop software. In normal situations you will not to hack or patch a library but use wrapper code to override or tailor its behavior. Agama provides a couple of vehicles to manipulate behavior and appearance: Template overrides Flow cancellation These allow you to preserve encapsulation and keep project intrusiveness controlled. About flow design # It is up to developers how to design a flow. This will normally require identifying the several \"steps\" that make up the \"journey\" and the conditions upon which \"branching\" takes place. Also it is important to check already existing flows in the server that may be reused for the purpose. Agama language was made to structure flows only, not for doing general purpose programming. This means developers have to use Java for doing low-level computations in the Janssen engine. This way, the resulting implementation (in DSL) serves as a depiction of the flow itself, hiding most of the internal details. About crashes # As a flow executes things can go wrong for reasons that developers cannot foresee. A database may have crashed, a connection to an external system may have failed, the flow itself may have some bug, etc. When an abnormal situation is presented, a flow simply crashes. If a flow crashes, its parent flows (or flow) if they exist, crash as well. Trying to handle crashes involves a lot of planning and work which is too costly and will unlikely account for the so many things that might fail in a real setting. Thus, coding defensively is not recommended. While it is possible to deal with Java exceptions (product of Call s) and other abnormalities when Trigger ing flows, these features should be used sparingly. Internationalization labels # When using localization and internationalization use meaningful label keys and prefix all of them with the name of the project in question. If your project is called magicAuthnJourneys , then magicAuthnJourneys.image.caption and magicAuthnJourneys.start_button_label are good examples. This is a strategy that avoids possible name collisions in labels. OOP prose warning # Java support adds the ability to execute pieces of business logic required to build up a flow. These \u201cpieces of logic\u201d match well to Java methods, however situations like this must be avoided: x = \u2026 // A java object obtained in some way y = \u2026 // A java object obtained in some way Call x methodA arg1 arg2 \u2026 Call x methodB arg1 arg2 arg3 \u2026 z = Call y methodC \u2026 Call x methodD \u2026 z \u2026 If all those calls represent a meaningful unit of work they should be abstracted out and grouped into a single method invocation which should be thoroughly implemented in Java. Note Agama should not be used to do object-oriented programming but to make a clear, concise representation of a flow. As a rule of thumb, let Java do the heavy work; this is wiser, safer, and faster. Variable naming # Camel case is recommended. Also, in real-world flows developers would like to prefix a variable name with j when its value originates from a Java call and does not match any of Agama types directly. Example: jCustomerDetail . Finishing flows # Carefully decide how use the Finish directive in a flow. Specially when terminating sucessfully, many times developers would like to attach the identity of the user in question, as in Finish userId . This results in a successful authentication event and makes sense, but this is not always desired. Sometimes due to decomposition practices (in order to favor re-use and better organization), small flows can arise that should not carry the user identifier. As an example, suppose several flows exist for OTP (one-time passcode) authentication, like SMS, e-mail, token-based, etc. These would receive the user identifier as an input and act accordingly by verifying the passcode the user has entered at the browser. A parent flow can be used to prompt for a username and password first, and then forward the user to the OTP flow that better matches the user's preferences. This sounds fine, however, since any flow can be triggered by means of an authentication request by default, a skilled individual might try to launch one of the OTP flows directly passing proper parameters. This would result in authentications using a single factor (i.e. no password) which is undesirable. Thus, it is recommended to include userId in Finish only when there is a reason to do so, that is, when the authentication carried out by the flow is strong enough. This largely depends on the defined organization policies, but using a two-factor authentication is often a good sign of strength. Another approach is explicitly state which flows should not be triggered from a browser directly. This can be done in the Agama project descriptor , project.json . Recall the simplest way to express a positive authentication outcome is just Finish true .", "title": "Agama Best Practices"}, {"location": "janssen-server/developer/agama/agama-best-practices/#recommended-practices-in-agama-development", "text": "", "title": "Recommended practices in Agama development"}, {"location": "janssen-server/developer/agama/agama-best-practices/#project-reuse-and-customizations", "text": "Agama was designed with reusability in mind. If a project provides functionalities of your interest but you find it does not quite achieve what you want, do not try to modify the project. Instead, create a new separate project reusing the flows and code found in the original project. It might be tempting to just take an Agama project archive, apply some editions, add files to it, repack, and redeploy it. This practice is not recommended. Think of a project as a library used to develop software. In normal situations you will not to hack or patch a library but use wrapper code to override or tailor its behavior. Agama provides a couple of vehicles to manipulate behavior and appearance: Template overrides Flow cancellation These allow you to preserve encapsulation and keep project intrusiveness controlled.", "title": "Project reuse and customizations"}, {"location": "janssen-server/developer/agama/agama-best-practices/#about-flow-design", "text": "It is up to developers how to design a flow. This will normally require identifying the several \"steps\" that make up the \"journey\" and the conditions upon which \"branching\" takes place. Also it is important to check already existing flows in the server that may be reused for the purpose. Agama language was made to structure flows only, not for doing general purpose programming. This means developers have to use Java for doing low-level computations in the Janssen engine. This way, the resulting implementation (in DSL) serves as a depiction of the flow itself, hiding most of the internal details.", "title": "About flow design"}, {"location": "janssen-server/developer/agama/agama-best-practices/#about-crashes", "text": "As a flow executes things can go wrong for reasons that developers cannot foresee. A database may have crashed, a connection to an external system may have failed, the flow itself may have some bug, etc. When an abnormal situation is presented, a flow simply crashes. If a flow crashes, its parent flows (or flow) if they exist, crash as well. Trying to handle crashes involves a lot of planning and work which is too costly and will unlikely account for the so many things that might fail in a real setting. Thus, coding defensively is not recommended. While it is possible to deal with Java exceptions (product of Call s) and other abnormalities when Trigger ing flows, these features should be used sparingly.", "title": "About crashes"}, {"location": "janssen-server/developer/agama/agama-best-practices/#internationalization-labels", "text": "When using localization and internationalization use meaningful label keys and prefix all of them with the name of the project in question. If your project is called magicAuthnJourneys , then magicAuthnJourneys.image.caption and magicAuthnJourneys.start_button_label are good examples. This is a strategy that avoids possible name collisions in labels.", "title": "Internationalization labels"}, {"location": "janssen-server/developer/agama/agama-best-practices/#oop-prose-warning", "text": "Java support adds the ability to execute pieces of business logic required to build up a flow. These \u201cpieces of logic\u201d match well to Java methods, however situations like this must be avoided: x = \u2026 // A java object obtained in some way y = \u2026 // A java object obtained in some way Call x methodA arg1 arg2 \u2026 Call x methodB arg1 arg2 arg3 \u2026 z = Call y methodC \u2026 Call x methodD \u2026 z \u2026 If all those calls represent a meaningful unit of work they should be abstracted out and grouped into a single method invocation which should be thoroughly implemented in Java. Note Agama should not be used to do object-oriented programming but to make a clear, concise representation of a flow. As a rule of thumb, let Java do the heavy work; this is wiser, safer, and faster.", "title": "OOP prose warning"}, {"location": "janssen-server/developer/agama/agama-best-practices/#variable-naming", "text": "Camel case is recommended. Also, in real-world flows developers would like to prefix a variable name with j when its value originates from a Java call and does not match any of Agama types directly. Example: jCustomerDetail .", "title": "Variable naming"}, {"location": "janssen-server/developer/agama/agama-best-practices/#finishing-flows", "text": "Carefully decide how use the Finish directive in a flow. Specially when terminating sucessfully, many times developers would like to attach the identity of the user in question, as in Finish userId . This results in a successful authentication event and makes sense, but this is not always desired. Sometimes due to decomposition practices (in order to favor re-use and better organization), small flows can arise that should not carry the user identifier. As an example, suppose several flows exist for OTP (one-time passcode) authentication, like SMS, e-mail, token-based, etc. These would receive the user identifier as an input and act accordingly by verifying the passcode the user has entered at the browser. A parent flow can be used to prompt for a username and password first, and then forward the user to the OTP flow that better matches the user's preferences. This sounds fine, however, since any flow can be triggered by means of an authentication request by default, a skilled individual might try to launch one of the OTP flows directly passing proper parameters. This would result in authentications using a single factor (i.e. no password) which is undesirable. Thus, it is recommended to include userId in Finish only when there is a reason to do so, that is, when the authentication carried out by the flow is strong enough. This largely depends on the defined organization policies, but using a two-factor authentication is often a good sign of strength. Another approach is explicitly state which flows should not be triggered from a browser directly. This can be done in the Agama project descriptor , project.json . Recall the simplest way to express a positive authentication outcome is just Finish true .", "title": "Finishing flows"}, {"location": "janssen-server/developer/agama/engine-bridge-config/", "tags": ["administration", "developer", "agama"], "text": "Engine and bridge configurations # Availability # The engine and the bridge are two of the components part of the Agama Framework implementation in Janssen. The engine is a piece of software in charge of parsing flows written in Agama DSL and put them into action. The \"bridge\" is a regular jython script that temporarily hands control to the engine when an Agama flow is started, and receives control back once the flow has finished. This script is in charge of completing the authentication process for the user. By default, the bridge is disabled. To activate it do the following: Open TUI Navigate to Scripts > Search 'agama' > Select the script and hit enter > check enabled > save Engine configuration # Some aspects of the engine are configurable and they are integral part of the Jans authentication server's JSON configuration - specifically the section labeled agamaConfiguration . To learn how to perform changes in the server's configuration click here . The properties of Agama engine configuration are described in the following: enabled : A boolean value that specifies if the engine is enabled. To disable the engine, open TUI and navigate to Auth Server > properties > agamaConfiguration . Then uncheck enabled and hit save templatesPath : A path relative to /opt/jans/jetty/jans-auth/agama that serves as the root of Agama flow pages. Default value is /ftl scriptsPath : A path relative to /opt/jans/jetty/jans-auth/agama that serves as the root of the hierarchy of (Java/Groovy) classes added on the fly. Default value is /scripts maxItemsLoggedInCollections : When a list or map is logged in a flow, only the first few items are included in the output. You can use this property to increase that limit. Default value is 9 pageMismatchErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when an unexpected URL is requested while a flow is in course. Default value is mismatch.ftlh interruptionErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when a user exceeds the amount of time allowed to take a flow to completion. Note that in order to preserve resources, the engine holds references to unfinished flows only for a small period of time (usually less than two minutes). Once the reference is lost, the error page regarded here won't be shown but pageMismatchErrorPage . Default value is timeout.ftlh crashErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when an error has occured while running the flow. It contains a brief description of the problem for troubleshooting. Default value is crash.ftlh finishedFlowPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when a flow has finished (whether successfully or not) in the phase handled exclusively by the engine. This page features an auto-submitting form that users won't notice in practice. This page will rarely need modifications. Default value is finished.ftlh bridgeScriptPage : This is a facelets (JSF) page the bridge needs for proper operation. This page resides in the authentication server WAR file and will rarely need modifications. Default value is agama.xhtml serializeRules : A JSON object specifying the serialization rules, see below. It is not recommended to remove items from the out-of-the-box rules. Adding items is fine Serialization rules # At certain points in the course of a flow, serialization of all its variables is required. The engine employs two mechanisms for this purpose: standard Java serialization and KRYO serialization. Depending on the type of (Java) object to be serialized, administrators can specify when a mechanism is preferred over the other through a set of simple rules. This can be better explained with an example. Suppose the following configuration: \"serializeRules\": { \"JAVA\": [\"ice\", \"com.acme\"], \"KRYO\": [ \"com.acme.bike\" ] } If the object to serialize belongs to class com.acme.bike.SuperSonic , both lists are traversed for the best package match. Here KRYO wins because it has a perfect match with respect to the package of the class If the class were com.acme.bike.mega.SuperSonic , KRYO still wins because it has the closest match to the package of the class In case of ice.cream.Salty , JAVA is chosen (best match) In case of org.buskers.Singer , no matches are found, however, KRYO is chosen - it's the fallback method In case of com.acmeMan , no matches are found. KRYO is picked as in the previous case Please account additional behaviors: If the object's class is in the default package (unnamed package), KRYO is used If the exact class name is found in one of the lists, the method represented by such list is employed If the object is a (Java) exception, JAVA is used unless the full class name appears listed in the KRYO rules Bridge configuration # Administrators can modify the behavior of the bridge by setting the finish_userid_db_attribute configuration property of the script. This is used to map the identity of the user to login in the case of sucessfully finished flows. The value of this property will contain a physical database attribute that will be correlated with the userId passed in the Finish instruction of the flow.", "title": "Engine and bridge configurations"}, {"location": "janssen-server/developer/agama/engine-bridge-config/#engine-and-bridge-configurations", "text": "", "title": "Engine and bridge configurations"}, {"location": "janssen-server/developer/agama/engine-bridge-config/#availability", "text": "The engine and the bridge are two of the components part of the Agama Framework implementation in Janssen. The engine is a piece of software in charge of parsing flows written in Agama DSL and put them into action. The \"bridge\" is a regular jython script that temporarily hands control to the engine when an Agama flow is started, and receives control back once the flow has finished. This script is in charge of completing the authentication process for the user. By default, the bridge is disabled. To activate it do the following: Open TUI Navigate to Scripts > Search 'agama' > Select the script and hit enter > check enabled > save", "title": "Availability"}, {"location": "janssen-server/developer/agama/engine-bridge-config/#engine-configuration", "text": "Some aspects of the engine are configurable and they are integral part of the Jans authentication server's JSON configuration - specifically the section labeled agamaConfiguration . To learn how to perform changes in the server's configuration click here . The properties of Agama engine configuration are described in the following: enabled : A boolean value that specifies if the engine is enabled. To disable the engine, open TUI and navigate to Auth Server > properties > agamaConfiguration . Then uncheck enabled and hit save templatesPath : A path relative to /opt/jans/jetty/jans-auth/agama that serves as the root of Agama flow pages. Default value is /ftl scriptsPath : A path relative to /opt/jans/jetty/jans-auth/agama that serves as the root of the hierarchy of (Java/Groovy) classes added on the fly. Default value is /scripts maxItemsLoggedInCollections : When a list or map is logged in a flow, only the first few items are included in the output. You can use this property to increase that limit. Default value is 9 pageMismatchErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when an unexpected URL is requested while a flow is in course. Default value is mismatch.ftlh interruptionErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when a user exceeds the amount of time allowed to take a flow to completion. Note that in order to preserve resources, the engine holds references to unfinished flows only for a small period of time (usually less than two minutes). Once the reference is lost, the error page regarded here won't be shown but pageMismatchErrorPage . Default value is timeout.ftlh crashErrorPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when an error has occured while running the flow. It contains a brief description of the problem for troubleshooting. Default value is crash.ftlh finishedFlowPage : A path relative to /opt/jans/jetty/jans-auth/agama containing the location of the page shown when a flow has finished (whether successfully or not) in the phase handled exclusively by the engine. This page features an auto-submitting form that users won't notice in practice. This page will rarely need modifications. Default value is finished.ftlh bridgeScriptPage : This is a facelets (JSF) page the bridge needs for proper operation. This page resides in the authentication server WAR file and will rarely need modifications. Default value is agama.xhtml serializeRules : A JSON object specifying the serialization rules, see below. It is not recommended to remove items from the out-of-the-box rules. Adding items is fine", "title": "Engine configuration"}, {"location": "janssen-server/developer/agama/engine-bridge-config/#serialization-rules", "text": "At certain points in the course of a flow, serialization of all its variables is required. The engine employs two mechanisms for this purpose: standard Java serialization and KRYO serialization. Depending on the type of (Java) object to be serialized, administrators can specify when a mechanism is preferred over the other through a set of simple rules. This can be better explained with an example. Suppose the following configuration: \"serializeRules\": { \"JAVA\": [\"ice\", \"com.acme\"], \"KRYO\": [ \"com.acme.bike\" ] } If the object to serialize belongs to class com.acme.bike.SuperSonic , both lists are traversed for the best package match. Here KRYO wins because it has a perfect match with respect to the package of the class If the class were com.acme.bike.mega.SuperSonic , KRYO still wins because it has the closest match to the package of the class In case of ice.cream.Salty , JAVA is chosen (best match) In case of org.buskers.Singer , no matches are found, however, KRYO is chosen - it's the fallback method In case of com.acmeMan , no matches are found. KRYO is picked as in the previous case Please account additional behaviors: If the object's class is in the default package (unnamed package), KRYO is used If the exact class name is found in one of the lists, the method represented by such list is employed If the object is a (Java) exception, JAVA is used unless the full class name appears listed in the KRYO rules", "title": "Serialization rules"}, {"location": "janssen-server/developer/agama/engine-bridge-config/#bridge-configuration", "text": "Administrators can modify the behavior of the bridge by setting the finish_userid_db_attribute configuration property of the script. This is used to map the identity of the user to login in the case of sucessfully finished flows. The value of this property will contain a physical database attribute that will be correlated with the userId passed in the Finish instruction of the flow.", "title": "Bridge configuration"}, {"location": "janssen-server/developer/agama/faq/", "tags": ["administration", "developer", "agama"], "text": "Frequently asked questions # Common errors # Unable to find a suitable constructor with arity ... in class ... # A Java invocation of the form Call package.className#new ... is passing an incorrect number of arguments or their data types do not match the signature of any of the constructors for that class. Unable to find a suitable method called ... with arity ... in class ... # A java invocation is attempting to call a method that is not part of the given class, the number of arguments passed for the method is not correct, or the arguments could not be converted to make a successful call. No Finish instruction was reached # This occurs when no Finish statement has been found in the execution of a flow and there are no remaining instructions. Serialization errors # Agama engine saves the state of a flow every time an RRF or RFAC instruction is reached. The State can be understood as the set of all variables defined in a flow and their associated values up to certain point. Most of times, variables hold basic Agama values like strings, booleans, numbers, lists or maps, however, more complex values may appear due to Java Call s. The engine does its best to properly serialize these Java objects, nonetheless, this is not always possible. In these cases, the flow crashes and errors will appear on screen as well as in the server logs. Use the information in the logs to detect the problematic Java class. This would normally allow you to identify the variable that is causing the issue. Now you have several options to proceed: Check if the value held by the variable is needed for the given RRF/RFAC or some upcoming statement. If that's not the case, simply set it to null before RRF/RFAC occurs Extract only the necessary pieces from the variable, that is, grab only the fields from the object which are of use for the rest of the flow. If they are simple values like strings or numbers, serialization will succeed. Ensure to nullify or overwrite the original variable Adjust the given class so it is \"serialization\" friendlier. Sometimes, adding a no-args constructor fixes the problem. In other cases, making the class implement the java.io.Serializable interface will make it work. The error in the log should provide a hint Tweak the engine serialization rules so an alternative type of serialization can be used for this particular object Modify your Java code so an alternative class is used instead In general, a good practice is to avoid handling complex variables in flows. Letting big object graphs live in the state has a negative impact on performance and also increases the risk of serialization issues. Libraries and classes added on the fly # What Groovy and Java versions are supported? # Groovy 4.0 and Java 8 or higher. The runtime is Amazon Corretto 17. How to add third party libraries? # You can include jar files in the lib directory of a project . This applies only for VM-based installation of Janssen. Onboarding the jar files require a restart of the authentication server. A class is still available after removing the corresponding file # This is because the JVM does not support unloading: even if a given source file is removed, its corresponding class will still be accessible - it remains in the classpath. The classpath will be clean again after a service restart. How to add log statements? # The Jans server uses slf4j and log4j2 logging frameworks. Below is a simple usage example for Java/Groovy code: import org.slf4j.Logger; import org.slf4j.LoggerFactory; ... Logger logger = LoggerFactory.getLogger(your.class); logger.info(\"ahoy, ahoy\"); Note The logging descriptor used by the server can be found here Depending on the package your class belongs to, the message may not appear in the server log. In this case, you have two choices: Supply a custom log4j descriptor Use a class in package io.jans when calling getLogger . A good example would be using io.jans.agama.model.Flow How to append data to a flow's log directly? # Call method log of class io.jans.agama.engine.script.LogUtils . This method receives a variable number of arguments as DSL's Log does. Thus you can do LogUtils.log(\"@w Today is Friday %th\", 13) , as in the logging examples . How to use Contexts and Dependency Injection (CDI)? # Jans server uses Weld (a CDI reference implementation), and as such makes heavy use of managed beans, scopes, dependency injection, events, etc. Unless the code added is part of a jar library , annotations related to scopes or dependency injection won't take any effect in your code. This is because the Java container does a thorough scanning of classes upon start, but the source code files in lib directory are compiled upon use and modification, as expected in a scripting scenario. Java/Groovy files can however reuse any of the (application-scoped) managed beans available in the server's classpath. To obtain a reference to a bean, use a call like: import io.jans.service.cdi.util.CdiUtil; ... ref = CdiUtil.bean(managedBean.class); More advanced bean lookup capabilities are provided by method instance of this class where you can supply qualifiers. Templates # How to implement localization? # This topic is covered here . How to modify the built-in error pages? # Agama features some error pages out-of-the-box. They can be customized by editing the corresponding files referenced in the configuration doc page. Is Javascript supported? # Yes, the template engine is not concerned about the kind of contents linked in markup. It does not even care if your markup makes any sense. For FreeMarker, templates just produce a textual output. A flow page is not rendered as HTML, the browser just shows the source code as text # This is due to lack of proper Content-Type response header. This occurs if your template has filename extension other than ftlh . If you don't want to rename your template, insert <#ftl output_format=\"HTML\"> at the beginning of the file. How to produce JSON instead of HTML? # In your templates use <#ftl output_format=\"JSON\"> in the first line. Take a look at the templates whose name start with json_ in folder /opt/jans/jetty/jans-auth/agama . Particularly check how JSON content can be escaped - unfortunately FreeMarker does not support escaping for JSON out-of-the-box. Development tools # Are there any IDE or editor plugins available for coding flows and manage projects? # Not plugins but you can use Agama Lab for projects and flows authoring. How to debug flows? # We plan to offer a debugger in the future. In the meantime, you can do printf -like debugging using the Log instruction. See Agama logging . Miscellaneous # How to launch a flow? # A flow is launched by issuing an authentication request in a browser as explained here . Does flow execution timeout? # Yes. The maximum amount of time an end-user can take to fully complete a flow is driven by the configuration of the authentication server and can be constrained even more in the flow itself. Read about timeouts here . How to prevent launching a flow directly from the browser? # This can be configured in the project's metadata file . Updates in a flow's code are not reflected in its execution # When a project is re-deployed, a flow remains unchanged if it comes with errors in the provided .gama file. The tool used for deployment will let you know which flows have errors and their descriptions. Why are the contents of a list or map logged partially? # This is to avoid traversing big structures fully. You can increase the value of maxItemsLoggedInCollections in the engine configuration . How to add two numbers or compare numeric values in Agama? # Agama only provides operators for equality/inequality check in conditional statements. Comparisons like \"less-than\", \"greater-than-or-equal\", etc. require Java usage, however, the structure of an authentication flow will rarely have to deal with this kind of computations. Hint : methods like addExact , incrementExact , etc. in java.lang.Math may help you to do some arithmetic. How to concatenate strings in Agama? # See the previous answer. A two-lines solution could be: strings = [ s1, s2, ... ] Call java.lang.String#join \"\" strings How to know the index of a given loop iteration? # See the examples in the Looping section of the language reference . How to know the number of iterations carried out by a loop once it has finished? # You can assign this value to a variable at the top of your loop declaration. See the examples in the Looping section of the language reference . How to access localization labels from Java code? # In Freemarker, localization labels are accessed using the ${labels(key, ...)} notation. The following would be a Java equivalent: import io.jans.agama.engine.service.LabelsService; ... lbls = io.jans.service.cdi.util.CdiUtil.bean(LabelsService.class); String label = lbls.get(\"<label key>\", ... optional extra params); Note the localization context (language, country, etc.) used in such a call is based on the HTTP request that is taking place when the code is invoked. Can Agama code be called from Java? # No. These two languages are supposed to play roles that should not be mixed, check here . How to run flows from native applications instead of web browsers? # There is a separate doc page covering this aspect here .", "title": "FAQ"}, {"location": "janssen-server/developer/agama/faq/#frequently-asked-questions", "text": "", "title": "Frequently asked questions"}, {"location": "janssen-server/developer/agama/faq/#common-errors", "text": "", "title": "Common errors"}, {"location": "janssen-server/developer/agama/faq/#unable-to-find-a-suitable-constructor-with-arity-in-class", "text": "A Java invocation of the form Call package.className#new ... is passing an incorrect number of arguments or their data types do not match the signature of any of the constructors for that class.", "title": "Unable to find a suitable constructor with arity ... in class ..."}, {"location": "janssen-server/developer/agama/faq/#unable-to-find-a-suitable-method-called-with-arity-in-class", "text": "A java invocation is attempting to call a method that is not part of the given class, the number of arguments passed for the method is not correct, or the arguments could not be converted to make a successful call.", "title": "Unable to find a suitable method called ... with arity ... in class ..."}, {"location": "janssen-server/developer/agama/faq/#no-finish-instruction-was-reached", "text": "This occurs when no Finish statement has been found in the execution of a flow and there are no remaining instructions.", "title": "No Finish instruction was reached"}, {"location": "janssen-server/developer/agama/faq/#serialization-errors", "text": "Agama engine saves the state of a flow every time an RRF or RFAC instruction is reached. The State can be understood as the set of all variables defined in a flow and their associated values up to certain point. Most of times, variables hold basic Agama values like strings, booleans, numbers, lists or maps, however, more complex values may appear due to Java Call s. The engine does its best to properly serialize these Java objects, nonetheless, this is not always possible. In these cases, the flow crashes and errors will appear on screen as well as in the server logs. Use the information in the logs to detect the problematic Java class. This would normally allow you to identify the variable that is causing the issue. Now you have several options to proceed: Check if the value held by the variable is needed for the given RRF/RFAC or some upcoming statement. If that's not the case, simply set it to null before RRF/RFAC occurs Extract only the necessary pieces from the variable, that is, grab only the fields from the object which are of use for the rest of the flow. If they are simple values like strings or numbers, serialization will succeed. Ensure to nullify or overwrite the original variable Adjust the given class so it is \"serialization\" friendlier. Sometimes, adding a no-args constructor fixes the problem. In other cases, making the class implement the java.io.Serializable interface will make it work. The error in the log should provide a hint Tweak the engine serialization rules so an alternative type of serialization can be used for this particular object Modify your Java code so an alternative class is used instead In general, a good practice is to avoid handling complex variables in flows. Letting big object graphs live in the state has a negative impact on performance and also increases the risk of serialization issues.", "title": "Serialization errors"}, {"location": "janssen-server/developer/agama/faq/#libraries-and-classes-added-on-the-fly", "text": "", "title": "Libraries and classes added on the fly"}, {"location": "janssen-server/developer/agama/faq/#what-groovy-and-java-versions-are-supported", "text": "Groovy 4.0 and Java 8 or higher. The runtime is Amazon Corretto 17.", "title": "What Groovy and Java versions are supported?"}, {"location": "janssen-server/developer/agama/faq/#how-to-add-third-party-libraries", "text": "You can include jar files in the lib directory of a project . This applies only for VM-based installation of Janssen. Onboarding the jar files require a restart of the authentication server.", "title": "How to add third party libraries?"}, {"location": "janssen-server/developer/agama/faq/#a-class-is-still-available-after-removing-the-corresponding-file", "text": "This is because the JVM does not support unloading: even if a given source file is removed, its corresponding class will still be accessible - it remains in the classpath. The classpath will be clean again after a service restart.", "title": "A class is still available after removing the corresponding file"}, {"location": "janssen-server/developer/agama/faq/#how-to-add-log-statements", "text": "The Jans server uses slf4j and log4j2 logging frameworks. Below is a simple usage example for Java/Groovy code: import org.slf4j.Logger; import org.slf4j.LoggerFactory; ... Logger logger = LoggerFactory.getLogger(your.class); logger.info(\"ahoy, ahoy\"); Note The logging descriptor used by the server can be found here Depending on the package your class belongs to, the message may not appear in the server log. In this case, you have two choices: Supply a custom log4j descriptor Use a class in package io.jans when calling getLogger . A good example would be using io.jans.agama.model.Flow", "title": "How to add log statements?"}, {"location": "janssen-server/developer/agama/faq/#how-to-append-data-to-a-flows-log-directly", "text": "Call method log of class io.jans.agama.engine.script.LogUtils . This method receives a variable number of arguments as DSL's Log does. Thus you can do LogUtils.log(\"@w Today is Friday %th\", 13) , as in the logging examples .", "title": "How to append data to a flow's log directly?"}, {"location": "janssen-server/developer/agama/faq/#how-to-use-contexts-and-dependency-injection-cdi", "text": "Jans server uses Weld (a CDI reference implementation), and as such makes heavy use of managed beans, scopes, dependency injection, events, etc. Unless the code added is part of a jar library , annotations related to scopes or dependency injection won't take any effect in your code. This is because the Java container does a thorough scanning of classes upon start, but the source code files in lib directory are compiled upon use and modification, as expected in a scripting scenario. Java/Groovy files can however reuse any of the (application-scoped) managed beans available in the server's classpath. To obtain a reference to a bean, use a call like: import io.jans.service.cdi.util.CdiUtil; ... ref = CdiUtil.bean(managedBean.class); More advanced bean lookup capabilities are provided by method instance of this class where you can supply qualifiers.", "title": "How to use Contexts and Dependency Injection (CDI)?"}, {"location": "janssen-server/developer/agama/faq/#templates", "text": "", "title": "Templates"}, {"location": "janssen-server/developer/agama/faq/#how-to-implement-localization", "text": "This topic is covered here .", "title": "How to implement localization?"}, {"location": "janssen-server/developer/agama/faq/#how-to-modify-the-built-in-error-pages", "text": "Agama features some error pages out-of-the-box. They can be customized by editing the corresponding files referenced in the configuration doc page.", "title": "How to modify the built-in error pages?"}, {"location": "janssen-server/developer/agama/faq/#is-javascript-supported", "text": "Yes, the template engine is not concerned about the kind of contents linked in markup. It does not even care if your markup makes any sense. For FreeMarker, templates just produce a textual output.", "title": "Is Javascript supported?"}, {"location": "janssen-server/developer/agama/faq/#a-flow-page-is-not-rendered-as-html-the-browser-just-shows-the-source-code-as-text", "text": "This is due to lack of proper Content-Type response header. This occurs if your template has filename extension other than ftlh . If you don't want to rename your template, insert <#ftl output_format=\"HTML\"> at the beginning of the file.", "title": "A flow page is not rendered as HTML, the browser just shows the source code as text"}, {"location": "janssen-server/developer/agama/faq/#how-to-produce-json-instead-of-html", "text": "In your templates use <#ftl output_format=\"JSON\"> in the first line. Take a look at the templates whose name start with json_ in folder /opt/jans/jetty/jans-auth/agama . Particularly check how JSON content can be escaped - unfortunately FreeMarker does not support escaping for JSON out-of-the-box.", "title": "How to produce JSON instead of HTML?"}, {"location": "janssen-server/developer/agama/faq/#development-tools", "text": "", "title": "Development tools"}, {"location": "janssen-server/developer/agama/faq/#are-there-any-ide-or-editor-plugins-available-for-coding-flows-and-manage-projects", "text": "Not plugins but you can use Agama Lab for projects and flows authoring.", "title": "Are there any IDE or editor plugins available for coding flows and manage projects?"}, {"location": "janssen-server/developer/agama/faq/#how-to-debug-flows", "text": "We plan to offer a debugger in the future. In the meantime, you can do printf -like debugging using the Log instruction. See Agama logging .", "title": "How to debug flows?"}, {"location": "janssen-server/developer/agama/faq/#miscellaneous", "text": "", "title": "Miscellaneous"}, {"location": "janssen-server/developer/agama/faq/#how-to-launch-a-flow", "text": "A flow is launched by issuing an authentication request in a browser as explained here .", "title": "How to launch a flow?"}, {"location": "janssen-server/developer/agama/faq/#does-flow-execution-timeout", "text": "Yes. The maximum amount of time an end-user can take to fully complete a flow is driven by the configuration of the authentication server and can be constrained even more in the flow itself. Read about timeouts here .", "title": "Does flow execution timeout?"}, {"location": "janssen-server/developer/agama/faq/#how-to-prevent-launching-a-flow-directly-from-the-browser", "text": "This can be configured in the project's metadata file .", "title": "How to prevent launching a flow directly from the browser?"}, {"location": "janssen-server/developer/agama/faq/#updates-in-a-flows-code-are-not-reflected-in-its-execution", "text": "When a project is re-deployed, a flow remains unchanged if it comes with errors in the provided .gama file. The tool used for deployment will let you know which flows have errors and their descriptions.", "title": "Updates in a flow's code are not reflected in its execution"}, {"location": "janssen-server/developer/agama/faq/#why-are-the-contents-of-a-list-or-map-logged-partially", "text": "This is to avoid traversing big structures fully. You can increase the value of maxItemsLoggedInCollections in the engine configuration .", "title": "Why are the contents of a list or map logged partially?"}, {"location": "janssen-server/developer/agama/faq/#how-to-add-two-numbers-or-compare-numeric-values-in-agama", "text": "Agama only provides operators for equality/inequality check in conditional statements. Comparisons like \"less-than\", \"greater-than-or-equal\", etc. require Java usage, however, the structure of an authentication flow will rarely have to deal with this kind of computations. Hint : methods like addExact , incrementExact , etc. in java.lang.Math may help you to do some arithmetic.", "title": "How to add two numbers or compare numeric values in Agama?"}, {"location": "janssen-server/developer/agama/faq/#how-to-concatenate-strings-in-agama", "text": "See the previous answer. A two-lines solution could be: strings = [ s1, s2, ... ] Call java.lang.String#join \"\" strings", "title": "How to concatenate strings in Agama?"}, {"location": "janssen-server/developer/agama/faq/#how-to-know-the-index-of-a-given-loop-iteration", "text": "See the examples in the Looping section of the language reference .", "title": "How to know the index of a given loop iteration?"}, {"location": "janssen-server/developer/agama/faq/#how-to-know-the-number-of-iterations-carried-out-by-a-loop-once-it-has-finished", "text": "You can assign this value to a variable at the top of your loop declaration. See the examples in the Looping section of the language reference .", "title": "How to know the number of iterations carried out by a loop once it has finished?"}, {"location": "janssen-server/developer/agama/faq/#how-to-access-localization-labels-from-java-code", "text": "In Freemarker, localization labels are accessed using the ${labels(key, ...)} notation. The following would be a Java equivalent: import io.jans.agama.engine.service.LabelsService; ... lbls = io.jans.service.cdi.util.CdiUtil.bean(LabelsService.class); String label = lbls.get(\"<label key>\", ... optional extra params); Note the localization context (language, country, etc.) used in such a call is based on the HTTP request that is taking place when the code is invoked.", "title": "How to access localization labels from Java code?"}, {"location": "janssen-server/developer/agama/faq/#can-agama-code-be-called-from-java", "text": "No. These two languages are supposed to play roles that should not be mixed, check here .", "title": "Can Agama code be called from Java?"}, {"location": "janssen-server/developer/agama/faq/#how-to-run-flows-from-native-applications-instead-of-web-browsers", "text": "There is a separate doc page covering this aspect here .", "title": "How to run flows from native applications instead of web browsers?"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/", "tags": ["administration", "developer", "agama"], "text": "Flows navigation, UI pages and assets # RRF is a powerful construct in Agama. Its syntax follows this pattern: ( assignment-var =)? RRF \"path-to-UI-template\" map-variable ? Execution involves several steps which can be summarized as: location of template, rendering, and user-data retrieval. The process is explained in the following. Template location # Note For convenience, references to the server directory /opt/jans/jetty/jans-auth/agama will be replaced by <AGAMA-DIR> from here onwards. A path is built by concatenating the Basepath of the flow this RRF belongs to and the actual template path, i.e. path-to-UI-template as in the introductory parapraph. Then the engine's templates path root is prepended to it. The \"root\" is the value set in the engine configuration for the property templatesPath . Thus, in a default installation, the value to prepend would be <AGAMA-DIR>/ftl . If there is no such file, the flow will crash right away, otherwise, processing continues. How to build templates? # Templates are expected to be written using Apache FreeMarker . This is a simple and highly productive language to produce HTML and other forms of output. By convention templates generating HTML markup in Agama should have the extension ftlh . Practically they will look and behave as regular HTML files. Developers are encouraged to take a peep at the FreeMarker manual before trying to write their first pages. It usually boils down to produce the desired markup plus adding some placeholders for information that is dynamic. The key concept there is Template + data-model = output which is pretty natural. The sumation in this equation is generally referred to as \"rendering a template\" in this documentation. Rendering # Rendering is the process of \"injecting\" the variable passed ( map-variable in the above) into a template. If no variable is present in the instruction, it is assumed an empty map was passed, i.e. { } . The variable injected (\"data model\" in FreeMarker terms) always has to be an Agama map , Java bean or object implementing the java.util.Map interface. This will allow access to the contents of such variable from within the template. Here is a simple example. Suppose you want to ask for a username and password in a page called login.ftl and that such page will be stored in <AGAMA-DIR>/ftl/myflow/pages/login.ftl . Assume the flow has the header directive Basepath \"myflow\" . Also, let's say we want to pass a custom salutation message to be shown at the top of the page. Here is how the Agama code would look like: ... obj = { message: \"Hey ho!, let's go\" } RRF \"pages/login.ftl\" obj ... And here the UI page contents: <!doctype html> <html xmlns=\"http://www.w3.org/1999/xhtml\"> ... <body> <h1>${message}</h1> <form method=\"post\" enctype=\"application/x-www-form-urlencoded\"> <div> <label for=\"username\">Username</label> <input type=\"text\" name=\"username\"> </div> <div> <label for=\"password\">Password</label> <input type=\"password\" name=\"password\"> </div> <input type=\"submit\" value=\"Login\"> </form> </body> </html> Extended data model # The data model (injected map ) is attached some additional keys for convenience: webCtx . It gives easy access to often needed bits like current path, locale, etc. This is a Java object you can inspect here . Take a look at the getters; writing ${webCtx.contextPath} in a template will insert the result of calling method getContextPath - normally the string /jans-auth cache . Allows developers to retrieve values already stored in the Jans configured cache, e.g. ${cache.myKey} . To avoid template errors in case of a cache miss, you can use Freemarker's safeguard expressions . Note you cannot store/modify values in the cache from templates labels and msgs . These give access to localized messages. They are useful when templates have to render different texts depening on user context, such as country and language. Learn more here Assets handling # Clearly, templates can link other local web resources like Javascript code, images, etc. The location of this kind of files is expected to be in the filesystem under <AGAMA-DIR>/fl directory. Note this is not the same directory of templates. Doing so would allow users to retrieve the code of templates by simple URL manipulation. As an example, suppose your flow Basepath is foo and you have the instructions RRF index.ftlh and RRF bar/index2.ftlh somewhere in your code. Then your local <AGAMA-DIR>/ftl would look like: foo |- index.ftlh +- bar \\- index2.ftlh Say index.ftlh has markup like <img src=\"bar/me.png\"> and index2.ftlh has <link href=\"my/style.css\" rel=\"stylesheet\"> somewhere. This is how <AGAMA-DIR>/fl would look like: foo +- bar |- me.png \\- my \\- style.css User-data retrieval # Once the rendered page is shown in the browser, the flow execution is literally paused. If the user stands idly at this page, nothing will happen. To make the flow proceed, an HTTP POST must be made to the current URL. This is exactly what login.ftl of the above example tries to do: it provides a button that submits the form via POST for the flow to resume execution. Once the flow continues, an Agama map is built using all form fields received at the server and bound to the variable used in the assignment of the RRF instruction (the variable referred as assignment-var in the introduction of this page). This only applies when RRF has an assignment associated, of course. If the earlier example is modified to ... obj = { message: \"Hey ho!, let's go\" } credentials = RRF \"pages/login.ftl\" obj ... the form values can then be referenced as credentials.username and credentials.password in the flow. In other words, the keys of the resulting map will correspond to the form field names. The values will all be strings . 3-param variant # In the Jans Agama engine, RRF can be passed a third parameter: RRF templatePath variable boolean . When the boolean value is true the callback URL will be available while RRF is in execution (as in RFAC ). In this case, if the callback is visited, data passed to it will be set as the result of the RRF . If a POST to the current URL is received first, i.e. callback not hit, behavior will be as in the two-param RRF invocation. This is also the case when a false value is passed for the third parameter. The three-param variant of RRF can be useful when: The decision to redirect to an external site can only be done from the browser itself The external site expects to receive an HTTP POST. In this case, the rendered template may contain a form with fields as needed plus auto-submission logic in Javascript to perform the actual POST. This typically occurs in inbound-identity flows where identity providers require authentication requests serialized in application/x-www-form-urlencoded format as is the case of SAML HTTP POST binding, for example", "title": "Navigation, UI pages and assets"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#flows-navigation-ui-pages-and-assets", "text": "RRF is a powerful construct in Agama. Its syntax follows this pattern: ( assignment-var =)? RRF \"path-to-UI-template\" map-variable ? Execution involves several steps which can be summarized as: location of template, rendering, and user-data retrieval. The process is explained in the following.", "title": "Flows navigation, UI pages and assets"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#template-location", "text": "Note For convenience, references to the server directory /opt/jans/jetty/jans-auth/agama will be replaced by <AGAMA-DIR> from here onwards. A path is built by concatenating the Basepath of the flow this RRF belongs to and the actual template path, i.e. path-to-UI-template as in the introductory parapraph. Then the engine's templates path root is prepended to it. The \"root\" is the value set in the engine configuration for the property templatesPath . Thus, in a default installation, the value to prepend would be <AGAMA-DIR>/ftl . If there is no such file, the flow will crash right away, otherwise, processing continues.", "title": "Template location"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#how-to-build-templates", "text": "Templates are expected to be written using Apache FreeMarker . This is a simple and highly productive language to produce HTML and other forms of output. By convention templates generating HTML markup in Agama should have the extension ftlh . Practically they will look and behave as regular HTML files. Developers are encouraged to take a peep at the FreeMarker manual before trying to write their first pages. It usually boils down to produce the desired markup plus adding some placeholders for information that is dynamic. The key concept there is Template + data-model = output which is pretty natural. The sumation in this equation is generally referred to as \"rendering a template\" in this documentation.", "title": "How to build templates?"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#rendering", "text": "Rendering is the process of \"injecting\" the variable passed ( map-variable in the above) into a template. If no variable is present in the instruction, it is assumed an empty map was passed, i.e. { } . The variable injected (\"data model\" in FreeMarker terms) always has to be an Agama map , Java bean or object implementing the java.util.Map interface. This will allow access to the contents of such variable from within the template. Here is a simple example. Suppose you want to ask for a username and password in a page called login.ftl and that such page will be stored in <AGAMA-DIR>/ftl/myflow/pages/login.ftl . Assume the flow has the header directive Basepath \"myflow\" . Also, let's say we want to pass a custom salutation message to be shown at the top of the page. Here is how the Agama code would look like: ... obj = { message: \"Hey ho!, let's go\" } RRF \"pages/login.ftl\" obj ... And here the UI page contents: <!doctype html> <html xmlns=\"http://www.w3.org/1999/xhtml\"> ... <body> <h1>${message}</h1> <form method=\"post\" enctype=\"application/x-www-form-urlencoded\"> <div> <label for=\"username\">Username</label> <input type=\"text\" name=\"username\"> </div> <div> <label for=\"password\">Password</label> <input type=\"password\" name=\"password\"> </div> <input type=\"submit\" value=\"Login\"> </form> </body> </html>", "title": "Rendering"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#extended-data-model", "text": "The data model (injected map ) is attached some additional keys for convenience: webCtx . It gives easy access to often needed bits like current path, locale, etc. This is a Java object you can inspect here . Take a look at the getters; writing ${webCtx.contextPath} in a template will insert the result of calling method getContextPath - normally the string /jans-auth cache . Allows developers to retrieve values already stored in the Jans configured cache, e.g. ${cache.myKey} . To avoid template errors in case of a cache miss, you can use Freemarker's safeguard expressions . Note you cannot store/modify values in the cache from templates labels and msgs . These give access to localized messages. They are useful when templates have to render different texts depening on user context, such as country and language. Learn more here", "title": "Extended data model"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#assets-handling", "text": "Clearly, templates can link other local web resources like Javascript code, images, etc. The location of this kind of files is expected to be in the filesystem under <AGAMA-DIR>/fl directory. Note this is not the same directory of templates. Doing so would allow users to retrieve the code of templates by simple URL manipulation. As an example, suppose your flow Basepath is foo and you have the instructions RRF index.ftlh and RRF bar/index2.ftlh somewhere in your code. Then your local <AGAMA-DIR>/ftl would look like: foo |- index.ftlh +- bar \\- index2.ftlh Say index.ftlh has markup like <img src=\"bar/me.png\"> and index2.ftlh has <link href=\"my/style.css\" rel=\"stylesheet\"> somewhere. This is how <AGAMA-DIR>/fl would look like: foo +- bar |- me.png \\- my \\- style.css", "title": "Assets handling"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#user-data-retrieval", "text": "Once the rendered page is shown in the browser, the flow execution is literally paused. If the user stands idly at this page, nothing will happen. To make the flow proceed, an HTTP POST must be made to the current URL. This is exactly what login.ftl of the above example tries to do: it provides a button that submits the form via POST for the flow to resume execution. Once the flow continues, an Agama map is built using all form fields received at the server and bound to the variable used in the assignment of the RRF instruction (the variable referred as assignment-var in the introduction of this page). This only applies when RRF has an assignment associated, of course. If the earlier example is modified to ... obj = { message: \"Hey ho!, let's go\" } credentials = RRF \"pages/login.ftl\" obj ... the form values can then be referenced as credentials.username and credentials.password in the flow. In other words, the keys of the resulting map will correspond to the form field names. The values will all be strings .", "title": "User-data retrieval"}, {"location": "janssen-server/developer/agama/flows-navigation-ui/#3-param-variant", "text": "In the Jans Agama engine, RRF can be passed a third parameter: RRF templatePath variable boolean . When the boolean value is true the callback URL will be available while RRF is in execution (as in RFAC ). In this case, if the callback is visited, data passed to it will be set as the result of the RRF . If a POST to the current URL is received first, i.e. callback not hit, behavior will be as in the two-param RRF invocation. This is also the case when a false value is passed for the third parameter. The three-param variant of RRF can be useful when: The decision to redirect to an external site can only be done from the browser itself The external site expects to receive an HTTP POST. In this case, the rendered template may contain a form with fields as needed plus auto-submission logic in Javascript to perform the actual POST. This typically occurs in inbound-identity flows where identity providers require authentication requests serialized in application/x-www-form-urlencoded format as is the case of SAML HTTP POST binding, for example", "title": "3-param variant"}, {"location": "janssen-server/developer/agama/jans-agama-engine/", "tags": ["administration", "developer", "agama"], "text": "Janssen Agama Engine # Introduction # The Janssen Server implements the Agama framework through several components bundled in its authentication server (AS): The engine: the piece of software that actually runs the flows and interacts with the user's browser - sort of a small web application. As expected, these flows are mainly targetted at user authentication A transpiler: code written in Agama language is transpiled to an intermediate representation which can then be interpreted at runtime by the engine The bridge: since the engine itself does not implement an authentication protocol, another piece is required to put flows in the context of a standard authorization framework like OpenId Connect. This is what the bridge does The deployer: a piece of software capable of deploying Agama projects to the engine. The rest of this document describes implementation-specific details of the engine bundled with the Jans Server. These details give shape to the requirements abstractly defined for an Agama-compliant engine . Note Ensure both the Agama engine and the bridge are enabled in the Janssen server to effectively use engine's features Launching flows # Flows can be launched by sending an (OpenId Connect) authentication request to the user's browser. This usually boils down to making a redirection to a URL looking like https://<jans-server-name>/jans-auth/restv1/authorize?acr_values=agama_flowQname&scope=...&response_type=...&redirect_uri=https...&client_id=...&state=... . Check the OpenId Connect spec for more details. Note Jans Server is spec-compliant. Things to highlight: The acr_values parameter carries the qualified name (identifier) of the flow to launch prefixed with the string agama_ , for example acr_values=agama_test.acme.co If the flow to call receives input parameters, this data can be appended to the acr_values parameter: use a hyphen to separate the flow name and the parameters expressed in Base64 URL encoded format. For example, if the flow had inputs height and color , you would encode the string {\"height\": 190, \"color\": \"blue\"} and the resulting value would be agama_test.acme.co-eyJoZWlnaHQiOiAxOTAsICJjb2xvciI6ICJibHVlIn0 . When a given input variable is not provided, the engine will assign a null value automatically Authentication and Finish # When a top-level flow (i.e. one with no parents) finishes successfully, the selection of the user to authenticate is driven by the userId passed in data , as in obj = { success: true, data: { userId: \"john_doe\" } } // map literals cannot be passed directly to Finish - a variable can be used instead Finish obj By default userId maps to the uid attribute that generally all user entries already have in the database of Jans Server, in other words, the \"user name\". This attribute is configurable though via property finish_userid_db_attribute of the bridge script . In some cases, you would like to change that to mail in order to pass things like { success: true, data: { userId: \"john_doe@jd.me\" } } for instance. Important If the database lookup does not produce exactly one user entry, this is treated as a failed authentication attempt by the authentication server. When the authentication succeeds, the whole contents of data are stored in the authentication server's session of the given user under the key agamaData . Contents are serialized to a JSON string previously. Crashes, timeouts, and failures # Execution rules define several possible flow states . For crashed, timed out, and finished failed flows, the engine will present proper error pages to users. These are configurable by properties crashErrorPage , interruptionErrorPage , and finishedFlowPage respectively, of the engine-configuration . How timeouts work # Authentication flows are normally short-lived. They usually span no more than a few minutes. In Agama, the maximum amount of time an end-user can take to fully complete a flow is driven by the configuration of the authentication server , specifically the sessionIdUnauthenticatedUnusedLifetime property which is measured in seconds. As an example, if this value is 120, any attempt to authenticate taking more than two minutes will throw the given error page. Moreover, when a flow specifies its own timeout in the header the effective timeout is the smallest value between sessionIdUnauthenticatedUnusedLifetime and the value in the header. Depending on specific needs, sessionIdUnauthenticatedUnusedLifetime may have to be set to a higher value than the server's default. This may be the case where flows send e-mail notifications with temporary codes, for instance. Logging # There are three relevant sources of log data: The engine. It emits information related to flows transpilation, projects deployment, and flow crashes - generally low-level information Log instructions. These are statements originated directly from the Agama code Call directives. Foreign code can issue logging statements as well as any other code a Call may depend on. See the FAQ The following table details the location of log data. Paths are relative to directory /opt/jans/jetty/jans-auth/log : Source Destination file Engine jans-auth.log Log instructions jans-auth_script.log Foreign code jans-auth.log Depending on the specificity required, you may have to change the logging level so more or less details appear in the logs. This can be done by altering the loggingLevel property of the auth server configuration . DEBUG usually suffices for troubleshooting. The available levels for statements issued with the Log instruction are: Level name shortcut error e warn w info i debug d trace t For instance, these two instructions are equivalent: Log \"@e Universe collapsed\" and Log \"@error Universe collapsed\" The engine will use info when the level is not specified explicitly, as in Log \"Look ma!\" . RFAC and Callback URL # Engine's callback URL is https://<your-server-name>/jans-auth/fl/callback . This resource is only be available for a given browser session while RFAC is in execution. Once the callback is visited or the flow times out (whichever occurs first), subsequent requests will respond with an HTTP 404 error. The mechanism used for redirection is a \"302 Found\" HTTP redirect that entails a subsequent GET request to the external site. In cases where a POST is expected, the 3-param version of RRF can be useful. RRF, navigation, and assets handling # Understanding how RRF works in the engine is key to writing meaningful flows. This topic is fully covered here . Foreign calls # In the Jans Agama engine, Java or Groovy code can be called by means of the Call instruction. Specifically, public methods from public classes or static methods from public interfaces. Note Java language background is required for this section. The following exemplifies different kind of usages of Java from Agama code: Example Notes Call java.lang.Integer#parseInt \"FF\" 16 Invokes the parseInt method of Integer class passing the given arguments (i.e. conversion of hexadecimal string to a primitive int ). The returned value is ignored numbers = [ 2, -2, 0, 3, -3, 4 ] small = Call java.util.Collections#min numbers Invokes the min method of the Collections class. Supplies a list of numbers as argument. The smallest number is stored in variable small jLocale = Call java.util.Locale#getDefault localeName = jLocale.displayName Computes the display name of the JVM default locale car = { brand: \"Ford\", model: 1963 } sidecar = Call java.util.Map#copyOf car Makes a deep clone of a map number | E = Call java.lang.Integer#parseInt \"AGA\" 16 When E is not null Log \"An error occurred:\" E.message Similar to the first example. If an exception is thrown by the invocation, it's caught and assigned to variable E . Note both checked and unchecked exceptions are caught | E = Call com.acme.Worker#notifyExternalSystem //Do something with E //... If exception catching is required when calling a method that returns void , there is no need to put a variable before the pipe p1 = Call java.awt.Point#new p2 = Call java.awt.Point#new 1 3 Call p2 translate -1 1 Creates instances of class java.awt.Point with different constructors. For p1 the no-args constructor is used. Method translate is invoked on the p2 instance. Note usage of a space here instead of hash ( # ) cls1 = Call java.lang.CharSequence#class cls2 = Call java.lang.Integer#class Call cls2 parseInt \"FF\" 16 Stores in cls1 a reference to interface class CharSequence.class . Stores in cls2 a reference to Integer.class . The 3rd line statement achieves the same effect of Call java.lang.Integer#parseInt \"FF\" 16 L = [ \"A\", \"B\", \"C\" ] S = Call java.util.Set#of 0 2 4 6 map = { numbers: S, letters: L } hasOne = Call map.numbers contains 1 Calls the contains method of the java.util.Set object stored in map.numbers passing 1 as argument and storing the result in hasOne The usage of a hash sign (or spaces) before a method name helps disambiguate whether the invocation is on a static class method or an object method. This is so because an expression like hey.You may reference the class You on package hey , or the value of key You in a map named hey . Highlights # Any method that meets the conditions mentioned (public or interface static) and that is reachable in the JVM classpath can be called; developers are not restricted solely to java.* packages. When using Call , the method to execute is picked based on the name (e.g. after the # sign) and the number of arguments supplied. If a class/interface exhibits several methods with the same name and arity (number of parameters), the method that best matches the dataypes of the arguments with respect to its signature is selected. Sometimes this requires to perform arguments conversions and they may fail. In such case, the second best suited method is tried and so on. When all attempts fail or there are no candidate methods to choose from, the Call simply throws a NoSuchMethodException . For non-static method invocations, i.e. no hash sign, the class used for method lookup is that of the instance passed (the first parameter in the Call directive). This includes all associated superclasses too, as expected. When the instance does not hold a Java but an Agama value, the following is used to pick a class: Agama type Java class for method lookup string String boolean Boolean number Double list java.util.List map java.util.Map Limitations: list and map literals cannot be passed as arguments to method calls directly. This means the following is illegal: Call co.Utils#myMethod { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] . To achieve the same effect assign the literal value to a variable and pass that instead Call ing a method that mutates one or more of the arguments passed will not work properly if the corresponding parameters in the method signature have type information attached. For example, copying a list into another using java.util.Collections#copy\u200b(List<? super T> dest, List<? extends T> src) may not behave as expected. Conversely, calling java.lang.reflect.Array#set\u200b(Object array, int index, Object value) works fine because array does not have a parameterized type. The practice of mutating passed arguments is unusual and sometimes discouraged in programming Exception handling # As seen in the examples Agama engine can deal with Java exceptions, however, this feature should be used sparingly. When exception handling adds undesired complexity to your code, create wrapper methods in Java and do the processing there instead of delegating that to the DSL. Arguments conversion # Agama types do not match Java types. This means passing a \"native\" Agama value as parameter in a method Call requires some form of compatibility with the target (Java) type in the method signature. An argument (Agama value) is compatible with a method parameter if it can be \"converted\" successfully. As we'll see, conversion feels pretty natural in practice. If this process fails a java.lang.IllegalArgumentException is thrown and the flow will crash unless the exception is caught. Note however the recommended practice is to let flows crash . The following lists some of the most common successful conversions: Agama value Can be converted to string String or char[] boolean Boolean or primitive equivalent number Double / Float / Integer / Long / Short / Byte or primitive equivalent null Any non-primitive list Array or class implementing Collection<T> as long as items can be converted to type T map Class implementing Map<K, V> as long as keys and values can be converted to types K and V , respectively map Java bean. Unrecognized properties in Agama value are ignored The below table shows some examples of interesting and handy conversions: Agama value Param data type in target Java method Argument value (Agama) Received param value (in method) Notes Positive number having fractional part Integer / Long / Short / Byte or primitive equivalent 2.6 2 Integer part kept Negative number having fractional part Integer / Long / Short / Byte or primitive equivalent -2.4 2 Integer part kept Integer number Float / Double or primitive equivalent 1 1.0 list of number s List<Integer> [1, 2.0, 3.1, -4.2] [1, 2, 3, -4] Only integer parts kept list of integer number s List<Float> / List<Double> [1, 2, 3, -4] [1.0, 2.0, 3.0, -4.0] string of length 1 Character or primitive equivalent a a Passing a zero, two, or more lengthed string will make the call fail When the argument is not an Agama but a Java object/primitive, the following rules apply: If the value can be cast to the target type, no conversion is needed, otherwise If it is an instance of java.lang.Number and the type is a numeric primitive or wrapper (e.g. Integer ), the value is truncated if required, otherwise The value is serialized to JSON - if possible - and then an attempt to create a Java instance based on the given JSON contents is made. For this purpose, the FasterXML Jackson library is used This is powerful because it allows to send data of similar shape/structure when data types do not necessarily match. Consider the following example: s = \"a man's gotta do what a man's gotta do\" jStrArr = Call s split \" \" words = Call java.util.Collections#unmodifiableSet jStrArr This Agama snippet creates the (Java) Set of different words found in a given (Agama) string . Note jStrArr is of type String[] and is passed directly to method unmodifiableSet which originally expects an instance of Set as parameter. From Java to Agama # We just saw how Agama values are treated in Java code. Here we make an analysis in the reverse direction: from Java to Agama where Java values are obtained through Call invocations. The following table relates Java types to Agama types: Java value ( x ) Agama equivalent Notes x is a Java array or implements java.util.List list Changing the list contents (includes updates on x.length) can only be achieved if the Java list is modifiable x implements java.util.Map and keys are of type java.lang.String map Changing the map contents can only be achieved if the Java map is modifiable x is a java.lang.(Double|Float|Long|Integer|Short|Byte) or an equivalent primitive number x is a (non-null) java.lang.Boolean or equivalent primitive boolean x is a java.lang.String string (limited) Neither indexing nor x.length can be used null null Except for maps, the following holds for a value x obtained through a Java Call : If x 's class has getters and/or setters for some fields, they can be called. As an example if age and name are available fields, x.age can be used to get the value of age Likewise, setting a value is possible too: x.name = \"Larry\" (if a suitable setter exists) In general, a no-args method starting with get or is can be invoked. This is useful for instance to get the (Java) class name of your object ( x.class.name ) or determine if a list has no elements ( x.empty ) Classpath # A class/interface is accessible to Agama code as long as it is part of: jans-auth.war > WEB-INF/lib/*.jar or, jans-auth.war > WEB-INF/classes or, /opt/jans/jetty/jans-auth/custom/libs/*.jar (may require edition of jans-auth.xml descriptor) Additionally, it is possible to upload source code on the fly to augment the classpath. Any valid Java or Groovy file is accepted and must be located under /opt/jans/jetty/jans-auth/agama/scripts . For instance, a class named com.acme.Person must reside in folder /opt/jans/jetty/jans-auth/agama/scripts/com/acme . Important Only files with extensions .java or .groovy are accounted The scripts directory provides automatic \"hot\" reloading. This is a valuable time saver for developers because there is no need to restart the jans-auth webapp when sources are modified. This feature has some limitations which are explained in the following. Limitations of code added \"on the fly\" # Classes in scripts directory can only be accessed through Call directives. As an example suppose you added classes A and B to scripts , and A depends on B . Call s using class A will work and any change to files A and/or B will be picked automatically. On the contrary, trying to load this kind of classes using Class.forName either from a jar file in custom/libs or from Agama itself will degenerate in ClassNotFoundException . Note A and B can also depend on classes found at any of the locations listed at the beginning of this section. Note Java sources are actually interpreted as Groovy code. 99% of times this is not a concern since Groovy can be considered a superset of Java, however, there are some minor discrepancies that may exhibit unexpected behaviors. These differences are described here . We consider the following to be remarkable: Array literals in shorthand syntax not allowed, e.g. int[] array = {1, 2, 3} . Use int[] array = new int[] {1, 2, 3} instead String interpolation: \"hello $mark\" evaluates the value of variable mark and prepends hello to it!. To avoid this use a backslash, like in \"hello \\$mark\" . Learn more about interpolation here . In general, prepend ocurrences of $ in your string literals with a \\ Usage of == operator actually calls the equals method. Most of times this is fine but can be a problem when you are overriding equals in your class and make use of == . This will introduce a recursive call in your implementation and may degenerate in a stack overflow. If possible, use the === operator or the is method in these cases OOP prose warning # See the recommended practices to learn more about this topic.", "title": "Agama engine"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#janssen-agama-engine", "text": "", "title": "Janssen Agama Engine"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#introduction", "text": "The Janssen Server implements the Agama framework through several components bundled in its authentication server (AS): The engine: the piece of software that actually runs the flows and interacts with the user's browser - sort of a small web application. As expected, these flows are mainly targetted at user authentication A transpiler: code written in Agama language is transpiled to an intermediate representation which can then be interpreted at runtime by the engine The bridge: since the engine itself does not implement an authentication protocol, another piece is required to put flows in the context of a standard authorization framework like OpenId Connect. This is what the bridge does The deployer: a piece of software capable of deploying Agama projects to the engine. The rest of this document describes implementation-specific details of the engine bundled with the Jans Server. These details give shape to the requirements abstractly defined for an Agama-compliant engine . Note Ensure both the Agama engine and the bridge are enabled in the Janssen server to effectively use engine's features", "title": "Introduction"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#launching-flows", "text": "Flows can be launched by sending an (OpenId Connect) authentication request to the user's browser. This usually boils down to making a redirection to a URL looking like https://<jans-server-name>/jans-auth/restv1/authorize?acr_values=agama_flowQname&scope=...&response_type=...&redirect_uri=https...&client_id=...&state=... . Check the OpenId Connect spec for more details. Note Jans Server is spec-compliant. Things to highlight: The acr_values parameter carries the qualified name (identifier) of the flow to launch prefixed with the string agama_ , for example acr_values=agama_test.acme.co If the flow to call receives input parameters, this data can be appended to the acr_values parameter: use a hyphen to separate the flow name and the parameters expressed in Base64 URL encoded format. For example, if the flow had inputs height and color , you would encode the string {\"height\": 190, \"color\": \"blue\"} and the resulting value would be agama_test.acme.co-eyJoZWlnaHQiOiAxOTAsICJjb2xvciI6ICJibHVlIn0 . When a given input variable is not provided, the engine will assign a null value automatically", "title": "Launching flows"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#authentication-and-finish", "text": "When a top-level flow (i.e. one with no parents) finishes successfully, the selection of the user to authenticate is driven by the userId passed in data , as in obj = { success: true, data: { userId: \"john_doe\" } } // map literals cannot be passed directly to Finish - a variable can be used instead Finish obj By default userId maps to the uid attribute that generally all user entries already have in the database of Jans Server, in other words, the \"user name\". This attribute is configurable though via property finish_userid_db_attribute of the bridge script . In some cases, you would like to change that to mail in order to pass things like { success: true, data: { userId: \"john_doe@jd.me\" } } for instance. Important If the database lookup does not produce exactly one user entry, this is treated as a failed authentication attempt by the authentication server. When the authentication succeeds, the whole contents of data are stored in the authentication server's session of the given user under the key agamaData . Contents are serialized to a JSON string previously.", "title": "Authentication and Finish"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#crashes-timeouts-and-failures", "text": "Execution rules define several possible flow states . For crashed, timed out, and finished failed flows, the engine will present proper error pages to users. These are configurable by properties crashErrorPage , interruptionErrorPage , and finishedFlowPage respectively, of the engine-configuration .", "title": "Crashes, timeouts, and failures"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#how-timeouts-work", "text": "Authentication flows are normally short-lived. They usually span no more than a few minutes. In Agama, the maximum amount of time an end-user can take to fully complete a flow is driven by the configuration of the authentication server , specifically the sessionIdUnauthenticatedUnusedLifetime property which is measured in seconds. As an example, if this value is 120, any attempt to authenticate taking more than two minutes will throw the given error page. Moreover, when a flow specifies its own timeout in the header the effective timeout is the smallest value between sessionIdUnauthenticatedUnusedLifetime and the value in the header. Depending on specific needs, sessionIdUnauthenticatedUnusedLifetime may have to be set to a higher value than the server's default. This may be the case where flows send e-mail notifications with temporary codes, for instance.", "title": "How timeouts work"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#logging", "text": "There are three relevant sources of log data: The engine. It emits information related to flows transpilation, projects deployment, and flow crashes - generally low-level information Log instructions. These are statements originated directly from the Agama code Call directives. Foreign code can issue logging statements as well as any other code a Call may depend on. See the FAQ The following table details the location of log data. Paths are relative to directory /opt/jans/jetty/jans-auth/log : Source Destination file Engine jans-auth.log Log instructions jans-auth_script.log Foreign code jans-auth.log Depending on the specificity required, you may have to change the logging level so more or less details appear in the logs. This can be done by altering the loggingLevel property of the auth server configuration . DEBUG usually suffices for troubleshooting. The available levels for statements issued with the Log instruction are: Level name shortcut error e warn w info i debug d trace t For instance, these two instructions are equivalent: Log \"@e Universe collapsed\" and Log \"@error Universe collapsed\" The engine will use info when the level is not specified explicitly, as in Log \"Look ma!\" .", "title": "Logging"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#rfac-and-callback-url", "text": "Engine's callback URL is https://<your-server-name>/jans-auth/fl/callback . This resource is only be available for a given browser session while RFAC is in execution. Once the callback is visited or the flow times out (whichever occurs first), subsequent requests will respond with an HTTP 404 error. The mechanism used for redirection is a \"302 Found\" HTTP redirect that entails a subsequent GET request to the external site. In cases where a POST is expected, the 3-param version of RRF can be useful.", "title": "RFAC and Callback URL"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#rrf-navigation-and-assets-handling", "text": "Understanding how RRF works in the engine is key to writing meaningful flows. This topic is fully covered here .", "title": "RRF, navigation, and assets handling"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#foreign-calls", "text": "In the Jans Agama engine, Java or Groovy code can be called by means of the Call instruction. Specifically, public methods from public classes or static methods from public interfaces. Note Java language background is required for this section. The following exemplifies different kind of usages of Java from Agama code: Example Notes Call java.lang.Integer#parseInt \"FF\" 16 Invokes the parseInt method of Integer class passing the given arguments (i.e. conversion of hexadecimal string to a primitive int ). The returned value is ignored numbers = [ 2, -2, 0, 3, -3, 4 ] small = Call java.util.Collections#min numbers Invokes the min method of the Collections class. Supplies a list of numbers as argument. The smallest number is stored in variable small jLocale = Call java.util.Locale#getDefault localeName = jLocale.displayName Computes the display name of the JVM default locale car = { brand: \"Ford\", model: 1963 } sidecar = Call java.util.Map#copyOf car Makes a deep clone of a map number | E = Call java.lang.Integer#parseInt \"AGA\" 16 When E is not null Log \"An error occurred:\" E.message Similar to the first example. If an exception is thrown by the invocation, it's caught and assigned to variable E . Note both checked and unchecked exceptions are caught | E = Call com.acme.Worker#notifyExternalSystem //Do something with E //... If exception catching is required when calling a method that returns void , there is no need to put a variable before the pipe p1 = Call java.awt.Point#new p2 = Call java.awt.Point#new 1 3 Call p2 translate -1 1 Creates instances of class java.awt.Point with different constructors. For p1 the no-args constructor is used. Method translate is invoked on the p2 instance. Note usage of a space here instead of hash ( # ) cls1 = Call java.lang.CharSequence#class cls2 = Call java.lang.Integer#class Call cls2 parseInt \"FF\" 16 Stores in cls1 a reference to interface class CharSequence.class . Stores in cls2 a reference to Integer.class . The 3rd line statement achieves the same effect of Call java.lang.Integer#parseInt \"FF\" 16 L = [ \"A\", \"B\", \"C\" ] S = Call java.util.Set#of 0 2 4 6 map = { numbers: S, letters: L } hasOne = Call map.numbers contains 1 Calls the contains method of the java.util.Set object stored in map.numbers passing 1 as argument and storing the result in hasOne The usage of a hash sign (or spaces) before a method name helps disambiguate whether the invocation is on a static class method or an object method. This is so because an expression like hey.You may reference the class You on package hey , or the value of key You in a map named hey .", "title": "Foreign calls"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#highlights", "text": "Any method that meets the conditions mentioned (public or interface static) and that is reachable in the JVM classpath can be called; developers are not restricted solely to java.* packages. When using Call , the method to execute is picked based on the name (e.g. after the # sign) and the number of arguments supplied. If a class/interface exhibits several methods with the same name and arity (number of parameters), the method that best matches the dataypes of the arguments with respect to its signature is selected. Sometimes this requires to perform arguments conversions and they may fail. In such case, the second best suited method is tried and so on. When all attempts fail or there are no candidate methods to choose from, the Call simply throws a NoSuchMethodException . For non-static method invocations, i.e. no hash sign, the class used for method lookup is that of the instance passed (the first parameter in the Call directive). This includes all associated superclasses too, as expected. When the instance does not hold a Java but an Agama value, the following is used to pick a class: Agama type Java class for method lookup string String boolean Boolean number Double list java.util.List map java.util.Map Limitations: list and map literals cannot be passed as arguments to method calls directly. This means the following is illegal: Call co.Utils#myMethod { key: [ 1, 2 , 3] } [ \"Yeeha!\" ] . To achieve the same effect assign the literal value to a variable and pass that instead Call ing a method that mutates one or more of the arguments passed will not work properly if the corresponding parameters in the method signature have type information attached. For example, copying a list into another using java.util.Collections#copy\u200b(List<? super T> dest, List<? extends T> src) may not behave as expected. Conversely, calling java.lang.reflect.Array#set\u200b(Object array, int index, Object value) works fine because array does not have a parameterized type. The practice of mutating passed arguments is unusual and sometimes discouraged in programming", "title": "Highlights"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#exception-handling", "text": "As seen in the examples Agama engine can deal with Java exceptions, however, this feature should be used sparingly. When exception handling adds undesired complexity to your code, create wrapper methods in Java and do the processing there instead of delegating that to the DSL.", "title": "Exception handling"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#arguments-conversion", "text": "Agama types do not match Java types. This means passing a \"native\" Agama value as parameter in a method Call requires some form of compatibility with the target (Java) type in the method signature. An argument (Agama value) is compatible with a method parameter if it can be \"converted\" successfully. As we'll see, conversion feels pretty natural in practice. If this process fails a java.lang.IllegalArgumentException is thrown and the flow will crash unless the exception is caught. Note however the recommended practice is to let flows crash . The following lists some of the most common successful conversions: Agama value Can be converted to string String or char[] boolean Boolean or primitive equivalent number Double / Float / Integer / Long / Short / Byte or primitive equivalent null Any non-primitive list Array or class implementing Collection<T> as long as items can be converted to type T map Class implementing Map<K, V> as long as keys and values can be converted to types K and V , respectively map Java bean. Unrecognized properties in Agama value are ignored The below table shows some examples of interesting and handy conversions: Agama value Param data type in target Java method Argument value (Agama) Received param value (in method) Notes Positive number having fractional part Integer / Long / Short / Byte or primitive equivalent 2.6 2 Integer part kept Negative number having fractional part Integer / Long / Short / Byte or primitive equivalent -2.4 2 Integer part kept Integer number Float / Double or primitive equivalent 1 1.0 list of number s List<Integer> [1, 2.0, 3.1, -4.2] [1, 2, 3, -4] Only integer parts kept list of integer number s List<Float> / List<Double> [1, 2, 3, -4] [1.0, 2.0, 3.0, -4.0] string of length 1 Character or primitive equivalent a a Passing a zero, two, or more lengthed string will make the call fail When the argument is not an Agama but a Java object/primitive, the following rules apply: If the value can be cast to the target type, no conversion is needed, otherwise If it is an instance of java.lang.Number and the type is a numeric primitive or wrapper (e.g. Integer ), the value is truncated if required, otherwise The value is serialized to JSON - if possible - and then an attempt to create a Java instance based on the given JSON contents is made. For this purpose, the FasterXML Jackson library is used This is powerful because it allows to send data of similar shape/structure when data types do not necessarily match. Consider the following example: s = \"a man's gotta do what a man's gotta do\" jStrArr = Call s split \" \" words = Call java.util.Collections#unmodifiableSet jStrArr This Agama snippet creates the (Java) Set of different words found in a given (Agama) string . Note jStrArr is of type String[] and is passed directly to method unmodifiableSet which originally expects an instance of Set as parameter.", "title": "Arguments conversion"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#from-java-to-agama", "text": "We just saw how Agama values are treated in Java code. Here we make an analysis in the reverse direction: from Java to Agama where Java values are obtained through Call invocations. The following table relates Java types to Agama types: Java value ( x ) Agama equivalent Notes x is a Java array or implements java.util.List list Changing the list contents (includes updates on x.length) can only be achieved if the Java list is modifiable x implements java.util.Map and keys are of type java.lang.String map Changing the map contents can only be achieved if the Java map is modifiable x is a java.lang.(Double|Float|Long|Integer|Short|Byte) or an equivalent primitive number x is a (non-null) java.lang.Boolean or equivalent primitive boolean x is a java.lang.String string (limited) Neither indexing nor x.length can be used null null Except for maps, the following holds for a value x obtained through a Java Call : If x 's class has getters and/or setters for some fields, they can be called. As an example if age and name are available fields, x.age can be used to get the value of age Likewise, setting a value is possible too: x.name = \"Larry\" (if a suitable setter exists) In general, a no-args method starting with get or is can be invoked. This is useful for instance to get the (Java) class name of your object ( x.class.name ) or determine if a list has no elements ( x.empty )", "title": "From Java to Agama"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#classpath", "text": "A class/interface is accessible to Agama code as long as it is part of: jans-auth.war > WEB-INF/lib/*.jar or, jans-auth.war > WEB-INF/classes or, /opt/jans/jetty/jans-auth/custom/libs/*.jar (may require edition of jans-auth.xml descriptor) Additionally, it is possible to upload source code on the fly to augment the classpath. Any valid Java or Groovy file is accepted and must be located under /opt/jans/jetty/jans-auth/agama/scripts . For instance, a class named com.acme.Person must reside in folder /opt/jans/jetty/jans-auth/agama/scripts/com/acme . Important Only files with extensions .java or .groovy are accounted The scripts directory provides automatic \"hot\" reloading. This is a valuable time saver for developers because there is no need to restart the jans-auth webapp when sources are modified. This feature has some limitations which are explained in the following.", "title": "Classpath"}, {"location": "janssen-server/developer/agama/jans-agama-engine/#limitations-of-code-added-on-the-fly", "text": "Classes in scripts directory can only be accessed through Call directives. As an example suppose you added classes A and B to scripts , and A depends on B . Call s using class A will work and any change to files A and/or B will be picked automatically. On the contrary, trying to load this kind of classes using Class.forName either from a jar file in custom/libs or from Agama itself will degenerate in ClassNotFoundException . Note A and B can also depend on classes found at any of the locations listed at the beginning of this section. Note Java sources are actually interpreted as Groovy code. 99% of times this is not a concern since Groovy can be considered a superset of Java, however, there are some minor discrepancies that may exhibit unexpected behaviors. These differences are described here . We consider the following to be remarkable: Array literals in shorthand syntax not allowed, e.g. int[] array = {1, 2, 3} . Use int[] array = new int[] {1, 2, 3} instead String interpolation: \"hello $mark\" evaluates the value of variable mark and prepends hello to it!. To avoid this use a backslash, like in \"hello \\$mark\" . Learn more about interpolation here . In general, prepend ocurrences of $ in your string literals with a \\ Usage of == operator actually calls the equals method. Most of times this is fine but can be a problem when you are overriding equals in your class and make use of == . This will introduce a recursive call in your implementation and may degenerate in a stack overflow. If possible, use the === operator or the is method in these cases", "title": "Limitations of code added \"on the fly\""}, {"location": "janssen-server/developer/agama/jans-agama-engine/#oop-prose-warning", "text": "See the recommended practices to learn more about this topic.", "title": "OOP prose warning"}, {"location": "janssen-server/developer/agama/native-applications/", "tags": ["developer", "agama", "native apps", "challenge endpoint"], "text": "Agama flows in native applications # Agama is a framework primarily focused on web flows, however, with the Authorization Challenge endpoint of Jans Server, developers can now run their flows outside the browser. This makes possible to offer secure, multi-step authentication flows from desktop and mobile applications without resorting to mechanisms like Web Views that substantially degrade the user experience. Additionally, the same already-familiar tools for authoring and deploying Agama projects can be used for the job. Moreover, the flows built for the web can be run in the native world without modification, requiring only to code the respective native UI and the logic that interacts with the Authorization Challenge endpoint, called \"the endpoint\" hereafter. In this document, we present an overview of how the endpoint works to make your Agama flows run without a web browser. Preliminar acquaintance with the following topics is recommended: Agama DSL and .gama format Agama projects deployment in the Janssen Server Execution rules in the Jans Agama engine A basic understanding of OAuth 2.0 for First-Party Applications How do flows actually run? # Before getting into the technicalities, let's cover some key preliminar concepts. The engine - the piece of software that actually runs flows - is eminently driven by HTTP requests. This is unsurprising because the main \"consumers\" of the engine are web browsers. When targetting native apps, the engine remains the same, and flows still run at the server side. This means native apps won't hold any business logic, or make computations of significance. The RRF (render-reply-fetch) Agama instruction is of paramount importance in flows. In a regular web setting, it involves three steps: Injecting some data to a UI template in order to generate HTML markup. This is known as rendering Reply the markup to the web browser - this will display a web page At the server side, retrieve data the user may have provided in his interaction with the page. This is, fetch In a native setting no HTML markup is suppossed to be generated and replied - it's the app that is in charge of displaying the UI now. For this purpose, it will receive (from the endpoint) the data that would be originally injected into the template. Most of times, this will carry information gathered at earlier stages of the flow and that is relevant to properly show or update the UI. Likewise, the \"data submission\" for the fetch phase of RRF is performed by the app too. In this case, the relevant data grabbed from the user interaction is sent to the server side (via challenge endpoint) and becomes the result of the RRF (the value for the variable on the left-hand side of the instruction). Note both the input (\"injected\" data) and the output (result) is specified in JSON format. Once the fetch occurs, the flow proceeds its execution until another RRF instruction is hit, where the procedure described above takes place again. Note this approach has two big benefits: Regular web flows can be reused in the native world without modifications The mindset for flows design remain the same There is a subtle exception regarding the first statement and has to do with flows containing RFAC instructions. RFAC is used to redirect to external sites, and as such, it requires a web browser. In the case of native apps, flows will crash once an RFAC instruction is hit. Inversion of control in apps # The above concepts bring an important constraint to app design that should be accounted before undertaking any project: control is inverted. Normally, an app \"knows\" exactly what to do at each step of its workflow, and eventually delegates data retrieval tasks to the server side. When using the endpoint, the server side drives the logic: the app does not \"take decisions\" and instead \"reacts\" to the received data. This will be demostrated later through a practical example. About the example: OTP via e-mail # To avoid a rather abstract explanation, we'll use an example to illustrate the steps required to run a flow from a native app. Suppose an authentication flow operating in the following manner: A username is prompted If the corresponding user has no e-mail associated to his account, the flow ends with an error message If the user has exactly one e-mail in his profile, a random one-time passcode (OTP) is sent to his registered address If the user has more than one e-mail, a screen is shown to pick the address where he would like the OTP be sent to The user is prompted to enter the passcode sent. If supplied correctly, the flow ends and the user is authenticated, otherwise the flow ends with an error This hypothetical flow is simple but will give you a good idea on how to interact with the endpoint. The flow code # The below depicts the implementation: Flow co.acme.flows.emailOtp is self-explanatory and does not require further insight. Note the templates referenced in RRF directives don't necessarily have to exist, however, the template names will be included in the output of the endpoint as the flow executes. This serves as a hint or reference for the app to know the current point of execution and determine what should be shown in the UI. It will be more clearly seen in the next section. Running the flow # Requisites # To be able to run an Agama flow from a native app using the endpoint, it is required to register an OAuth Client in the Jans server with at least the authorization_challenge scope. The process of client registration is beyond the scope of this document. All HTTP requests exemplified here make use of curl . Ensure this tool is familiar to you. Workflow # Requests to the endpoint are all issued to the URL https://<jans-hostname>/jans-auth/restv1/authorize-challenge using the POST verb. Responses will contain JSON content whose structure will vary depending on the result of the operation as we will see. Once the first request is sent, the flow will start and all instructions will be executed until an RRF is found. Here the flow will be paused, and the endpoint will respond with the data that was passed to RRF: the template path and the \"injected\" data. Let's start issuing real requests now. Initial request # In the first request, at least the following parameters must be passed: Name Value acr_values agama_challenge use_auth_session true client_id The client identifier of a previously registered client flow_name The qualified name of the flow to launch So in our example, it may look like: curl -i -d acr_values=agama_challenge -d use_auth_session=true -d flow_name=co.acme.flows.emailOtp -d client_id=<client-id> https://<jans-hostname>/jans-auth/restv1/authorize-challenge Note This command, as all others following has been split into several lines for better readability. The response will look like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"username-prompt.ftl\" }, \"auth_session\": \"BmAiCeArLdAa0\", } While this may look like something wrong happened, it is not really the case. This is derived from the spec the endpoint adheres to, where the authorization server must report every intermediate response as an error with a 401 status code. The value of the error property references a section that contains the template path. Here it corresponds to the first RRF instruction reached in the execution (line 4 in the flow's code). Particularly this RRF was not invoked passing two parameters, so there is only one property inside the flow_paused JSON object. Note the presence of auth_session . This value allows the authorization server to associate subsequent requests issued by the app with this specific flow execution. Based on this response, the app should render UI elements in order to capture the username. Here, username-prompt.ftl serves as a hint for the app to know the point of execution the flow is at currently. Subsequent requests # From here onwards, requests must contain the following parameters: Name Value use_auth_session true auth_session The value obtained in the previous request data A JSON object value which will become the result of the RRF instruction the flow is paused at Note Whenever a request is missing the auth_session param, it is assumed the inital request is being attempted. Let's assume the user entered Joan as username in the app. A request like the below can then be issued so the variable obj at line 4 is assigned a value: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"username\": \"Joan\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge This will make the flow advance until the next RRF is reached. Suppose the user Joan was found to have two e-mail addresses: joan@doe.com and joan@deere.com . This will make the flow hit line 23. The response will look as follows: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"email-prompt.ftl\", \"addresses\": [ \"joan@doe.com\", \"joan@deere.com\" ] }, \"auth_session\": \"BmAiCeArLdAa0\", } Note the flow_paused section has the contents of the object prepared in line 22. Based on this response, now the app should show a selection list for the user to pick one of these addresses. Once the selection is made, a new request can be issued: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"email\": \"joan@doe.com\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge The flow will continue and the hypothetical message will be sent to joan@doe.com (line 28). Then the next RRF is reached (line 32) and we get as response: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"passcode-prompt.ftl\" }, \"auth_session\": \"BmAiCeArLdAa0\", } The app must now update the UI so the passcode is prompted. When ready, a new request comes: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"otp\": \"123456\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge Assuming the entered code (123456) was correct, the response would look like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_finished\", \"flow_finished\": { \"data\": { \"userId\": \"Joan\" }, \"success\": true }, \"auth_session\": \"efb10525-6c43-4e50-88ab-92461c258526\" } This means we have hit line 37. When a Finish instruction is reached it is fully executed and the error reported in the response changes to flow_finished . What is left now is binding the user identified by userId (Joan) to the authorization request we have been handling ( BmAiCeArLdAa0 ). This is how the user actually gets authenticated. Final request # To authenticate the user, we issue one last request: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true https://<jans-hostname>/jans-auth/restv1/authorize-challenge Note parameter data is not needed. As response we obtain: HTTP/1.1 200 OK Content-Type: application/json ... { \"authorization_code\" : \"SplxlOBeZQQYbYS6WxSbIA\" } Once an authorization code has been obtained, the app can request an access token. This topic is beyond the scope of this document. At this point, the app can update the UI giving the user access to the actual app contents. No more requests are expected to be received by the endpoint with the given auth_session value. Understanding errors # So far we have been following the \"happy\" path in the example flow where all assumptions are met. This is unrealistic so here we offer an overview of how the endpoint behaves when abnormal conditions come up. Note In this section, we stick to the terminology found here . Missing parameters # Assume the following request is issued: curl -i -d use_auth_session=true -d acr_values=agama_challenge -d client_id=<client-id> https://<jans-hostname>/jans-auth/restv1/authorize-challenge This lacks the name of the flow to launch. The response is: HTTP/1.1 400 Bad Request Content-Type: application/json ... { \"error\": \"missing_param\", \"missing_param\": { \"description\": \"Parameter 'flow_name' missing in request\" } } Failed flows # Many times, flows simply fail as a way to reject access. This is achived in Agama by using code like: obj = { success: false, error: \"You are too suspicious\" } Finish obj In this case, the response looks like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_finished\", \"flow_finished\": { \"success\": false, \"error\": \"You are too suspicious\" } } Note auth_session is not replied. As such, no more requests to the endpoint should be made passing the auth_session value obtained earlier. Engine errors # There are several conditions under which the engine produces errors. In these cases, the HTTP error emitted by the engine is included in the endpoint response. As in previous error scenarios, no auth_session is replied. Flow timeout # With native apps, timeout of flows obeys the same rules of the web scenario. The only difference is the server property employed for the timeout calculation, namely, authorizationChallengeSessionLifetimeInSeconds . If absent, it defaults to one day. Here is how a flow timeout is reported: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"message\": \"You have exceeded the amount of time required to complete your authentication\", \"timeout\": true }, \"contentType\": \"application/json\", \"status\": 410 } } Crashed flow # When a flow crashes, the error is reported in similar way the timeout is reported. Here are some examples: An attempt to access a property or index of a null variable in Agama code HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"TypeError: Cannot read property \\\"x\\\" from null\" }, \"contentType\": \"application/json\", \"status\": 500 } } A variable does not meet the expected shape for a given Agama directive HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"TypeError: Data passed to RRF was not a map or Java equivalent\" }, \"contentType\": \"application/json\", \"status\": 500 } } Indexing a string in Java beyond length HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"String index out of range: 100\" }, \"contentType\": \"application/json\", \"status\": 500 } } Other errors # There are a variety of miscelaneous errors. Here we describe the most common. Finished flows with problems of user identification # When a Finish instruction does not include a reference to a user identifier, or if the referenced user does not exist, the endpoint responds like: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"unexpected_error\", \"unexpected_error\": { \"description\": \"Unable to determine identity of user\" } } Attempt to launch an unknown flow # If the initial request references an inexisting flow or one that has been flagged as not launchable directly by clients. HTTP/1.1 500 Server Error Content-Type: application/json ... { \"unexpected_error\": {\"description\": \"Flow ... does not exist or cannot be launched an application\"}, \"error\": \"unexpected_error\" } Agama is disabled # If the Agama engine is disabled, the following is generated upon the first request: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"unexpected_error\", \"unexpected_error\": { \"description\": \"Agama engine is disabled\" } }", "title": "Agama flows in native applications"}, {"location": "janssen-server/developer/agama/native-applications/#agama-flows-in-native-applications", "text": "Agama is a framework primarily focused on web flows, however, with the Authorization Challenge endpoint of Jans Server, developers can now run their flows outside the browser. This makes possible to offer secure, multi-step authentication flows from desktop and mobile applications without resorting to mechanisms like Web Views that substantially degrade the user experience. Additionally, the same already-familiar tools for authoring and deploying Agama projects can be used for the job. Moreover, the flows built for the web can be run in the native world without modification, requiring only to code the respective native UI and the logic that interacts with the Authorization Challenge endpoint, called \"the endpoint\" hereafter. In this document, we present an overview of how the endpoint works to make your Agama flows run without a web browser. Preliminar acquaintance with the following topics is recommended: Agama DSL and .gama format Agama projects deployment in the Janssen Server Execution rules in the Jans Agama engine A basic understanding of OAuth 2.0 for First-Party Applications", "title": "Agama flows in native applications"}, {"location": "janssen-server/developer/agama/native-applications/#how-do-flows-actually-run", "text": "Before getting into the technicalities, let's cover some key preliminar concepts. The engine - the piece of software that actually runs flows - is eminently driven by HTTP requests. This is unsurprising because the main \"consumers\" of the engine are web browsers. When targetting native apps, the engine remains the same, and flows still run at the server side. This means native apps won't hold any business logic, or make computations of significance. The RRF (render-reply-fetch) Agama instruction is of paramount importance in flows. In a regular web setting, it involves three steps: Injecting some data to a UI template in order to generate HTML markup. This is known as rendering Reply the markup to the web browser - this will display a web page At the server side, retrieve data the user may have provided in his interaction with the page. This is, fetch In a native setting no HTML markup is suppossed to be generated and replied - it's the app that is in charge of displaying the UI now. For this purpose, it will receive (from the endpoint) the data that would be originally injected into the template. Most of times, this will carry information gathered at earlier stages of the flow and that is relevant to properly show or update the UI. Likewise, the \"data submission\" for the fetch phase of RRF is performed by the app too. In this case, the relevant data grabbed from the user interaction is sent to the server side (via challenge endpoint) and becomes the result of the RRF (the value for the variable on the left-hand side of the instruction). Note both the input (\"injected\" data) and the output (result) is specified in JSON format. Once the fetch occurs, the flow proceeds its execution until another RRF instruction is hit, where the procedure described above takes place again. Note this approach has two big benefits: Regular web flows can be reused in the native world without modifications The mindset for flows design remain the same There is a subtle exception regarding the first statement and has to do with flows containing RFAC instructions. RFAC is used to redirect to external sites, and as such, it requires a web browser. In the case of native apps, flows will crash once an RFAC instruction is hit.", "title": "How do flows actually run?"}, {"location": "janssen-server/developer/agama/native-applications/#inversion-of-control-in-apps", "text": "The above concepts bring an important constraint to app design that should be accounted before undertaking any project: control is inverted. Normally, an app \"knows\" exactly what to do at each step of its workflow, and eventually delegates data retrieval tasks to the server side. When using the endpoint, the server side drives the logic: the app does not \"take decisions\" and instead \"reacts\" to the received data. This will be demostrated later through a practical example.", "title": "Inversion of control in apps"}, {"location": "janssen-server/developer/agama/native-applications/#about-the-example-otp-via-e-mail", "text": "To avoid a rather abstract explanation, we'll use an example to illustrate the steps required to run a flow from a native app. Suppose an authentication flow operating in the following manner: A username is prompted If the corresponding user has no e-mail associated to his account, the flow ends with an error message If the user has exactly one e-mail in his profile, a random one-time passcode (OTP) is sent to his registered address If the user has more than one e-mail, a screen is shown to pick the address where he would like the OTP be sent to The user is prompted to enter the passcode sent. If supplied correctly, the flow ends and the user is authenticated, otherwise the flow ends with an error This hypothetical flow is simple but will give you a good idea on how to interact with the endpoint.", "title": "About the example: OTP via e-mail"}, {"location": "janssen-server/developer/agama/native-applications/#the-flow-code", "text": "The below depicts the implementation: Flow co.acme.flows.emailOtp is self-explanatory and does not require further insight. Note the templates referenced in RRF directives don't necessarily have to exist, however, the template names will be included in the output of the endpoint as the flow executes. This serves as a hint or reference for the app to know the current point of execution and determine what should be shown in the UI. It will be more clearly seen in the next section.", "title": "The flow code"}, {"location": "janssen-server/developer/agama/native-applications/#running-the-flow", "text": "", "title": "Running the flow"}, {"location": "janssen-server/developer/agama/native-applications/#requisites", "text": "To be able to run an Agama flow from a native app using the endpoint, it is required to register an OAuth Client in the Jans server with at least the authorization_challenge scope. The process of client registration is beyond the scope of this document. All HTTP requests exemplified here make use of curl . Ensure this tool is familiar to you.", "title": "Requisites"}, {"location": "janssen-server/developer/agama/native-applications/#workflow", "text": "Requests to the endpoint are all issued to the URL https://<jans-hostname>/jans-auth/restv1/authorize-challenge using the POST verb. Responses will contain JSON content whose structure will vary depending on the result of the operation as we will see. Once the first request is sent, the flow will start and all instructions will be executed until an RRF is found. Here the flow will be paused, and the endpoint will respond with the data that was passed to RRF: the template path and the \"injected\" data. Let's start issuing real requests now.", "title": "Workflow"}, {"location": "janssen-server/developer/agama/native-applications/#initial-request", "text": "In the first request, at least the following parameters must be passed: Name Value acr_values agama_challenge use_auth_session true client_id The client identifier of a previously registered client flow_name The qualified name of the flow to launch So in our example, it may look like: curl -i -d acr_values=agama_challenge -d use_auth_session=true -d flow_name=co.acme.flows.emailOtp -d client_id=<client-id> https://<jans-hostname>/jans-auth/restv1/authorize-challenge Note This command, as all others following has been split into several lines for better readability. The response will look like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"username-prompt.ftl\" }, \"auth_session\": \"BmAiCeArLdAa0\", } While this may look like something wrong happened, it is not really the case. This is derived from the spec the endpoint adheres to, where the authorization server must report every intermediate response as an error with a 401 status code. The value of the error property references a section that contains the template path. Here it corresponds to the first RRF instruction reached in the execution (line 4 in the flow's code). Particularly this RRF was not invoked passing two parameters, so there is only one property inside the flow_paused JSON object. Note the presence of auth_session . This value allows the authorization server to associate subsequent requests issued by the app with this specific flow execution. Based on this response, the app should render UI elements in order to capture the username. Here, username-prompt.ftl serves as a hint for the app to know the point of execution the flow is at currently.", "title": "Initial request"}, {"location": "janssen-server/developer/agama/native-applications/#subsequent-requests", "text": "From here onwards, requests must contain the following parameters: Name Value use_auth_session true auth_session The value obtained in the previous request data A JSON object value which will become the result of the RRF instruction the flow is paused at Note Whenever a request is missing the auth_session param, it is assumed the inital request is being attempted. Let's assume the user entered Joan as username in the app. A request like the below can then be issued so the variable obj at line 4 is assigned a value: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"username\": \"Joan\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge This will make the flow advance until the next RRF is reached. Suppose the user Joan was found to have two e-mail addresses: joan@doe.com and joan@deere.com . This will make the flow hit line 23. The response will look as follows: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"email-prompt.ftl\", \"addresses\": [ \"joan@doe.com\", \"joan@deere.com\" ] }, \"auth_session\": \"BmAiCeArLdAa0\", } Note the flow_paused section has the contents of the object prepared in line 22. Based on this response, now the app should show a selection list for the user to pick one of these addresses. Once the selection is made, a new request can be issued: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"email\": \"joan@doe.com\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge The flow will continue and the hypothetical message will be sent to joan@doe.com (line 28). Then the next RRF is reached (line 32) and we get as response: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_paused\" \"flow_paused\": { \"_template\": \"passcode-prompt.ftl\" }, \"auth_session\": \"BmAiCeArLdAa0\", } The app must now update the UI so the passcode is prompted. When ready, a new request comes: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true --data-urlencode data='{ \"otp\": \"123456\" }' https://<jans-hostname>/jans-auth/restv1/authorize-challenge Assuming the entered code (123456) was correct, the response would look like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_finished\", \"flow_finished\": { \"data\": { \"userId\": \"Joan\" }, \"success\": true }, \"auth_session\": \"efb10525-6c43-4e50-88ab-92461c258526\" } This means we have hit line 37. When a Finish instruction is reached it is fully executed and the error reported in the response changes to flow_finished . What is left now is binding the user identified by userId (Joan) to the authorization request we have been handling ( BmAiCeArLdAa0 ). This is how the user actually gets authenticated.", "title": "Subsequent requests"}, {"location": "janssen-server/developer/agama/native-applications/#final-request", "text": "To authenticate the user, we issue one last request: curl -i -d auth_session=BmAiCeArLdAa0 -d use_auth_session=true https://<jans-hostname>/jans-auth/restv1/authorize-challenge Note parameter data is not needed. As response we obtain: HTTP/1.1 200 OK Content-Type: application/json ... { \"authorization_code\" : \"SplxlOBeZQQYbYS6WxSbIA\" } Once an authorization code has been obtained, the app can request an access token. This topic is beyond the scope of this document. At this point, the app can update the UI giving the user access to the actual app contents. No more requests are expected to be received by the endpoint with the given auth_session value.", "title": "Final request"}, {"location": "janssen-server/developer/agama/native-applications/#understanding-errors", "text": "So far we have been following the \"happy\" path in the example flow where all assumptions are met. This is unrealistic so here we offer an overview of how the endpoint behaves when abnormal conditions come up. Note In this section, we stick to the terminology found here .", "title": "Understanding errors"}, {"location": "janssen-server/developer/agama/native-applications/#missing-parameters", "text": "Assume the following request is issued: curl -i -d use_auth_session=true -d acr_values=agama_challenge -d client_id=<client-id> https://<jans-hostname>/jans-auth/restv1/authorize-challenge This lacks the name of the flow to launch. The response is: HTTP/1.1 400 Bad Request Content-Type: application/json ... { \"error\": \"missing_param\", \"missing_param\": { \"description\": \"Parameter 'flow_name' missing in request\" } }", "title": "Missing parameters"}, {"location": "janssen-server/developer/agama/native-applications/#failed-flows", "text": "Many times, flows simply fail as a way to reject access. This is achived in Agama by using code like: obj = { success: false, error: \"You are too suspicious\" } Finish obj In this case, the response looks like: HTTP/1.1 401 Unauthorized Content-Type: application/json ... { \"error\": \"flow_finished\", \"flow_finished\": { \"success\": false, \"error\": \"You are too suspicious\" } } Note auth_session is not replied. As such, no more requests to the endpoint should be made passing the auth_session value obtained earlier.", "title": "Failed flows"}, {"location": "janssen-server/developer/agama/native-applications/#engine-errors", "text": "There are several conditions under which the engine produces errors. In these cases, the HTTP error emitted by the engine is included in the endpoint response. As in previous error scenarios, no auth_session is replied.", "title": "Engine errors"}, {"location": "janssen-server/developer/agama/native-applications/#flow-timeout", "text": "With native apps, timeout of flows obeys the same rules of the web scenario. The only difference is the server property employed for the timeout calculation, namely, authorizationChallengeSessionLifetimeInSeconds . If absent, it defaults to one day. Here is how a flow timeout is reported: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"message\": \"You have exceeded the amount of time required to complete your authentication\", \"timeout\": true }, \"contentType\": \"application/json\", \"status\": 410 } }", "title": "Flow timeout"}, {"location": "janssen-server/developer/agama/native-applications/#crashed-flow", "text": "When a flow crashes, the error is reported in similar way the timeout is reported. Here are some examples: An attempt to access a property or index of a null variable in Agama code HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"TypeError: Cannot read property \\\"x\\\" from null\" }, \"contentType\": \"application/json\", \"status\": 500 } } A variable does not meet the expected shape for a given Agama directive HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"TypeError: Data passed to RRF was not a map or Java equivalent\" }, \"contentType\": \"application/json\", \"status\": 500 } } Indexing a string in Java beyond length HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"engine_error\", \"engine_error\": { \"description\": \"Unexpected response to https://<jans-hostname>/jans-auth/fl/...\", \"body\": { \"title\": \"An unexpected error ocurred\", \"message\": \"String index out of range: 100\" }, \"contentType\": \"application/json\", \"status\": 500 } }", "title": "Crashed flow"}, {"location": "janssen-server/developer/agama/native-applications/#other-errors", "text": "There are a variety of miscelaneous errors. Here we describe the most common.", "title": "Other errors"}, {"location": "janssen-server/developer/agama/native-applications/#finished-flows-with-problems-of-user-identification", "text": "When a Finish instruction does not include a reference to a user identifier, or if the referenced user does not exist, the endpoint responds like: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"unexpected_error\", \"unexpected_error\": { \"description\": \"Unable to determine identity of user\" } }", "title": "Finished flows with problems of user identification"}, {"location": "janssen-server/developer/agama/native-applications/#attempt-to-launch-an-unknown-flow", "text": "If the initial request references an inexisting flow or one that has been flagged as not launchable directly by clients. HTTP/1.1 500 Server Error Content-Type: application/json ... { \"unexpected_error\": {\"description\": \"Flow ... does not exist or cannot be launched an application\"}, \"error\": \"unexpected_error\" }", "title": "Attempt to launch an unknown flow"}, {"location": "janssen-server/developer/agama/native-applications/#agama-is-disabled", "text": "If the Agama engine is disabled, the following is generated upon the first request: HTTP/1.1 500 Server Error Content-Type: application/json ... { \"error\": \"unexpected_error\", \"unexpected_error\": { \"description\": \"Agama engine is disabled\" } }", "title": "Agama is disabled"}, {"location": "janssen-server/developer/agama/projects-deployment/", "tags": ["administration", "developer", "agama"], "text": "Agama projects deployment # The Agama framework defines a file format to package and distribute Agama projects. Here we describe the process of deployment in the Jans Agama engine. Workflow # Deployment occurs through a REST API. Here is a typical workflow once a .gama file is ready: Send (POST) the archive contents to the deployment endpoint. Normally a 202 response should be obtained meaning a task has been queued for processing Poll (via GET) the status of the deployment. When the archive has been effectively deployed a status of 200 should be obtained. It may take up to 30 seconds for the process to complete once the archive is sent. This time may extend if there is another deployment in course Optionally supply configuration properties for flows if needed. This is done via PUT to the /configs endpoint. The response of the previous step may contain descriptive/sample configurations that can be used as a guide Test the deployed flows and adjust the archive for any changes required Go to point 1 if needed. If configuration properties were previously set and no changes are required in this regard, step 3 can be skipped If desired, a request can be sent to undeploy the flows (via DELETE) The following tables summarize the available endpoints. All URLs are relative to /jans-config-api/api/v1 . An OpenAPI document is also available here . Endpoint -> /agama-deployment Purpose Retrieve a list of deployments in the server. This is not a search, just a paged listing Method GET Query params start and count helps paginating results. start is 0-index based. Both params optional Output Existing deployments (regardless they are thoroughly processed or still being deployed). They are listed and sorted by deployment date Sample output {\"start\":...,\"totalEntriesCount\":...,\"entriesCount\":...,\"entries\":[ ... ]} Status 200 (OK) Endpoint -> /agama-deployment/{name} Purpose Retrieve details of a single deployment by name Method GET Path params name Sample output The structure of a deployment is explained below Status 200 (deployment task is finished), 204 (task still in course), 404 (project unknown) Deployment structure Notes Example dn Distinguished name jansId=123,ou=deployments,ou=agama,o=jans id Identifier of deployment (generated automatically) 115276 createdAt Datetime (in UTC) of the instant the deployment task was created (POSTed) 2022-12-07T21:47:42 taskActive Boolean value indicating if the deployment task is being currently processed, ie. the gama file is being scanned, flows analysed, etc. false finishedAt Datetime (in UTC) representing the instant when the deployment task was finished, or null if it hasn't ended 2022-12-07T21:48:42 details Extra details, see below Deployment details structure Notes Example projectMetadata Includes author, type, description, project's name, and example configuration - as supplied when the deployment task was created error A general description of the error (if presented) when processing the task, otherwise null Archive missing web and/or code subdirectories flowsError A mapping of the errors obtained per flow found in the archive. The keys correspond to qualified names. A null value indicates the flow was successfully added { \"co.acme.example\": \"Syntax error on line 4\", \"io.jans.test\": null } libs A listing of paths to java , groovy , or jar files included in the project archive Endpoint -> /agama-deployment/{name} Purpose Add or replace an Agama project to the server Method POST Path params name (the project's name) Body The binary contents of a .gama file; example here . Ensure to use header Content-Type: application/zip Query params autoconfigure - passing true will make this project be configured with the sample configurations found in the provided binary archive ( configs section of project.json ). This param should rarely be passed: use only in controlled environments where the archive is not shared with third parties Output Textual explanation, e.g. A deployment task for project XXX has been queued. Use the GET endpoint to poll status Status 202 (the task was created and scheduled for deployment), 409 (there is a task already for this project and it hasn't finished yet), 400 (a param is missing) Endpoint -> /agama-deployment/configs/{name} Purpose Retrieve the configurations associated to flows that belong to the project of interest. The project must have been already processed fully Method GET Path params name (the project's name) Output A JSON object whose properties are flow names and values correspond to configuration properties defined (JSON objects too) Status 200 (successful response), 204 (this project is still in course of deployment), 404 (unknown project) Endpoint -> /agama-deployment/configs/{name} Purpose Set or replace the configurations associated to flows that belong to the project of interest. The project must have been already processed fully Method PUT Path params name (the project's name) Body JSON payload Output A JSON object whose properties are flow names and values correspond to a boolean indicating the success of the update for the given flow Status 200 (successful response), 204 (this project is still in course of deployment), 404 (unknown project), 400 (a param is missing) Endpoint -> /agama-deployment/{name} Purpose Undeploy an Agama project from the server. Entails removing flows and assets initally supplied Method DELETE Path params name (the project's name) Status 204 (scheduled for removal), 409 (the project is being deployed currently), 404 (unknown project) Endpoints access # API operations are protected by Oauth2 scopes this way: GET: https://jans.io/oauth/config/agama.readonly POST: https://jans.io/oauth/config/agama.write DELETE: https://jans.io/oauth/config/agama.delete Internals of deployment # This section offers details on how the server deploys a .gama file. In summary five steps take place once the deployment task is picked up: Input payload validation Flows transpilation Transfer of libraries Transfer of assets and source files Task finalization After the initial validation of structure takes place, the code directory is scanned for flow files and every flow is transpiled and added to the database if its transpilation was successful. Next, jar files found are transferred to the server's custom libs directory - this only applies for VM-based installations. Then a transfer of templates and assets from web directory followed by copying Groovy/Java sources (from lib ) takes place. Finally the deployment task is marked as finalized and a status summary saved to database for later retrieval. Notes: Developers are required to restart the authentication server for the classes in jar files to be effectively picked up Steps 3 and 4 are carried out only if all flows passed transpilation successfully In Cloud Native environments only one node takes charge of processing a given deployment thoroughly. Other nodes will automatically sync with regards to the files of step 4. The API also offers undeployment capabilities. Here is how it works: Directories holding templates and assets are removed Source files and jar files are removed, if any Flows are removed from database The above applies only for the artifacts originally part of the deployment, of course. Again, nodes in Cloud Native installations will sync accordingly.", "title": "Projects deployment"}, {"location": "janssen-server/developer/agama/projects-deployment/#agama-projects-deployment", "text": "The Agama framework defines a file format to package and distribute Agama projects. Here we describe the process of deployment in the Jans Agama engine.", "title": "Agama projects deployment"}, {"location": "janssen-server/developer/agama/projects-deployment/#workflow", "text": "Deployment occurs through a REST API. Here is a typical workflow once a .gama file is ready: Send (POST) the archive contents to the deployment endpoint. Normally a 202 response should be obtained meaning a task has been queued for processing Poll (via GET) the status of the deployment. When the archive has been effectively deployed a status of 200 should be obtained. It may take up to 30 seconds for the process to complete once the archive is sent. This time may extend if there is another deployment in course Optionally supply configuration properties for flows if needed. This is done via PUT to the /configs endpoint. The response of the previous step may contain descriptive/sample configurations that can be used as a guide Test the deployed flows and adjust the archive for any changes required Go to point 1 if needed. If configuration properties were previously set and no changes are required in this regard, step 3 can be skipped If desired, a request can be sent to undeploy the flows (via DELETE) The following tables summarize the available endpoints. All URLs are relative to /jans-config-api/api/v1 . An OpenAPI document is also available here . Endpoint -> /agama-deployment Purpose Retrieve a list of deployments in the server. This is not a search, just a paged listing Method GET Query params start and count helps paginating results. start is 0-index based. Both params optional Output Existing deployments (regardless they are thoroughly processed or still being deployed). They are listed and sorted by deployment date Sample output {\"start\":...,\"totalEntriesCount\":...,\"entriesCount\":...,\"entries\":[ ... ]} Status 200 (OK) Endpoint -> /agama-deployment/{name} Purpose Retrieve details of a single deployment by name Method GET Path params name Sample output The structure of a deployment is explained below Status 200 (deployment task is finished), 204 (task still in course), 404 (project unknown) Deployment structure Notes Example dn Distinguished name jansId=123,ou=deployments,ou=agama,o=jans id Identifier of deployment (generated automatically) 115276 createdAt Datetime (in UTC) of the instant the deployment task was created (POSTed) 2022-12-07T21:47:42 taskActive Boolean value indicating if the deployment task is being currently processed, ie. the gama file is being scanned, flows analysed, etc. false finishedAt Datetime (in UTC) representing the instant when the deployment task was finished, or null if it hasn't ended 2022-12-07T21:48:42 details Extra details, see below Deployment details structure Notes Example projectMetadata Includes author, type, description, project's name, and example configuration - as supplied when the deployment task was created error A general description of the error (if presented) when processing the task, otherwise null Archive missing web and/or code subdirectories flowsError A mapping of the errors obtained per flow found in the archive. The keys correspond to qualified names. A null value indicates the flow was successfully added { \"co.acme.example\": \"Syntax error on line 4\", \"io.jans.test\": null } libs A listing of paths to java , groovy , or jar files included in the project archive Endpoint -> /agama-deployment/{name} Purpose Add or replace an Agama project to the server Method POST Path params name (the project's name) Body The binary contents of a .gama file; example here . Ensure to use header Content-Type: application/zip Query params autoconfigure - passing true will make this project be configured with the sample configurations found in the provided binary archive ( configs section of project.json ). This param should rarely be passed: use only in controlled environments where the archive is not shared with third parties Output Textual explanation, e.g. A deployment task for project XXX has been queued. Use the GET endpoint to poll status Status 202 (the task was created and scheduled for deployment), 409 (there is a task already for this project and it hasn't finished yet), 400 (a param is missing) Endpoint -> /agama-deployment/configs/{name} Purpose Retrieve the configurations associated to flows that belong to the project of interest. The project must have been already processed fully Method GET Path params name (the project's name) Output A JSON object whose properties are flow names and values correspond to configuration properties defined (JSON objects too) Status 200 (successful response), 204 (this project is still in course of deployment), 404 (unknown project) Endpoint -> /agama-deployment/configs/{name} Purpose Set or replace the configurations associated to flows that belong to the project of interest. The project must have been already processed fully Method PUT Path params name (the project's name) Body JSON payload Output A JSON object whose properties are flow names and values correspond to a boolean indicating the success of the update for the given flow Status 200 (successful response), 204 (this project is still in course of deployment), 404 (unknown project), 400 (a param is missing) Endpoint -> /agama-deployment/{name} Purpose Undeploy an Agama project from the server. Entails removing flows and assets initally supplied Method DELETE Path params name (the project's name) Status 204 (scheduled for removal), 409 (the project is being deployed currently), 404 (unknown project)", "title": "Workflow"}, {"location": "janssen-server/developer/agama/projects-deployment/#endpoints-access", "text": "API operations are protected by Oauth2 scopes this way: GET: https://jans.io/oauth/config/agama.readonly POST: https://jans.io/oauth/config/agama.write DELETE: https://jans.io/oauth/config/agama.delete", "title": "Endpoints access"}, {"location": "janssen-server/developer/agama/projects-deployment/#internals-of-deployment", "text": "This section offers details on how the server deploys a .gama file. In summary five steps take place once the deployment task is picked up: Input payload validation Flows transpilation Transfer of libraries Transfer of assets and source files Task finalization After the initial validation of structure takes place, the code directory is scanned for flow files and every flow is transpiled and added to the database if its transpilation was successful. Next, jar files found are transferred to the server's custom libs directory - this only applies for VM-based installations. Then a transfer of templates and assets from web directory followed by copying Groovy/Java sources (from lib ) takes place. Finally the deployment task is marked as finalized and a status summary saved to database for later retrieval. Notes: Developers are required to restart the authentication server for the classes in jar files to be effectively picked up Steps 3 and 4 are carried out only if all flows passed transpilation successfully In Cloud Native environments only one node takes charge of processing a given deployment thoroughly. Other nodes will automatically sync with regards to the files of step 4. The API also offers undeployment capabilities. Here is how it works: Directories holding templates and assets are removed Source files and jar files are removed, if any Flows are removed from database The above applies only for the artifacts originally part of the deployment, of course. Again, nodes in Cloud Native installations will sync accordingly.", "title": "Internals of deployment"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/", "tags": ["administration", "developer", "agama", "agama lab"], "text": "Quick Start Using Agama Lab # In this quick start guide, we will build, deploy and test a simple password-based authentication flow using Agama and Agama Lab . Agama Lab is an online visual editor to build authentication flows. A flow built on Agama Lab is packaged as a .gama project file. .gama package needs to be manually deployed on Janssen Server where the Agama engine will execute the flow when an authentication request is received. Major Steps involved in this process are: Create Agama project using Agama Lab Deploying .gama package on Janssen Server Testing the authentication flow This guide covers these steps in the following sections. Prerequisites # Janssen Server instance A public GitHub repository with at least one prior commit Create Agama Project # We will use Agama Lab to create a simple username-password based user authentication flow. This involves defining the authentication steps, designing the user interface to capture user inputs, and lastly, releasing the flow as an Agama project. Defining The Authentication Flow # Log Into Agama Lab # Go to Agama Lab login page. Authenticate on the GitHub authentication page. Input the name of the repository where Agama Lab should release the project artifacts. Click Next Project listing page will be shown. All the existing projects for your GitHub user are listed here. Projects can be created, edited, and deleted from the project listing page. Create A New Project # To create a new project, click on the New Project button on the project listing page above. Enter the name and the description for the new project and click the Create button. This will create a new project and it'll be listed on the project listing page. Create The Authentication Flow # Create A Flow File Click on The flow authoring view will open with a blank canvas. To start creating the flow, we need to create a Flow File . To do that, Right-click on code and then select New > Flow File Give name and description for the flow file and then click Create A newly created flow file has one block in it by default. Clicking on the block will allow you to add further blocks using or to edit the existing block using . Create AuthenticationService Call block Click on the block and then . Then select call A new Call block should appear with a link to Start block Click Call block and then click to open the configuration screen. Add configuration values as shown below. This will create a new instance of AuthenticationService class. This instance will be used to authenticate the user. The new instance will be stored in a variable called authService . Create CdiUtil Call block To perform authentication we will also need a bean instance of CdiUtil class. This bean instance takes AuthenticationService instance that we created in the previous step as an argument. Click the New Authentication Service block and then click on . Then click Call Click on the newly created Call block and by clicking open the configuration page. Input values as shown below in the configuration screen Create Assignment(s) block Next, we need to create an empty variable that the flow will use in the future to store authentication results. Click on New CdiUtil Object and then click . Select Assignment(s) Click on the newly created Assign block. Click . Input values as shown below in the configuration screen Create repeat block Repeat block represents the Repeat instruction of Agama DSL. Repeat block creates a loop to iterate over certain steps(blocks). We will create a repeat loop that allows 3 retries if the authentication fails. Click on the Result Object block and then click . Select Repeat . Click on the newly created Repeat block. Click . Input values as shown below in the configuration screen Create An RRF block RRF block represents the RRF instruction of Agama DSL. Click on the Repeat block. Click . Check the In Repeat Block and then click on RRF . Click on the newly created Repeat block. Click . Input values as shown below in the configuration screen Since we have checked the In Repeat Block at the time of adding the RRF block, the RRF block as well as all the blocks that we add to the RRF block iterated blocks. At this stage, let's save the flow. Click Save on the flow canvas. Create a CdiUtil Call block Create a Call block to process the username and password received from the user (in RRF) and validate them. The result of validation should be stored in a variable. Click on the RRF block. Click . Click on Call . Click on the newly created Call block. Click . Input values as shown below in the configuration screen Create An Assignment block In case of authentication failure, we want to show the username to the user while reentering the password on the web page. For this, we will save the username in a variable using the Assignment(s) block. Click on the Call block. Click . Click on Assignment(s) . Click on the newly created Call block. Click . Input values as shown below in the configuration screen Create A Conditional When block When block represents the When instruction of Agama DSL. Create a conditional check using the When block to check if the authentication (validated in validate credentials block) has been successful. Click on Assignment(s) block. Click . Click on When . Click on the newly created When block. Click . Input values as shown below in the configuration screen Create finish blocks The Finish block represents the Flow finish instruction of Agama DSL. If the authentication was successful then the flow should finish and return the username. This will be achieved by adding a Finish block to the When block. And if authentication fails after 3 attempts, we need another Finish block following the Repeat block. Click on the When block. Click . Click on Condition met and then click Finish Click on the newly created Finish block. Click . Input values as shown below in the configuration screen Click on the Repeat block. Click . Click Finish Click on the newly created Finish block. Click . Input values as shown below in the configuration screen and click Save . Save the flow using the Save button on flow canvas. The completed flow looks like below: Check Generated code Agama Lab flow gets translated in Agama DSL . Click the Code button to see the code generated by the flow. Flow co.acme.password Basepath \"\" authService = Call io.jans.as.server.service.AuthenticationService#class cdiUtil = Call io.jans.service.cdi.util.CdiUtil#bean authService authResult = {} Repeat 3 times max creds = RRF \"login.ftlh\" authResult authResult.success = Call cdiUtil authenticate creds.username creds.password authResult.uid = creds.username When authResult.success is true Finish authResult.uid Finish false Design User Interface # In the RRF configuration step, we mentioned login.ftlh to render the login page elements. We need to add login.ftlh to the Agama project so that the flow can use during the flow execution. Use the steps below to create the page. Create a template file On the left project explorer menu, click on web > New > Freemarker Template Select + Create under the New Blank Template Give Name and Description as shown below and click Create Use the visual editor This opens a visual editor to create a freemarker template. Use this visual editor to create a template as per the need. For this article, we will use the code below. Click Edit HTML . This opens a text editor. Remove existing code in the editor and paste the code shown below. <!doctype html> < html xmlns = \"http://www.w3.org/1999/xhtml\" > < head > < title > Jans Agama Basic Auth flow </ title > </ head > < body > < h2 > Welcome </ h2 > < hr /> [#if !(success!true)] < p class = \"fs-6 text-danger mb-3\" > ${msgs[\"login.errorMessage\"]} </ p > [/#if] < hr /> < form method = \"post\" enctype = \"application/x-www-form-urlencoded\" > < div > Username: < input type = \"text\" class = \"form-control\" name = \"username\" id = \"username\" value = \"${uid!}\" required > </ div > < div > Password: < input type = \"password\" class = \"form-control\" id = \"password\" name = \"password\" > </ div > < div > < input type = \"submit\" class = \"btn btn-success px-4\" value = \"Login\" > </ div > </ form > </ body > < style > input { border : 1 px solid #000000 ; } </ style > </ html > Click Save changes This will render the page in the visual editor . Release The Project # To use the flow for authentication in the Janssen Server, the flow needs to be released. Agama Lab releases the flow and the related artifacts (like template) in the form of a .gama file in the GitHub repository. To release the project, click on any of the files in the left project explorer, and click Release Project . Enter a desired version number and click Save Upon successful release, Agama Lab Releases dashboard is shown. It lists all projects that are released. Click on the project name to go to the GitHub repository release page where .gama file has been released Download the .gama file from here to deploy on to the Janssen Server. Deploy Agama Project # Note Please ensure that Agama engine and scripts are enabled in Janssen Server deployment Download the .gama file from the GitHub repository Open TUI using following commands on Janssen Server Command jans tui Navigate to Auth Server > Agama > Upload Project . Select the .gama file to upload. Test # Setup Janssen Tent Change the configuration as given below in config.py ACR_VALUES = \"agama_co.acme.password.flow\" Run the Tent test by accessing it via the browser", "title": "Quick Start Using Agama Lab"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#quick-start-using-agama-lab", "text": "In this quick start guide, we will build, deploy and test a simple password-based authentication flow using Agama and Agama Lab . Agama Lab is an online visual editor to build authentication flows. A flow built on Agama Lab is packaged as a .gama project file. .gama package needs to be manually deployed on Janssen Server where the Agama engine will execute the flow when an authentication request is received. Major Steps involved in this process are: Create Agama project using Agama Lab Deploying .gama package on Janssen Server Testing the authentication flow This guide covers these steps in the following sections.", "title": "Quick Start Using Agama Lab"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#prerequisites", "text": "Janssen Server instance A public GitHub repository with at least one prior commit", "title": "Prerequisites"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#create-agama-project", "text": "We will use Agama Lab to create a simple username-password based user authentication flow. This involves defining the authentication steps, designing the user interface to capture user inputs, and lastly, releasing the flow as an Agama project.", "title": "Create Agama Project"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#defining-the-authentication-flow", "text": "", "title": "Defining The Authentication Flow"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#log-into-agama-lab", "text": "Go to Agama Lab login page. Authenticate on the GitHub authentication page. Input the name of the repository where Agama Lab should release the project artifacts. Click Next Project listing page will be shown. All the existing projects for your GitHub user are listed here. Projects can be created, edited, and deleted from the project listing page.", "title": "Log Into Agama Lab"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#create-a-new-project", "text": "To create a new project, click on the New Project button on the project listing page above. Enter the name and the description for the new project and click the Create button. This will create a new project and it'll be listed on the project listing page.", "title": "Create A New Project"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#create-the-authentication-flow", "text": "Create A Flow File Click on The flow authoring view will open with a blank canvas. To start creating the flow, we need to create a Flow File . To do that, Right-click on code and then select New > Flow File Give name and description for the flow file and then click Create A newly created flow file has one block in it by default. Clicking on the block will allow you to add further blocks using or to edit the existing block using . Create AuthenticationService Call block Click on the block and then . Then select call A new Call block should appear with a link to Start block Click Call block and then click to open the configuration screen. Add configuration values as shown below. This will create a new instance of AuthenticationService class. This instance will be used to authenticate the user. The new instance will be stored in a variable called authService . Create CdiUtil Call block To perform authentication we will also need a bean instance of CdiUtil class. This bean instance takes AuthenticationService instance that we created in the previous step as an argument. Click the New Authentication Service block and then click on . Then click Call Click on the newly created Call block and by clicking open the configuration page. Input values as shown below in the configuration screen Create Assignment(s) block Next, we need to create an empty variable that the flow will use in the future to store authentication results. Click on New CdiUtil Object and then click . Select Assignment(s) Click on the newly created Assign block. Click . Input values as shown below in the configuration screen Create repeat block Repeat block represents the Repeat instruction of Agama DSL. Repeat block creates a loop to iterate over certain steps(blocks). We will create a repeat loop that allows 3 retries if the authentication fails. Click on the Result Object block and then click . Select Repeat . Click on the newly created Repeat block. Click . Input values as shown below in the configuration screen Create An RRF block RRF block represents the RRF instruction of Agama DSL. Click on the Repeat block. Click . Check the In Repeat Block and then click on RRF . Click on the newly created Repeat block. Click . Input values as shown below in the configuration screen Since we have checked the In Repeat Block at the time of adding the RRF block, the RRF block as well as all the blocks that we add to the RRF block iterated blocks. At this stage, let's save the flow. Click Save on the flow canvas. Create a CdiUtil Call block Create a Call block to process the username and password received from the user (in RRF) and validate them. The result of validation should be stored in a variable. Click on the RRF block. Click . Click on Call . Click on the newly created Call block. Click . Input values as shown below in the configuration screen Create An Assignment block In case of authentication failure, we want to show the username to the user while reentering the password on the web page. For this, we will save the username in a variable using the Assignment(s) block. Click on the Call block. Click . Click on Assignment(s) . Click on the newly created Call block. Click . Input values as shown below in the configuration screen Create A Conditional When block When block represents the When instruction of Agama DSL. Create a conditional check using the When block to check if the authentication (validated in validate credentials block) has been successful. Click on Assignment(s) block. Click . Click on When . Click on the newly created When block. Click . Input values as shown below in the configuration screen Create finish blocks The Finish block represents the Flow finish instruction of Agama DSL. If the authentication was successful then the flow should finish and return the username. This will be achieved by adding a Finish block to the When block. And if authentication fails after 3 attempts, we need another Finish block following the Repeat block. Click on the When block. Click . Click on Condition met and then click Finish Click on the newly created Finish block. Click . Input values as shown below in the configuration screen Click on the Repeat block. Click . Click Finish Click on the newly created Finish block. Click . Input values as shown below in the configuration screen and click Save . Save the flow using the Save button on flow canvas. The completed flow looks like below: Check Generated code Agama Lab flow gets translated in Agama DSL . Click the Code button to see the code generated by the flow. Flow co.acme.password Basepath \"\" authService = Call io.jans.as.server.service.AuthenticationService#class cdiUtil = Call io.jans.service.cdi.util.CdiUtil#bean authService authResult = {} Repeat 3 times max creds = RRF \"login.ftlh\" authResult authResult.success = Call cdiUtil authenticate creds.username creds.password authResult.uid = creds.username When authResult.success is true Finish authResult.uid Finish false", "title": "Create The Authentication Flow"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#design-user-interface", "text": "In the RRF configuration step, we mentioned login.ftlh to render the login page elements. We need to add login.ftlh to the Agama project so that the flow can use during the flow execution. Use the steps below to create the page. Create a template file On the left project explorer menu, click on web > New > Freemarker Template Select + Create under the New Blank Template Give Name and Description as shown below and click Create Use the visual editor This opens a visual editor to create a freemarker template. Use this visual editor to create a template as per the need. For this article, we will use the code below. Click Edit HTML . This opens a text editor. Remove existing code in the editor and paste the code shown below. <!doctype html> < html xmlns = \"http://www.w3.org/1999/xhtml\" > < head > < title > Jans Agama Basic Auth flow </ title > </ head > < body > < h2 > Welcome </ h2 > < hr /> [#if !(success!true)] < p class = \"fs-6 text-danger mb-3\" > ${msgs[\"login.errorMessage\"]} </ p > [/#if] < hr /> < form method = \"post\" enctype = \"application/x-www-form-urlencoded\" > < div > Username: < input type = \"text\" class = \"form-control\" name = \"username\" id = \"username\" value = \"${uid!}\" required > </ div > < div > Password: < input type = \"password\" class = \"form-control\" id = \"password\" name = \"password\" > </ div > < div > < input type = \"submit\" class = \"btn btn-success px-4\" value = \"Login\" > </ div > </ form > </ body > < style > input { border : 1 px solid #000000 ; } </ style > </ html > Click Save changes This will render the page in the visual editor .", "title": "Design User Interface"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#release-the-project", "text": "To use the flow for authentication in the Janssen Server, the flow needs to be released. Agama Lab releases the flow and the related artifacts (like template) in the form of a .gama file in the GitHub repository. To release the project, click on any of the files in the left project explorer, and click Release Project . Enter a desired version number and click Save Upon successful release, Agama Lab Releases dashboard is shown. It lists all projects that are released. Click on the project name to go to the GitHub repository release page where .gama file has been released Download the .gama file from here to deploy on to the Janssen Server.", "title": "Release The Project"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#deploy-agama-project", "text": "Note Please ensure that Agama engine and scripts are enabled in Janssen Server deployment Download the .gama file from the GitHub repository Open TUI using following commands on Janssen Server Command jans tui Navigate to Auth Server > Agama > Upload Project . Select the .gama file to upload.", "title": "Deploy Agama Project"}, {"location": "janssen-server/developer/agama/quick-start-using-agama-lab/#test", "text": "Setup Janssen Tent Change the configuration as given below in config.py ACR_VALUES = \"agama_co.acme.password.flow\" Run the Tent test by accessing it via the browser", "title": "Test"}, {"location": "janssen-server/developer/customization/custom-client-logs/", "tags": ["administration", "developer", "customization"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Custom client logs"}, {"location": "janssen-server/developer/customization/custom-client-logs/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/developer/customization/custom-client-logs/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/developer/customization/custom-client-logs/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/developer/customization/customize-web-pages/", "tags": ["administration", "developer", "customization", "internationalization", "i18n", "locale", "css", "images", "header", "footer", "template"], "text": "Customization Using Custom Assets # Janssen Server allows customization and extension of current web page designs, images, web templates etc. For example, extending the list of languages supported by Janssen Server or maybe customizing the login page to show the organization's logo and align styling to meet the branding of the organization. All of the above need some amount of custom assets, like custom CSS stylesheets, logo images, etc to be available on the Janssen Server. All these are called Custom Assets . Custom Assets Accepted by Module # Listing of custom asset types that each Janssen Server module accepts: Config-API # Path Asset Type /opt/jans/jetty/jans-config-api/custom/config *.xml /opt/jans/jetty/jans-config-api/custom/i18n *.properties /opt/jans/jetty/jans-config-api/custom/libs *.jar /opt/jans/jetty/jans-config-api/custom/pages *.xhtml /opt/jans/jetty/jans-config-api/custom/static .js, .css, .png, .gif, .jpg, .jpeg Auth-Server # Path Asset Type /opt/jans/jetty/jans-auth/custom/i18n *.properties /opt/jans/jetty/jans-auth/custom/libs *.jars /opt/jans/jetty/jans-auth/custom/pages *.xhtml /opt/jans/jetty/jans-auth/custom/static .js, .css, .png, .gif, .jpg, .jpeg /etc/certs/jans-auth-keys.pkcs12 *.pkcs12 Casa # Path Asset Type /opt/jans/jetty/jans-casa/plugins *.jar /opt/jans/jetty/jans-casa/static .js, .css, .png, .gif, .jpg, .jpeg Agama # Path Asset Type /opt/jans/jetty/jans-auth/agama engine templates /opt/jans/jetty/jans-auth/agama/fl .js, .css, .png, .gif, .jpg, .jpeg /opt/jans/jetty/jans-auth/agama/ftl .ftl, .ftlh /opt/jans/jetty/jans-auth/agama/scripts .java .groovy, .gvy, .gy, *.gsh Fido2 # Path Asset Type /etc/jans/conf/fido2/authenticator_cert .pem, .crt /etc/jans/conf/fido2/mds/cert *.crt /etc/jans/conf/fido2/mds/toc *.jwt /etc/jans/conf/fido2/server_metadata *.json Lock # Path Asset Type /opt/jans/jetty/jans-lock/custom-libs *.jar KeyCloak-link # Path Asset Type /opt/jans/jetty/jans-keycloak-link/custom/libs/ *.jar /var/jans/keycloak-link-snapshots/ *.txt Link # Path Asset Type /opt/jans/jetty/jans-link/custom-libs *.jar /var/jans/link-snapshots/ *.txt Managing Custom Assets # Janssen Server configuration tools like CLI and TUI provide the ability to add, update, and delete custom assets. Refer to the custom assets configuration guide to learn how to manage custom assets. Customizing Web Pages # Janssen Server uses xhtml pages to render the web interface needed in interactive web-flows. For example, password authentication flow. It is possible to override the built-in xhtml pages or to add completely new pages. Customizing Built-in Web Pages # In order to customize built-in web pages, follow the steps below: Create a new xhtml page as a copy of the relevant built-in xhtml page Make changes to the code of the new page according to the need Override the built-in page with the new page To override the built-in page with the new page, add the new page as a custom asset and make sure that the new page has the same name and extension as the built-in page. The Janssen Server will automatically use the custom page instead of the built-in page. For example, the default login web page is rendered using login.xhtml . To override this page, add a new custom login.xhtml . Same can be done for other built-in pages like authorization page , logout page , error page . Adding New Web Pages # If the authentication/authorization flow requires new web pages, the same can be added as custom asset and then can be referenced using a relative path. For instance, if enterOTP.xhtml is your webpage for step 2 of the authentication flow that is being implemented using a custom script, then upload page as a custom asset under the relevant Janssen service and then reference it in the custom script as follows: def getPageForStep(self, configurationAttributes, step): # Used to specify the page you want to return for a given step if (step == 1): return \"/auth/login.xhtml\" if (step == 2) return \"/auth/enterOTP.xhtml\" Reference login pages: # Here you will find several login pages for different authentication methods. Customized resource bundles: # Janssen Server provides language translation support using a set of built-in resource bundles . To override the defaults, the custom .properties files should be uploaded as custom assets . If the file name matches the existing resource bundle, then the custom bundle will override the built-in resource bundle. Examples of file names are: jans-auth_en.properties jans-auth_bg.properties To add translations for a language that is not yet supported, create a new properties file and name it jans-auth_[language_code].properties. Then add it to the Janssen Server as custom asset . Janssen Server will automatically add the support for new language using the new resource bundle. Custom CSS files: # Upload the custom CSS files as custom assets and then reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/stylesheet/theme.css or /jans-auth/ext/resources/stylesheet/theme.css Custom image files: # Upload the custom image files as custom assets and then reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/img/fileName.png or /jans-auth/ext/resources/img/fileName.jpg . Page layout, header, footer (xhtml Template) customization # Templates refer to the common interface layout and style. For example, a banner, logo in the common header, and copyright information in the footer. Upload the custom template template.xhtml file as custom assets .This file will automatically override the built-in default template file .", "title": "Customize Web pages"}, {"location": "janssen-server/developer/customization/customize-web-pages/#customization-using-custom-assets", "text": "Janssen Server allows customization and extension of current web page designs, images, web templates etc. For example, extending the list of languages supported by Janssen Server or maybe customizing the login page to show the organization's logo and align styling to meet the branding of the organization. All of the above need some amount of custom assets, like custom CSS stylesheets, logo images, etc to be available on the Janssen Server. All these are called Custom Assets .", "title": "Customization Using Custom Assets"}, {"location": "janssen-server/developer/customization/customize-web-pages/#custom-assets-accepted-by-module", "text": "Listing of custom asset types that each Janssen Server module accepts:", "title": "Custom Assets Accepted by Module"}, {"location": "janssen-server/developer/customization/customize-web-pages/#config-api", "text": "Path Asset Type /opt/jans/jetty/jans-config-api/custom/config *.xml /opt/jans/jetty/jans-config-api/custom/i18n *.properties /opt/jans/jetty/jans-config-api/custom/libs *.jar /opt/jans/jetty/jans-config-api/custom/pages *.xhtml /opt/jans/jetty/jans-config-api/custom/static .js, .css, .png, .gif, .jpg, .jpeg", "title": "Config-API"}, {"location": "janssen-server/developer/customization/customize-web-pages/#auth-server", "text": "Path Asset Type /opt/jans/jetty/jans-auth/custom/i18n *.properties /opt/jans/jetty/jans-auth/custom/libs *.jars /opt/jans/jetty/jans-auth/custom/pages *.xhtml /opt/jans/jetty/jans-auth/custom/static .js, .css, .png, .gif, .jpg, .jpeg /etc/certs/jans-auth-keys.pkcs12 *.pkcs12", "title": "Auth-Server"}, {"location": "janssen-server/developer/customization/customize-web-pages/#casa", "text": "Path Asset Type /opt/jans/jetty/jans-casa/plugins *.jar /opt/jans/jetty/jans-casa/static .js, .css, .png, .gif, .jpg, .jpeg", "title": "Casa"}, {"location": "janssen-server/developer/customization/customize-web-pages/#agama", "text": "Path Asset Type /opt/jans/jetty/jans-auth/agama engine templates /opt/jans/jetty/jans-auth/agama/fl .js, .css, .png, .gif, .jpg, .jpeg /opt/jans/jetty/jans-auth/agama/ftl .ftl, .ftlh /opt/jans/jetty/jans-auth/agama/scripts .java .groovy, .gvy, .gy, *.gsh", "title": "Agama"}, {"location": "janssen-server/developer/customization/customize-web-pages/#fido2", "text": "Path Asset Type /etc/jans/conf/fido2/authenticator_cert .pem, .crt /etc/jans/conf/fido2/mds/cert *.crt /etc/jans/conf/fido2/mds/toc *.jwt /etc/jans/conf/fido2/server_metadata *.json", "title": "Fido2"}, {"location": "janssen-server/developer/customization/customize-web-pages/#lock", "text": "Path Asset Type /opt/jans/jetty/jans-lock/custom-libs *.jar", "title": "Lock"}, {"location": "janssen-server/developer/customization/customize-web-pages/#keycloak-link", "text": "Path Asset Type /opt/jans/jetty/jans-keycloak-link/custom/libs/ *.jar /var/jans/keycloak-link-snapshots/ *.txt", "title": "KeyCloak-link"}, {"location": "janssen-server/developer/customization/customize-web-pages/#link", "text": "Path Asset Type /opt/jans/jetty/jans-link/custom-libs *.jar /var/jans/link-snapshots/ *.txt", "title": "Link"}, {"location": "janssen-server/developer/customization/customize-web-pages/#managing-custom-assets", "text": "Janssen Server configuration tools like CLI and TUI provide the ability to add, update, and delete custom assets. Refer to the custom assets configuration guide to learn how to manage custom assets.", "title": "Managing Custom Assets"}, {"location": "janssen-server/developer/customization/customize-web-pages/#customizing-web-pages", "text": "Janssen Server uses xhtml pages to render the web interface needed in interactive web-flows. For example, password authentication flow. It is possible to override the built-in xhtml pages or to add completely new pages.", "title": "Customizing Web Pages"}, {"location": "janssen-server/developer/customization/customize-web-pages/#customizing-built-in-web-pages", "text": "In order to customize built-in web pages, follow the steps below: Create a new xhtml page as a copy of the relevant built-in xhtml page Make changes to the code of the new page according to the need Override the built-in page with the new page To override the built-in page with the new page, add the new page as a custom asset and make sure that the new page has the same name and extension as the built-in page. The Janssen Server will automatically use the custom page instead of the built-in page. For example, the default login web page is rendered using login.xhtml . To override this page, add a new custom login.xhtml . Same can be done for other built-in pages like authorization page , logout page , error page .", "title": "Customizing Built-in Web Pages"}, {"location": "janssen-server/developer/customization/customize-web-pages/#adding-new-web-pages", "text": "If the authentication/authorization flow requires new web pages, the same can be added as custom asset and then can be referenced using a relative path. For instance, if enterOTP.xhtml is your webpage for step 2 of the authentication flow that is being implemented using a custom script, then upload page as a custom asset under the relevant Janssen service and then reference it in the custom script as follows: def getPageForStep(self, configurationAttributes, step): # Used to specify the page you want to return for a given step if (step == 1): return \"/auth/login.xhtml\" if (step == 2) return \"/auth/enterOTP.xhtml\"", "title": "Adding New Web Pages"}, {"location": "janssen-server/developer/customization/customize-web-pages/#reference-login-pages", "text": "Here you will find several login pages for different authentication methods.", "title": "Reference login pages:"}, {"location": "janssen-server/developer/customization/customize-web-pages/#customized-resource-bundles", "text": "Janssen Server provides language translation support using a set of built-in resource bundles . To override the defaults, the custom .properties files should be uploaded as custom assets . If the file name matches the existing resource bundle, then the custom bundle will override the built-in resource bundle. Examples of file names are: jans-auth_en.properties jans-auth_bg.properties To add translations for a language that is not yet supported, create a new properties file and name it jans-auth_[language_code].properties. Then add it to the Janssen Server as custom asset . Janssen Server will automatically add the support for new language using the new resource bundle.", "title": "Customized resource bundles:"}, {"location": "janssen-server/developer/customization/customize-web-pages/#custom-css-files", "text": "Upload the custom CSS files as custom assets and then reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/stylesheet/theme.css or /jans-auth/ext/resources/stylesheet/theme.css", "title": "Custom CSS files:"}, {"location": "janssen-server/developer/customization/customize-web-pages/#custom-image-files", "text": "Upload the custom image files as custom assets and then reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/img/fileName.png or /jans-auth/ext/resources/img/fileName.jpg .", "title": "Custom image files:"}, {"location": "janssen-server/developer/customization/customize-web-pages/#page-layout-header-footer-xhtml-template-customization", "text": "Templates refer to the common interface layout and style. For example, a banner, logo in the common header, and copyright information in the footer. Upload the custom template template.xhtml file as custom assets .This file will automatically override the built-in default template file .", "title": "Page layout, header, footer (xhtml Template) customization"}, {"location": "janssen-server/fido/bluetooth-authn/", "tags": ["administration", "fido"], "text": "Troubleshooting notes: # Enable the Bluetooth Device Permissions in Chrome Settings https://support.google.com/accounts/answer/9289445?hl=en&co=GENIE.Platform%3DAndroid", "title": "Bluetooth Authenticator Support"}, {"location": "janssen-server/fido/bluetooth-authn/#troubleshooting-notes", "text": "Enable the Bluetooth Device Permissions in Chrome Settings https://support.google.com/accounts/answer/9289445?hl=en&co=GENIE.Platform%3DAndroid", "title": "Troubleshooting notes:"}, {"location": "janssen-server/fido/config/", "tags": ["administration", "fido2"], "text": "Configuration Parameters of Janssen's FIDO2 server: # Field named Example Description issuer https://my-jans-server.jans.io URL using the https scheme with no query or fragment component. The OP asserts this as its Issuer Identifier baseEndpoint https://my-jans-server/jans-fido2/restv1 Base URL of the FIDO2 server Endpoints webAuthnEndpoint https://FQDN/jans-fido2/restv1/webauthn/configuration Base URL of the FIDO2 Web Authn Server Endpoint which return RP Origins cleanServiceInterval 60 Time interval for the Clean Service in seconds. cleanServiceBatchChunkSize 10000 Each clean up iteration fetches chunk of expired data per base dn and removes it from storage. useLocalCache true Boolean value specifying whether to enable local in-memory cache for attributes, scopes, clients and organization configuration disableJdkLogger true Boolean value specifying whether to enable JDK Loggers loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for FIDO2 server loggingLayout \"text\" or \"json\" Contents of logs as plain text or json format externalLoggerConfiguration Path to external log4j2 logging configuration metricReporterInterval 300 The interval for metric reporter in seconds. metricReporterKeepDataDays 15 The number of days to retain metric reported data in the system metricReporterEnabled true Boolean value specifying whether to enable Metric Reporter fido2Configuration See JSON contents in the below example FIDO2 Configuration Fido2Configuration structure # Field named Example Description authenticatorCertsFolder /etc/jans/conf/fido2/authenticator_cert Authenticators certificates fodler. mdsCertsFolder /etc/jans/conf/fido2/mds/cert MDS TOC root certificates folder. mdsTocsFolder /etc/jans/conf/fido2/mds/toc MDS TOC files folder. serverMetadataFolder /etc/jans/conf/fido2/server_metadata Authenticators metadata in json format. Example: virtual devices. metadataUrlsProvider https://mds3.fido.tools String value to provide source of URLs with external metadata. enabledFidoAlgorithms [\"RS256\",\"ES256\"] rp [{\"id\":\"https://my-jans-server.jans.io\",\"origins\":[\"my-jans-server.jans.io\"]}] Requested party id. debugUserAutoEnrollment false Allow to enroll users on enrollment/authentication requests. (Useful while running tests) unfinishedRequestExpiration 180 Expiration time in seconds for pending enrollment/authentication requests authenticationHistoryExpiration 1296000 Expiration time in seconds for approved authentication requests. disableMetadataService false Boolean value indicating whether the MDS download should be omitted attestationMode \"monitor\" Enum value indicating whether MDS validation should be omitted during attestation assertionOptionsGenerateEndpointEnabled false Boolean value indicating whether the assertion custom endpoint (used especially in passkey) is enabled. Configuring the FIDO2 server: # 1. Read Configuration parameters: # Use the following command to obtain configuration parameters: jans cli --operation-id get-properties-fido2 Response: { \"issuer\": \"https://my.jans.server\", \"baseEndpoint\": \"https://my.jans.server/jans-fido2/restv1\", \"cleanServiceInterval\": 60, \"cleanServiceBatchChunkSize\": 10000, \"useLocalCache\": true, \"disableJdkLogger\": true, \"loggingLevel\": \"DEBUG\", \"loggingLayout\": \"text\", \"metricReporterInterval\": 300, \"metricReporterKeepDataDays\": 15, \"metricReporterEnabled\": true, \"personCustomObjectClassList\": [ \"jansCustomPerson\", \"jansPerson\" ], \"sessionIdPersistInCache\": false, \"fido2Configuration\": { \"authenticatorCertsFolder\": \"/etc/jans/conf/fido2/authenticator_cert\", \"mdsCertsFolder\": \"/etc/jans/conf/fido2/mds/cert\", \"mdsTocsFolder\": \"/etc/jans/conf/fido2/mds/toc\", \"checkU2fAttestations\": false, \"debugUserAutoEnrollment\": false, \"unfinishedRequestExpiration\": 180, \"authenticationHistoryExpiration\": 1296000, \"serverMetadataFolder\": \"/etc/jans/conf/fido2/server_metadata\", \"metadataUrlsProvider\": \"\", \"disableMetadataService\": false, \"attestationMode\": \"monitor\", \"assertionOptionsGenerateEndpointEnabled\":true, \"enabledFidoAlgorithms\": [ \"RS256\", \"ES256\" ], \"rp\": [ { \"id\": \"https://my.jans.server\", \"origins\": [ \"my.jans.server\" ] } ] } } 2. Update configuration parameters: # Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1 B. Use the following command jans cli --operation-id post-config-scripts --data /tmp/config_values.json 3. Change log level of FIDO2 server # Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1. Edit loggingLevel to TRACE or DEBUG or INFO B. Use the following command jans cli --operation-id put-properties-fido --data /tmp/config_values.json 4. Locating FIDO2 configuration in Persistence Layer # While it is not recommended that an administrator directly edits a configuration at the persistence layer, it may be useful information for a developer. 5. WebAuthn Endpoint # A. The WebAuthn Endpoints retrieve the list of RP (Relying Party) Origins configured for FIDO2 authentication. B. Endpoints: https://FQDN/restv1/webauthn/configuration && https://FQDN/.well-known/webauthn MySQL # erDiagram jansAppConf { string doc_id PK \"\" string ou \"jans-fido2\" string jansConfDyn \"json configuration for the app\" }", "title": "Configuration"}, {"location": "janssen-server/fido/config/#configuration-parameters-of-janssens-fido2-server", "text": "Field named Example Description issuer https://my-jans-server.jans.io URL using the https scheme with no query or fragment component. The OP asserts this as its Issuer Identifier baseEndpoint https://my-jans-server/jans-fido2/restv1 Base URL of the FIDO2 server Endpoints webAuthnEndpoint https://FQDN/jans-fido2/restv1/webauthn/configuration Base URL of the FIDO2 Web Authn Server Endpoint which return RP Origins cleanServiceInterval 60 Time interval for the Clean Service in seconds. cleanServiceBatchChunkSize 10000 Each clean up iteration fetches chunk of expired data per base dn and removes it from storage. useLocalCache true Boolean value specifying whether to enable local in-memory cache for attributes, scopes, clients and organization configuration disableJdkLogger true Boolean value specifying whether to enable JDK Loggers loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for FIDO2 server loggingLayout \"text\" or \"json\" Contents of logs as plain text or json format externalLoggerConfiguration Path to external log4j2 logging configuration metricReporterInterval 300 The interval for metric reporter in seconds. metricReporterKeepDataDays 15 The number of days to retain metric reported data in the system metricReporterEnabled true Boolean value specifying whether to enable Metric Reporter fido2Configuration See JSON contents in the below example FIDO2 Configuration", "title": "Configuration Parameters of Janssen's FIDO2 server:"}, {"location": "janssen-server/fido/config/#fido2configuration-structure", "text": "Field named Example Description authenticatorCertsFolder /etc/jans/conf/fido2/authenticator_cert Authenticators certificates fodler. mdsCertsFolder /etc/jans/conf/fido2/mds/cert MDS TOC root certificates folder. mdsTocsFolder /etc/jans/conf/fido2/mds/toc MDS TOC files folder. serverMetadataFolder /etc/jans/conf/fido2/server_metadata Authenticators metadata in json format. Example: virtual devices. metadataUrlsProvider https://mds3.fido.tools String value to provide source of URLs with external metadata. enabledFidoAlgorithms [\"RS256\",\"ES256\"] rp [{\"id\":\"https://my-jans-server.jans.io\",\"origins\":[\"my-jans-server.jans.io\"]}] Requested party id. debugUserAutoEnrollment false Allow to enroll users on enrollment/authentication requests. (Useful while running tests) unfinishedRequestExpiration 180 Expiration time in seconds for pending enrollment/authentication requests authenticationHistoryExpiration 1296000 Expiration time in seconds for approved authentication requests. disableMetadataService false Boolean value indicating whether the MDS download should be omitted attestationMode \"monitor\" Enum value indicating whether MDS validation should be omitted during attestation assertionOptionsGenerateEndpointEnabled false Boolean value indicating whether the assertion custom endpoint (used especially in passkey) is enabled.", "title": "Fido2Configuration structure"}, {"location": "janssen-server/fido/config/#configuring-the-fido2-server", "text": "", "title": "Configuring the FIDO2 server:"}, {"location": "janssen-server/fido/config/#1-read-configuration-parameters", "text": "Use the following command to obtain configuration parameters: jans cli --operation-id get-properties-fido2 Response: { \"issuer\": \"https://my.jans.server\", \"baseEndpoint\": \"https://my.jans.server/jans-fido2/restv1\", \"cleanServiceInterval\": 60, \"cleanServiceBatchChunkSize\": 10000, \"useLocalCache\": true, \"disableJdkLogger\": true, \"loggingLevel\": \"DEBUG\", \"loggingLayout\": \"text\", \"metricReporterInterval\": 300, \"metricReporterKeepDataDays\": 15, \"metricReporterEnabled\": true, \"personCustomObjectClassList\": [ \"jansCustomPerson\", \"jansPerson\" ], \"sessionIdPersistInCache\": false, \"fido2Configuration\": { \"authenticatorCertsFolder\": \"/etc/jans/conf/fido2/authenticator_cert\", \"mdsCertsFolder\": \"/etc/jans/conf/fido2/mds/cert\", \"mdsTocsFolder\": \"/etc/jans/conf/fido2/mds/toc\", \"checkU2fAttestations\": false, \"debugUserAutoEnrollment\": false, \"unfinishedRequestExpiration\": 180, \"authenticationHistoryExpiration\": 1296000, \"serverMetadataFolder\": \"/etc/jans/conf/fido2/server_metadata\", \"metadataUrlsProvider\": \"\", \"disableMetadataService\": false, \"attestationMode\": \"monitor\", \"assertionOptionsGenerateEndpointEnabled\":true, \"enabledFidoAlgorithms\": [ \"RS256\", \"ES256\" ], \"rp\": [ { \"id\": \"https://my.jans.server\", \"origins\": [ \"my.jans.server\" ] } ] } }", "title": "1. Read Configuration parameters:"}, {"location": "janssen-server/fido/config/#2-update-configuration-parameters", "text": "Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1 B. Use the following command jans cli --operation-id post-config-scripts --data /tmp/config_values.json", "title": "2. Update configuration parameters:"}, {"location": "janssen-server/fido/config/#3-change-log-level-of-fido2-server", "text": "Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1. Edit loggingLevel to TRACE or DEBUG or INFO B. Use the following command jans cli --operation-id put-properties-fido --data /tmp/config_values.json", "title": "3. Change log level of FIDO2 server"}, {"location": "janssen-server/fido/config/#4-locating-fido2-configuration-in-persistence-layer", "text": "While it is not recommended that an administrator directly edits a configuration at the persistence layer, it may be useful information for a developer.", "title": "4. Locating FIDO2 configuration in Persistence Layer"}, {"location": "janssen-server/fido/config/#5-webauthn-endpoint", "text": "A. The WebAuthn Endpoints retrieve the list of RP (Relying Party) Origins configured for FIDO2 authentication. B. Endpoints: https://FQDN/restv1/webauthn/configuration && https://FQDN/.well-known/webauthn", "title": "5. WebAuthn Endpoint"}, {"location": "janssen-server/fido/config/#mysql", "text": "erDiagram jansAppConf { string doc_id PK \"\" string ou \"jans-fido2\" string jansConfDyn \"json configuration for the app\" }", "title": "MySQL"}, {"location": "janssen-server/fido/key-mgt/", "tags": ["administration", "fido"], "text": "Attestation types # Basic attestation:", "title": "Key Management/Rotation"}, {"location": "janssen-server/fido/key-mgt/#attestation-types", "text": "Basic attestation:", "title": "Attestation types"}, {"location": "janssen-server/fido/logs/", "tags": ["administration", "fido"], "text": "Log level and Logging Layout Parameters of Janssen's FIDO2 server: # Field named Example Description loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for FIDO2 server loggingLayout \"text\" or \"json\" Contents of logs as plain text or json format 1. Read Configuration parameters: # Use the following command to obtain configuration parameters: jans cli --operation-id get-properties-fido2 Response: { \"issuer\":\"https://.jans.io\", \"baseEndpoint\":\"https://my-jans-server.jans.io/jans-fido2/restv1\", \"cleanServiceInterval\":60, \"cleanServiceBatchChunkSize\":10000, \"useLocalCache\":true, \"disableJdkLogger\":true, \"loggingLevel\":\"INFO\", \"loggingLayout\":\"text\", \"externalLoggerConfiguration\":\"\", \"metricReporterInterval\":300, \"metricReporterKeepDataDays\":15, \"metricReporterEnabled\":true, \"personCustomObjectClassList\":[ \"jansCustomPerson\", \"jansPerson\" ], \"fido2Configuration\":{ \"authenticatorCertsFolder\":\"/etc/jans/conf/fido2/authenticator_cert\", \"mdsCertsFolder\":\"/etc/jans/conf/fido2/mds/cert\", \"mdsTocsFolder\":\"/etc/jans/conf/fido2/mds/toc\", \"serverMetadataFolder\":\"/etc/jans/conf/fido2/server_metadata\", \"enabledFidoAlgorithms\":[ \"RS256\", \"ES256\" ], \"rp\":[ { \"id\":\"https://my-jans-server.jans.io\", \"origins\":[ \"my-jans-server.jans.io\" ] } ], \"debugUserAutoEnrollment\":false, \"unfinishedRequestExpiration\":180, \"authenticationHistoryExpiration\":1296000 } } 2. Update loggingLevel or loggingLayout : # Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1 and - edit loggingLevel to TRACE or DEBUG or INFO - edit loggingLayout to text or json B. Use the following command to update the logging level jans cli --operation-id post-config-scripts --data /tmp/config_values.json C. restart jans-fido2 service fido2 restart or systemctl restart fido2 Location of logs in FIDO2 server: # Logs can be found at /opt/jans/jetty/jans-fido2/logs", "title": "Logs"}, {"location": "janssen-server/fido/logs/#log-level-and-logging-layout-parameters-of-janssens-fido2-server", "text": "Field named Example Description loggingLevel \"INFO\" or \"TRACE\" or \"DEBUG\" Logging level for FIDO2 server loggingLayout \"text\" or \"json\" Contents of logs as plain text or json format", "title": "Log level and Logging Layout Parameters of Janssen's FIDO2 server:"}, {"location": "janssen-server/fido/logs/#1-read-configuration-parameters", "text": "Use the following command to obtain configuration parameters: jans cli --operation-id get-properties-fido2 Response: { \"issuer\":\"https://.jans.io\", \"baseEndpoint\":\"https://my-jans-server.jans.io/jans-fido2/restv1\", \"cleanServiceInterval\":60, \"cleanServiceBatchChunkSize\":10000, \"useLocalCache\":true, \"disableJdkLogger\":true, \"loggingLevel\":\"INFO\", \"loggingLayout\":\"text\", \"externalLoggerConfiguration\":\"\", \"metricReporterInterval\":300, \"metricReporterKeepDataDays\":15, \"metricReporterEnabled\":true, \"personCustomObjectClassList\":[ \"jansCustomPerson\", \"jansPerson\" ], \"fido2Configuration\":{ \"authenticatorCertsFolder\":\"/etc/jans/conf/fido2/authenticator_cert\", \"mdsCertsFolder\":\"/etc/jans/conf/fido2/mds/cert\", \"mdsTocsFolder\":\"/etc/jans/conf/fido2/mds/toc\", \"serverMetadataFolder\":\"/etc/jans/conf/fido2/server_metadata\", \"enabledFidoAlgorithms\":[ \"RS256\", \"ES256\" ], \"rp\":[ { \"id\":\"https://my-jans-server.jans.io\", \"origins\":[ \"my-jans-server.jans.io\" ] } ], \"debugUserAutoEnrollment\":false, \"unfinishedRequestExpiration\":180, \"authenticationHistoryExpiration\":1296000 } }", "title": "1. Read Configuration parameters:"}, {"location": "janssen-server/fido/logs/#2-update-logginglevel-or-logginglayout", "text": "Steps: A. Create a JSON file say /tmp/config_values.json by editing the JSON from Point 1 and - edit loggingLevel to TRACE or DEBUG or INFO - edit loggingLayout to text or json B. Use the following command to update the logging level jans cli --operation-id post-config-scripts --data /tmp/config_values.json C. restart jans-fido2 service fido2 restart or systemctl restart fido2", "title": "2. Update loggingLevel or loggingLayout:"}, {"location": "janssen-server/fido/logs/#location-of-logs-in-fido2-server", "text": "Logs can be found at /opt/jans/jetty/jans-fido2/logs", "title": "Location of logs in FIDO2 server:"}, {"location": "janssen-server/fido/monitoring/", "tags": ["administration", "fido"], "text": "Monitoring # FIDO Devices # A FIDO device represents a user credential stored in the Jans Server database that is compliant with the FIDO standard. These devices are used as a second factor in a setting of strong authentication. FIDO devices were superseded by FIDO 2 devices in Jans Server. FIDO2 devices # FIDO2 devices are credentials that adhere to the more current Fido 2.0 initiative (WebAuthn + CTAP). Examples of FIDO2 devices are USB security keys and Super Gluu devices. The SCIM endpoints for FIDO 2 allow application developers to query, update and delete already existing devices. Addition of devices do not take place through the service since this process requires direct end-user interaction, ie. device enrolling. The schema attributes for a device of this kind can be found by hitting the URL https://<jans-server>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:Fido2Device To distinguish between regular FIDO2 and SuperGluu devices, note only SuperGluu entries have the attribute deviceData populated (i.e. not null) Example: Querying Enrolled Devices # Say we are interested in having a list of Super Gluu devices users have enrolled and whose operating system is iOS. We may issue a query like this: curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=deviceData co \"ios\"' -d count=10 https://<jans-server>/jans-scim/restv1/v2/Fido2Devices The response will be like: { \"totalResults\": ..., \"itemsPerPage\": ..., \"startIndex\": 1, \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"Resources\": [ { \"id\": \"...\", \"meta\": {...}, \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:Fido2Device\"], \"userId\": \"...\", ... \"deviceData\": \"{...}\", \"displayName\": ..., }, ... ] }", "title": "Monitoring"}, {"location": "janssen-server/fido/monitoring/#monitoring", "text": "", "title": "Monitoring"}, {"location": "janssen-server/fido/monitoring/#fido-devices", "text": "A FIDO device represents a user credential stored in the Jans Server database that is compliant with the FIDO standard. These devices are used as a second factor in a setting of strong authentication. FIDO devices were superseded by FIDO 2 devices in Jans Server.", "title": "FIDO Devices"}, {"location": "janssen-server/fido/monitoring/#fido2-devices", "text": "FIDO2 devices are credentials that adhere to the more current Fido 2.0 initiative (WebAuthn + CTAP). Examples of FIDO2 devices are USB security keys and Super Gluu devices. The SCIM endpoints for FIDO 2 allow application developers to query, update and delete already existing devices. Addition of devices do not take place through the service since this process requires direct end-user interaction, ie. device enrolling. The schema attributes for a device of this kind can be found by hitting the URL https://<jans-server>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:Fido2Device To distinguish between regular FIDO2 and SuperGluu devices, note only SuperGluu entries have the attribute deviceData populated (i.e. not null)", "title": "FIDO2 devices"}, {"location": "janssen-server/fido/monitoring/#example-querying-enrolled-devices", "text": "Say we are interested in having a list of Super Gluu devices users have enrolled and whose operating system is iOS. We may issue a query like this: curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=deviceData co \"ios\"' -d count=10 https://<jans-server>/jans-scim/restv1/v2/Fido2Devices The response will be like: { \"totalResults\": ..., \"itemsPerPage\": ..., \"startIndex\": 1, \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"Resources\": [ { \"id\": \"...\", \"meta\": {...}, \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:Fido2Device\"], \"userId\": \"...\", ... \"deviceData\": \"{...}\", \"displayName\": ..., }, ... ] }", "title": "Example: Querying Enrolled Devices"}, {"location": "janssen-server/fido/platform-authn/", "tags": ["administration", "fido"], "text": "Apple Anonymous Attestation is first of its kind, providing a service like an Anonymization CA, where the authenticator works with a cloud operated CA owned by its manufacturer to dynamically generate per-credential attestation certificates such that no identification information of the authenticator will be revealed to websites in the attestation statement. Furthermore, among data relevant to the registration ceremony, only the public key of the credential along with a hash of the concatenated authenticator data and client data are sent to the CA for attestation, and the CA will not store any of these. This approach makes the whole attestation process privacy preserving. In addition, this approach avoids the security pitfall of Basic Attestation that the compromising of a single device results in revoking certificates from all devices with the same attestation certificate. https://medium.com/webauthnworks/webauthn-fido2-verifying-apple-anonymous-attestation-5eaff334c849", "title": "Platform Authenticator Support"}, {"location": "janssen-server/fido/usb-authn/", "tags": ["administration", "fido"], "text": "This page will be the landing page for the Janssen Project admin documentation", "title": "USB Authenticator Support"}, {"location": "janssen-server/fido/vendor-metadata/", "tags": ["administration", "fido2", "metadata Service", "attestation"], "text": "Metadata Service: # The metadata service is a centralized, trusted database of FIDO authenticators. It is used by the Relying Party to validate authenticators i.e. attest the genuine-ness of a device. If implemented in organizations like government, federal agencies, banking and healthcare organizations for example) and/or organizations handling sensitive data (media companies, R&D institutions, corporations, etc), this information can help protect organizations against security vulnerabilities. 1. Local metadata service: # Janssen's FIDO server has a configuration parameter called serverMetadataFolder which by default points to a directory location /etc/jans/conf/fido2/server_metadata where the administrator can (obtain from a vendor and ) place authenticator metadata in json format. Example of authenticator metadata: { \"aaguid\": \"83c44309-....-8be444b573cb\", \"metadataStatement\": { \"legalHeader\": \"Submission of this statement and retrieval and use of this statement indicates acceptance of the appropriate agreement located at https://fidoalliance.org/metadata/metadata-legal-terms/.\", \"aaguid\": \"83c44309-....-8be444b573cb\", \"description\": \"Just an example\", \"authenticatorVersion\": 448962, \"protocolFamily\": \"fido2\", \"schema\": 3, \"upv\": [ { \"major\": 1, \"minor\": 0 }, { \"major\": 1, \"minor\": 1 } ], \"authenticationAlgorithms\": [ \"ed25519_eddsa_sha512_raw\", \"secp256r1_ecdsa_sha256_raw\" ], \"publicKeyAlgAndEncodings\": [ \"cose\" ], \"attestationTypes\": [ \"basic_full\" ], \"userVerificationDetails\": [ [ { \"userVerificationMethod\": \"passcode_external\", \"caDesc\": { \"base\": 64, \"minLength\": 4, \"maxRetries\": 8, \"blockSlowdown\": 0 } }, { \"userVerificationMethod\": \"presence_internal\" } ], [ { \"userVerificationMethod\": \"passcode_external\", \"caDesc\": { \"base\": 64, \"minLength\": 4, \"maxRetries\": 8, \"blockSlowdown\": 0 } } ], [ { \"userVerificationMethod\": \"fingerprint_internal\", \"baDesc\": { \"selfAttestedFRR\": 0, \"selfAttestedFAR\": 0, \"maxTemplates\": 5, \"maxRetries\": 5, \"blockSlowdown\": 0 } }, { \"userVerificationMethod\": \"presence_internal\" } ], [ { \"userVerificationMethod\": \"none\" } ], [ { \"userVerificationMethod\": \"fingerprint_internal\", \"baDesc\": { \"selfAttestedFRR\": 0, \"selfAttestedFAR\": 0, \"maxTemplates\": 5, \"maxRetries\": 5, \"blockSlowdown\": 0 } } ], [ { \"userVerificationMethod\": \"presence_internal\" } ] ], \"keyProtection\": [ \"hardware\", \"secure_element\" ], \"matcherProtection\": [ \"on_chip\" ], \"cryptoStrength\": 128, \"attachmentHint\": [ \"external\", \"wired\" ], \"tcDisplay\": [], \"attestationRootCertificates\": [ \"MII....psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==\" ], \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAA....k5+36hF7vXAAAAAElFTkSuQmCC\", \"authenticatorGetInfo\": { \"versions\": [ \"FIDO_2_0\", \"FIDO_2_1_PRE\", \"FIDO_2_1\" ], \"extensions\": [ \"credProtect\", \"hmac-secret\", \"largeBlobKey\", \"credBlob\", \"minPinLength\" ], \"aaguid\": \"83c.....73cb\", \"options\": { \"plat\": false, \"rk\": true, \"clientPin\": true, \"up\": true, \"uv\": false, \"pinUvAuthToken\": true, \"largeBlobs\": true, \"ep\": false, \"bioEnroll\": false, \"userVerificationMgmtPreview\": false, \"authnrCfg\": true, \"credMgmt\": true, \"credentialMgmtPreview\": true, \"setMinPINLength\": true, \"makeCredUvNotRqd\": false, \"alwaysUv\": true }, \"maxMsgSize\": 1200, \"pinUvAuthProtocols\": [ 2, 1 ], \"maxCredentialCountInList\": 8, \"maxCredentialIdLength\": 128, \"transports\": [ \"usb\" ], \"algorithms\": [ { \"type\": \"public-key\", \"alg\": -7 }, { \"type\": \"public-key\", \"alg\": -8 } ], \"maxSerializedLargeBlobArray\": 1024, \"forcePINChange\": false, \"minPINLength\": 4, \"firmwareVersion\": 328965, \"maxCredBlobLength\": 32, \"maxRPIDsForSetMinPINLength\": 1, \"preferredPlatformUvAttempts\": 3, \"uvModality\": 2, \"remainingDiscoverableCredentials\": 25 } }, \"statusReports\": [ { \"status\": \"FIDO_CERTIFIED_L1\", \"effectiveDate\": \"2021-08-06\", \"url\": \"www.yubico.com\", \"certificationDescriptor\": \"An example\", \"certificateNumber\": \"FIDO2.....001\", \"certificationPolicyVersion\": \"1.3\", \"certificationRequirementsVersion\": \"1.4\" }, { \"status\": \"FIDO_CERTIFIED\", \"effectiveDate\": \"2021-08-06\" } ], \"timeOfLastStatusChange\": \"2021-08-16\" } 2. Metadata service for authenticators approved by FIDO Alliance (MDS3) # Metadata entries for trusted authenticators registered with FIDO Alliance can be found on - https://fidoalliance.org/certification/fido-certified-products/ Draw.io reference for image: <?xml version=\"1.0\" encoding=\"UTF-8\"?> <mxfile host=\"app.diagrams.net\" modified=\"2022-11-03T13:17:35.619Z\" agent=\"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.52\" etag=\"MPAHjBuOoBSpVro-BGSI\" version=\"20.5.1\" type=\"google\"><diagram id=\"An1oD0C01MiJfx2t8ul6\" name=\"Page-1\">7Vlbc6M2FP41nrYPyXAx2Hl07HUv052kdWe7fVRAAU0EokLEdn/9noOEsQBnva6ZnZ3ZJ3M+ISG+79yEJ/4y2/0sSZG+FzHlE8+JdxN/NfE8158F8IPIXiOzYKqBRLLY3NQCG/YfNaBj0IrFtLRuVEJwxQobjESe00hZGJFSbO3bngW3n1qQhPaATUR4H/2bxSrV6DxwWvwXypK0ebLrmJGMNDcboExJLLZHkP9u4i+lEEpfZbsl5Uhew4uetz4xetiYpLk6Z0L6cRW7f/0ZB+E2cD9U+8dy+ceNUeeV8Mq88G8kL2/Wv64eEN9Q+Uql2b/aN6SUW5ZxkoN1/yxyZVRz52Cb9ahUdHdyo+7h9cFvqMioknu4xUyY+oYx4zJzY25b/g9Yesx9aEBiNE8OS7e0wIVh5gtY8nssIUGALDhnJI/oDyUY76kiMVGk5ooomuH7wm7yGJ1WVqW2olQMMJqSAi9zoZDVbcoU3RQkQmwLkQVYqjKOLMPlE4leEimqPH6oFGc5NXhM5MsDzGIKqXNuneBcRU47x0mZvMBSaRr0VLoL+iLNg5E0mvY0+l1AGNu6bFpdvn0B3FlHgbCnwGxAgdlYCsx6CvRYpnm8wKQMVsRJWbLI5rWmlOJDnJO5hca9jH0ZjUc8BQPppMEk5USxV/uZQ+SZJzwKVsf9zqbbiORNO0mqFJWMqJl0nL7fXsf1O+soIhOqeuvUSh5e+nJxwy9NgVg6GISPF3KFEQM5L0zw6sdUKSzeC9yjt35msSBmjVshE9zdYZX1Tz0Xsl3kM3E6QnUKHLs6+d655amr/NUCbz4QeJp1fH+LvvDfSjQDN2XNDOjguF6xq+lpxhuxoGPJuSBIOPZYBWw2JBmynD+Vhb6R6wlr/TA9rycbEK5sbQhnSY6JAIiHHsO/R1kYpOyFGchYHOP0e0lhp+SpXgpFL9DJaxKD+0mwwrUqJUqjM5ilkuKFLgWHSospXXcqjPMuNL57eGHfPVxvwD1G8467/+8d8xPe0aSASqVAD2insLU5zyEujmPvOkK5ri3UoXE/Fmo2FMfeWEo1OxqvggI3cv/RDNbGP3WfEjTmanc8uNo31o4pnObeOk5obD0TD3jabqeicTzzkUoGDGGQ19gZddxAuji+RZlpzXX1+1z9+lo9gD/r1Iy7C5uAqddZqJs1Ru4CXHd0D208zfKyt33siv5091XdZN6pHe6lbtI5QfdOxmO7iTdeR7JQiuLxmon8e+9hlzS/W9L8fkkb6kxHaz3c/oeTq/UenabD+QB559vpPuzDnD/UJA4pNR9Nqf7nk6tFLLCiyAvFLUDIOsNNoxNhBD6jeRTZ7amxe+7QX9UkTViJEYzUAXOH1ZsT5fcU0el65x3PG/q4OlTiLvi2Cmb7dVuXlvY/Av/dJw==</diagram></mxfile> Janssen's FIDO2 server - Downloads, verifies and caches metadata BLOBs from the FIDO Metadata Service. Re-downloads the metadata BLOB when it expires. Provides trust root certificates for verifying attestation statements during credential registrations. 3. Skip metadata validation # Metadata validation is recommended but not mandatory as per FIDO2 specifications. In FIDO2 we can disable this validation by setting the attestionMode parameter (default is monitor). It should look something like this: \"fido2Configuration\": { ..., \"attestationMode\": \"disabled\", ... } 4. How Apple does it differently # If you check attStmt and it contains x5c , it is a FULL attestation. FULL basically means that it is a certificate that is chained to the vendor. It's signed by a batch private key whose public key is in a batch certificate that is chained to the Apple attestation root certificate. Usually certificates have an authorityInfoAccess extension that helps locate the root, but Apple chose not to do that. Nevertheless, a quick google give us the needed root certificate https://www.apple.com/certificateauthority/Apple_WebAuthn_Root_CA.pem. This certificate is downloaded to the path /etc/jans/conf/fido2/authenticator_cert . You can see more details of the implementation in this link from https://medium.com/webauthnworks/webauthn-fido2-verifying-apple-anonymous-attestation-5eaff334c849. References: # https://fidoalliance.org/announcing-the-new-streamlined-and-simplified-metadata-service-for-authenticator-vendors-and-customers/", "title": "Vendor Metadata Management"}, {"location": "janssen-server/fido/vendor-metadata/#metadata-service", "text": "The metadata service is a centralized, trusted database of FIDO authenticators. It is used by the Relying Party to validate authenticators i.e. attest the genuine-ness of a device. If implemented in organizations like government, federal agencies, banking and healthcare organizations for example) and/or organizations handling sensitive data (media companies, R&D institutions, corporations, etc), this information can help protect organizations against security vulnerabilities.", "title": "Metadata Service:"}, {"location": "janssen-server/fido/vendor-metadata/#1-local-metadata-service", "text": "Janssen's FIDO server has a configuration parameter called serverMetadataFolder which by default points to a directory location /etc/jans/conf/fido2/server_metadata where the administrator can (obtain from a vendor and ) place authenticator metadata in json format. Example of authenticator metadata: { \"aaguid\": \"83c44309-....-8be444b573cb\", \"metadataStatement\": { \"legalHeader\": \"Submission of this statement and retrieval and use of this statement indicates acceptance of the appropriate agreement located at https://fidoalliance.org/metadata/metadata-legal-terms/.\", \"aaguid\": \"83c44309-....-8be444b573cb\", \"description\": \"Just an example\", \"authenticatorVersion\": 448962, \"protocolFamily\": \"fido2\", \"schema\": 3, \"upv\": [ { \"major\": 1, \"minor\": 0 }, { \"major\": 1, \"minor\": 1 } ], \"authenticationAlgorithms\": [ \"ed25519_eddsa_sha512_raw\", \"secp256r1_ecdsa_sha256_raw\" ], \"publicKeyAlgAndEncodings\": [ \"cose\" ], \"attestationTypes\": [ \"basic_full\" ], \"userVerificationDetails\": [ [ { \"userVerificationMethod\": \"passcode_external\", \"caDesc\": { \"base\": 64, \"minLength\": 4, \"maxRetries\": 8, \"blockSlowdown\": 0 } }, { \"userVerificationMethod\": \"presence_internal\" } ], [ { \"userVerificationMethod\": \"passcode_external\", \"caDesc\": { \"base\": 64, \"minLength\": 4, \"maxRetries\": 8, \"blockSlowdown\": 0 } } ], [ { \"userVerificationMethod\": \"fingerprint_internal\", \"baDesc\": { \"selfAttestedFRR\": 0, \"selfAttestedFAR\": 0, \"maxTemplates\": 5, \"maxRetries\": 5, \"blockSlowdown\": 0 } }, { \"userVerificationMethod\": \"presence_internal\" } ], [ { \"userVerificationMethod\": \"none\" } ], [ { \"userVerificationMethod\": \"fingerprint_internal\", \"baDesc\": { \"selfAttestedFRR\": 0, \"selfAttestedFAR\": 0, \"maxTemplates\": 5, \"maxRetries\": 5, \"blockSlowdown\": 0 } } ], [ { \"userVerificationMethod\": \"presence_internal\" } ] ], \"keyProtection\": [ \"hardware\", \"secure_element\" ], \"matcherProtection\": [ \"on_chip\" ], \"cryptoStrength\": 128, \"attachmentHint\": [ \"external\", \"wired\" ], \"tcDisplay\": [], \"attestationRootCertificates\": [ \"MII....psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==\" ], \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAA....k5+36hF7vXAAAAAElFTkSuQmCC\", \"authenticatorGetInfo\": { \"versions\": [ \"FIDO_2_0\", \"FIDO_2_1_PRE\", \"FIDO_2_1\" ], \"extensions\": [ \"credProtect\", \"hmac-secret\", \"largeBlobKey\", \"credBlob\", \"minPinLength\" ], \"aaguid\": \"83c.....73cb\", \"options\": { \"plat\": false, \"rk\": true, \"clientPin\": true, \"up\": true, \"uv\": false, \"pinUvAuthToken\": true, \"largeBlobs\": true, \"ep\": false, \"bioEnroll\": false, \"userVerificationMgmtPreview\": false, \"authnrCfg\": true, \"credMgmt\": true, \"credentialMgmtPreview\": true, \"setMinPINLength\": true, \"makeCredUvNotRqd\": false, \"alwaysUv\": true }, \"maxMsgSize\": 1200, \"pinUvAuthProtocols\": [ 2, 1 ], \"maxCredentialCountInList\": 8, \"maxCredentialIdLength\": 128, \"transports\": [ \"usb\" ], \"algorithms\": [ { \"type\": \"public-key\", \"alg\": -7 }, { \"type\": \"public-key\", \"alg\": -8 } ], \"maxSerializedLargeBlobArray\": 1024, \"forcePINChange\": false, \"minPINLength\": 4, \"firmwareVersion\": 328965, \"maxCredBlobLength\": 32, \"maxRPIDsForSetMinPINLength\": 1, \"preferredPlatformUvAttempts\": 3, \"uvModality\": 2, \"remainingDiscoverableCredentials\": 25 } }, \"statusReports\": [ { \"status\": \"FIDO_CERTIFIED_L1\", \"effectiveDate\": \"2021-08-06\", \"url\": \"www.yubico.com\", \"certificationDescriptor\": \"An example\", \"certificateNumber\": \"FIDO2.....001\", \"certificationPolicyVersion\": \"1.3\", \"certificationRequirementsVersion\": \"1.4\" }, { \"status\": \"FIDO_CERTIFIED\", \"effectiveDate\": \"2021-08-06\" } ], \"timeOfLastStatusChange\": \"2021-08-16\" }", "title": "1. Local metadata service:"}, {"location": "janssen-server/fido/vendor-metadata/#2-metadata-service-for-authenticators-approved-by-fido-alliance-mds3", "text": "Metadata entries for trusted authenticators registered with FIDO Alliance can be found on - https://fidoalliance.org/certification/fido-certified-products/ Draw.io reference for image: <?xml version=\"1.0\" encoding=\"UTF-8\"?> <mxfile host=\"app.diagrams.net\" modified=\"2022-11-03T13:17:35.619Z\" agent=\"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.52\" etag=\"MPAHjBuOoBSpVro-BGSI\" version=\"20.5.1\" type=\"google\"><diagram id=\"An1oD0C01MiJfx2t8ul6\" name=\"Page-1\">7Vlbc6M2FP41nrYPyXAx2Hl07HUv052kdWe7fVRAAU0EokLEdn/9noOEsQBnva6ZnZ3ZJ3M+ISG+79yEJ/4y2/0sSZG+FzHlE8+JdxN/NfE8158F8IPIXiOzYKqBRLLY3NQCG/YfNaBj0IrFtLRuVEJwxQobjESe00hZGJFSbO3bngW3n1qQhPaATUR4H/2bxSrV6DxwWvwXypK0ebLrmJGMNDcboExJLLZHkP9u4i+lEEpfZbsl5Uhew4uetz4xetiYpLk6Z0L6cRW7f/0ZB+E2cD9U+8dy+ceNUeeV8Mq88G8kL2/Wv64eEN9Q+Uql2b/aN6SUW5ZxkoN1/yxyZVRz52Cb9ahUdHdyo+7h9cFvqMioknu4xUyY+oYx4zJzY25b/g9Yesx9aEBiNE8OS7e0wIVh5gtY8nssIUGALDhnJI/oDyUY76kiMVGk5ooomuH7wm7yGJ1WVqW2olQMMJqSAi9zoZDVbcoU3RQkQmwLkQVYqjKOLMPlE4leEimqPH6oFGc5NXhM5MsDzGIKqXNuneBcRU47x0mZvMBSaRr0VLoL+iLNg5E0mvY0+l1AGNu6bFpdvn0B3FlHgbCnwGxAgdlYCsx6CvRYpnm8wKQMVsRJWbLI5rWmlOJDnJO5hca9jH0ZjUc8BQPppMEk5USxV/uZQ+SZJzwKVsf9zqbbiORNO0mqFJWMqJl0nL7fXsf1O+soIhOqeuvUSh5e+nJxwy9NgVg6GISPF3KFEQM5L0zw6sdUKSzeC9yjt35msSBmjVshE9zdYZX1Tz0Xsl3kM3E6QnUKHLs6+d655amr/NUCbz4QeJp1fH+LvvDfSjQDN2XNDOjguF6xq+lpxhuxoGPJuSBIOPZYBWw2JBmynD+Vhb6R6wlr/TA9rycbEK5sbQhnSY6JAIiHHsO/R1kYpOyFGchYHOP0e0lhp+SpXgpFL9DJaxKD+0mwwrUqJUqjM5ilkuKFLgWHSospXXcqjPMuNL57eGHfPVxvwD1G8467/+8d8xPe0aSASqVAD2insLU5zyEujmPvOkK5ri3UoXE/Fmo2FMfeWEo1OxqvggI3cv/RDNbGP3WfEjTmanc8uNo31o4pnObeOk5obD0TD3jabqeicTzzkUoGDGGQ19gZddxAuji+RZlpzXX1+1z9+lo9gD/r1Iy7C5uAqddZqJs1Ru4CXHd0D208zfKyt33siv5091XdZN6pHe6lbtI5QfdOxmO7iTdeR7JQiuLxmon8e+9hlzS/W9L8fkkb6kxHaz3c/oeTq/UenabD+QB559vpPuzDnD/UJA4pNR9Nqf7nk6tFLLCiyAvFLUDIOsNNoxNhBD6jeRTZ7amxe+7QX9UkTViJEYzUAXOH1ZsT5fcU0el65x3PG/q4OlTiLvi2Cmb7dVuXlvY/Av/dJw==</diagram></mxfile> Janssen's FIDO2 server - Downloads, verifies and caches metadata BLOBs from the FIDO Metadata Service. Re-downloads the metadata BLOB when it expires. Provides trust root certificates for verifying attestation statements during credential registrations.", "title": "2. Metadata service for authenticators approved by FIDO Alliance (MDS3)"}, {"location": "janssen-server/fido/vendor-metadata/#3-skip-metadata-validation", "text": "Metadata validation is recommended but not mandatory as per FIDO2 specifications. In FIDO2 we can disable this validation by setting the attestionMode parameter (default is monitor). It should look something like this: \"fido2Configuration\": { ..., \"attestationMode\": \"disabled\", ... }", "title": "3. Skip metadata validation"}, {"location": "janssen-server/fido/vendor-metadata/#4-how-apple-does-it-differently", "text": "If you check attStmt and it contains x5c , it is a FULL attestation. FULL basically means that it is a certificate that is chained to the vendor. It's signed by a batch private key whose public key is in a batch certificate that is chained to the Apple attestation root certificate. Usually certificates have an authorityInfoAccess extension that helps locate the root, but Apple chose not to do that. Nevertheless, a quick google give us the needed root certificate https://www.apple.com/certificateauthority/Apple_WebAuthn_Root_CA.pem. This certificate is downloaded to the path /etc/jans/conf/fido2/authenticator_cert . You can see more details of the implementation in this link from https://medium.com/webauthnworks/webauthn-fido2-verifying-apple-anonymous-attestation-5eaff334c849.", "title": "4. How Apple does it differently"}, {"location": "janssen-server/fido/vendor-metadata/#references", "text": "https://fidoalliance.org/announcing-the-new-streamlined-and-simplified-metadata-service-for-authenticator-vendors-and-customers/", "title": "References:"}, {"location": "janssen-server/install/install-faq/", "tags": ["administration", "installation", "faq"], "text": "Janssen Server Installation FAQs # After installation, how do I verify that the Janssen Server is up and running? # Health and status of Janssen Server and its various processes can be verified in multiple ways: Use the Janssen Server Health Check endpoint # Janssen Server provides a health check endpoint for Authentication module. It can be invoked from commandline using CURL as below: curl -k https://janssen-host-name/jans-auth/sys/health-check For a healthy server, this option will return output as below: Please wait while retrieving data ... { \"status\": \"running\", \"db_status\": \"online\" } Access .well-known endpoints # Janssen Server exposes .well-known endpoint for openid configuration as per the OpenIDConnect RFC . Successful response from this endpoint is also an indicator of healthy authentication module. From command-line interface, use CURL to access this endpoint. For example: curl https://janssen-host-name/jans-auth/.well-known/openid-configuration This should return JSON response from Janssen Server as per OpenId specification. Sample below: { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://janssen-host-name\", \"userinfo_encryption_enc_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"authorization_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"user_name\", \"formatted\", \"phone_mobile_number\", \"preferred_username\", \"inum\", \"locale\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"FORM_POST\", \"QUERY_JWT\", \"FRAGMENT_JWT\", \"FORM_POST_JWT\", \"QUERY\", \"FRAGMENT\", \"JWT\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/token\", \"response_types_supported\" : [ \"id_token token\", \"id_token\", \"code\", \"code token\", \"id_token code token\", \"id_token code\", \"token\" ], \"acr_mappings\" : {\"alias1\": \"acr1\"}, \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"RESOURCE_OWNER_PASSWORD_CREDENTIALS\", \"CLIENT_CREDENTIALS\", \"OXAUTH_UMA_TICKET\", \"AUTHORIZATION_CODE\", \"DEVICE_CODE\", \"REFRESH_TOKEN\", \"IMPLICIT\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/userinfo\", \"op_tos_uri\" : \"http://www.jans.io/doku.php?id=jans:tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"session_revocation_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/revoke_session\", \"global_token_revocation_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/global-token-revocation\", \"check_session_iframe\" : \"https://janssen-host-name/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"https://jans.io/scim/all-resources.search\", \"address\", \"user_name\", \"clientinfo\", \"openid\", \"https://jans.io/scim/fido2.write\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/fido.read\", \"https://jans.io/scim/users.write\", \"https://jans.io/scim/groups.read\", \"revoke_session\", \"global_token_revocation\", \"https://jans.io/scim/fido.write\", \"https://jans.io/scim/bulk\", \"https://jans.io/scim/users.read\", \"phone\", \"mobile_phone\", \"offline_access\", \"https://jans.io/scim/groups.write\", \"email\", \"https://jans.io/scim/fido2.read\", \"jans_client_api\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], ... ... Check OS Services # Check the OS platform Janssen Services and their status Check Logs # Check logs for errors How can I see status of Janssen OS platform services? # Ubuntu # systemctl list-units --all \"jans*\" Command above should list services along with its current status. UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed. Note Some process listed above may not be available in every installation based on options selected during installation. Where can I find Janssen Server logs? # During installation, Janssen Server produces setup logs under following location: /opt/jans/jans-setup/logs/ Individual modules of the Janssen Server will continue to write their operational logs under respective directory at path below: /opt/jans/jetty/<module-name>/logs/ How do I check the version of Janssen server? # /opt/jans/bin/show_version.py Alternatively, TUI can be used to get this information: Open TUI Navigate to Jans TUI menu item on top menu bar Navigate to Application Versions Hit enter This will show version of each Janssen Server modules: After installation, what's next? # After successful installation of the Janssen Server, start configuring Janssen Server to fulfil your organizational requirements and authentication flows you intend to implement. Use the Text-based UI or command-line interface to configure the Janssen Server. Does the Janssen Server uninstall process remove the data store as well? # No. For all persistence options, the Janssen server uninstall steps ( this for instance) will only remove the Janssen Server software and it'll keep the data store untouched. Removing the data store is at the discretion of the administrator and it is a manual step. If not removed before attempting a reinstall of the Janssen Server, the installer would fail due to the existence of the previous data store.", "title": "FAQ"}, {"location": "janssen-server/install/install-faq/#janssen-server-installation-faqs", "text": "", "title": "Janssen Server Installation FAQs"}, {"location": "janssen-server/install/install-faq/#after-installation-how-do-i-verify-that-the-janssen-server-is-up-and-running", "text": "Health and status of Janssen Server and its various processes can be verified in multiple ways:", "title": "After installation, how do I verify that the Janssen Server is up and running?"}, {"location": "janssen-server/install/install-faq/#use-the-janssen-server-health-check-endpoint", "text": "Janssen Server provides a health check endpoint for Authentication module. It can be invoked from commandline using CURL as below: curl -k https://janssen-host-name/jans-auth/sys/health-check For a healthy server, this option will return output as below: Please wait while retrieving data ... { \"status\": \"running\", \"db_status\": \"online\" }", "title": "Use the Janssen Server Health Check endpoint"}, {"location": "janssen-server/install/install-faq/#access-well-known-endpoints", "text": "Janssen Server exposes .well-known endpoint for openid configuration as per the OpenIDConnect RFC . Successful response from this endpoint is also an indicator of healthy authentication module. From command-line interface, use CURL to access this endpoint. For example: curl https://janssen-host-name/jans-auth/.well-known/openid-configuration This should return JSON response from Janssen Server as per OpenId specification. Sample below: { \"request_parameter_supported\" : true, \"pushed_authorization_request_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/par\", \"introspection_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/introspection\", \"claims_parameter_supported\" : false, \"issuer\" : \"https://janssen-host-name\", \"userinfo_encryption_enc_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"id_token_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"authorization_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/authorize\", \"service_documentation\" : \"http://jans.org/docs\", \"authorization_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"claims_supported\" : [ \"street_address\", \"country\", \"zoneinfo\", \"birthdate\", \"role\", \"gender\", \"user_name\", \"formatted\", \"phone_mobile_number\", \"preferred_username\", \"inum\", \"locale\", \"updated_at\", \"post_office_box\", \"nickname\", \"preferred_language\", \"email\", \"website\", \"email_verified\", \"profile\", \"locality\", \"room_number\", \"phone_number_verified\", \"given_name\", \"middle_name\", \"picture\", \"name\", \"phone_number\", \"postal_code\", \"region\", \"family_name\", \"jansAdminUIRole\" ], \"token_endpoint_auth_methods_supported\" : [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"tls_client_auth\", \"self_signed_tls_client_auth\" ], \"tls_client_certificate_bound_access_tokens\" : true, \"response_modes_supported\" : [ \"FORM_POST\", \"QUERY_JWT\", \"FRAGMENT_JWT\", \"FORM_POST_JWT\", \"QUERY\", \"FRAGMENT\", \"JWT\" ], \"backchannel_logout_session_supported\" : true, \"token_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/token\", \"response_types_supported\" : [ \"id_token token\", \"id_token\", \"code\", \"code token\", \"id_token code token\", \"id_token code\", \"token\" ], \"acr_mappings\" : {\"alias1\": \"acr1\"}, \"authorization_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], \"backchannel_token_delivery_modes_supported\" : [ \"poll\", \"ping\", \"push\" ], \"dpop_signing_alg_values_supported\" : [ \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_uri_parameter_supported\" : true, \"backchannel_user_code_parameter_supported\" : false, \"grant_types_supported\" : [ \"RESOURCE_OWNER_PASSWORD_CREDENTIALS\", \"CLIENT_CREDENTIALS\", \"OXAUTH_UMA_TICKET\", \"AUTHORIZATION_CODE\", \"DEVICE_CODE\", \"REFRESH_TOKEN\", \"IMPLICIT\" ], \"ui_locales_supported\" : [ \"en\", \"bg\", \"de\", \"es\", \"fr\", \"it\", \"ru\", \"tr\" ], \"userinfo_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/userinfo\", \"op_tos_uri\" : \"http://www.jans.io/doku.php?id=jans:tos\", \"require_request_uri_registration\" : false, \"id_token_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"frontchannel_logout_session_supported\" : true, \"authorization_signing_alg_values_supported\" : [ \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"claims_locales_supported\" : [ \"en\" ], \"clientinfo_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/clientinfo\", \"request_object_signing_alg_values_supported\" : [ \"none\", \"HS256\", \"HS384\", \"HS512\", \"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"ES512\", \"PS256\", \"PS384\", \"PS512\" ], \"request_object_encryption_alg_values_supported\" : [ \"RSA1_5\", \"RSA-OAEP\", \"A128KW\", \"A256KW\" ], \"session_revocation_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/revoke_session\", \"global_token_revocation_endpoint\" : \"https://janssen-host-name/jans-auth/restv1/global-token-revocation\", \"check_session_iframe\" : \"https://janssen-host-name/jans-auth/opiframe.htm\", \"scopes_supported\" : [ \"https://jans.io/scim/all-resources.search\", \"address\", \"user_name\", \"clientinfo\", \"openid\", \"https://jans.io/scim/fido2.write\", \"profile\", \"uma_protection\", \"permission\", \"https://jans.io/scim/fido.read\", \"https://jans.io/scim/users.write\", \"https://jans.io/scim/groups.read\", \"revoke_session\", \"global_token_revocation\", \"https://jans.io/scim/fido.write\", \"https://jans.io/scim/bulk\", \"https://jans.io/scim/users.read\", \"phone\", \"mobile_phone\", \"offline_access\", \"https://jans.io/scim/groups.write\", \"email\", \"https://jans.io/scim/fido2.read\", \"jans_client_api\" ], \"backchannel_logout_supported\" : true, \"acr_values_supported\" : [ \"simple_password_auth\" ], \"request_object_encryption_enc_values_supported\" : [ \"A128CBC+HS256\", \"A256CBC+HS512\", \"A128GCM\", \"A256GCM\" ], ... ...", "title": "Access .well-known endpoints"}, {"location": "janssen-server/install/install-faq/#check-os-services", "text": "Check the OS platform Janssen Services and their status", "title": "Check OS Services"}, {"location": "janssen-server/install/install-faq/#check-logs", "text": "Check logs for errors", "title": "Check Logs"}, {"location": "janssen-server/install/install-faq/#how-can-i-see-status-of-janssen-os-platform-services", "text": "", "title": "How can I see status of Janssen OS platform services?"}, {"location": "janssen-server/install/install-faq/#ubuntu", "text": "systemctl list-units --all \"jans*\" Command above should list services along with its current status. UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed. Note Some process listed above may not be available in every installation based on options selected during installation.", "title": "Ubuntu"}, {"location": "janssen-server/install/install-faq/#where-can-i-find-janssen-server-logs", "text": "During installation, Janssen Server produces setup logs under following location: /opt/jans/jans-setup/logs/ Individual modules of the Janssen Server will continue to write their operational logs under respective directory at path below: /opt/jans/jetty/<module-name>/logs/", "title": "Where can I find Janssen Server logs?"}, {"location": "janssen-server/install/install-faq/#how-do-i-check-the-version-of-janssen-server", "text": "/opt/jans/bin/show_version.py Alternatively, TUI can be used to get this information: Open TUI Navigate to Jans TUI menu item on top menu bar Navigate to Application Versions Hit enter This will show version of each Janssen Server modules:", "title": "How do I check the version of Janssen server?"}, {"location": "janssen-server/install/install-faq/#after-installation-whats-next", "text": "After successful installation of the Janssen Server, start configuring Janssen Server to fulfil your organizational requirements and authentication flows you intend to implement. Use the Text-based UI or command-line interface to configure the Janssen Server.", "title": "After installation, what's next?"}, {"location": "janssen-server/install/install-faq/#does-the-janssen-server-uninstall-process-remove-the-data-store-as-well", "text": "No. For all persistence options, the Janssen server uninstall steps ( this for instance) will only remove the Janssen Server software and it'll keep the data store untouched. Removing the data store is at the discretion of the administrator and it is a manual step. If not removed before attempting a reinstall of the Janssen Server, the installer would fail due to the existence of the previous data store.", "title": "Does the Janssen Server uninstall process remove the data store as well?"}, {"location": "janssen-server/install/setup/", "tags": ["administration", "installation", "setup"], "text": "Janssen Setup Script # Running Setup # After installation, executing setup.py will launch the SETUP Command Line by default. To run the script, run the following command: python3 /opt/jans/jans-setup/setup.py A warning will pop up if the free disk space is less than the recommended 40 GB. The installer will check that all dependant packages are installed or not, and if missing it will ask to install. When prompted Y/y at the command prompt will install all required packages. The installer will detect which operating system, init type, and Apache version are currently on the server. The setup script will bring up a prompt to provide information for certificates as well as the IP Address and the hostname for the Janssen Authorization Server. Hit Enter to accept the default values. Enter IP Address: Enter hostname: Enter your city or locality: Enter your state or province two letter code: Enter two letter Country Code Enter Organization name: Enter email address for support at your organization: Enter maximum RAM for applications in MB: Enter Password for Admin User: Next, pick a persistence mechanism. Choose from MySQL, PGSql that can be installed locally or remotely. Next, pick which services should be installed for this deployment: bash Install Jans Config API? [Yes] : Install Scim Server? [Yes] : Install Fido2 Server? [Yes] : Install Jans Link Server? [Yes] : Install Gluu Casa? [No] : Finally, review the summary screen that gives an overview of the selections made during the setup process. Note! After setup completed, you will be prompted to remove setup files (directories /opt/dist and /opt/jans/jans-setup ). If you are not going to do any post-setup operations, type yes to remove setup files. If you don't respond in 10 seconds, setup files will be preserved. Avoiding common issues # Avoid setup issues by acknowledging the following: IP Address: Do not use localhost for either the IP address or hostname. Hostname: Make sure to choose the hostname carefully. Changing the hostname after installation is not a simple task. Use a real hostname--this can always be managed via host file entries if adding a DNS entry is too much work for testing. For clustered deployments, use the hostname of the cluster that will be used by applications connecting to Janssen Authorization Server. Warning Use a FQDN (fully qualified domain name) as hostname and refrain from using 127.0.0.1 as IP address or usage of private IP is not supported and not recommended. Script Command Line Options # To check usage of this script run help command python3 /opt/jans/jans-setup/setup.py --help usage: jans_setup.py [-h] [--version] [-c] [-d D] [-f F] [-n] [-N] [-u] [-csx] [-encode-salt ENCODE_SALT] [-remote-rdbm {mysql,pgsql} | -local-rdbm {mysql,pgsql}] [-ip-address IP_ADDRESS] [-host-name HOST_NAME] [-org-name ORG_NAME] [-email EMAIL] [-city CITY] [-state STATE] [-country COUNTRY] [-rdbm-user RDBM_USER] [-rdbm-password RDBM_PASSWORD] [-rdbm-port RDBM_PORT] [-rdbm-db RDBM_DB] [-rdbm-host RDBM_HOST] [--reset-rdbm-db] [--shell] [--dump-config-on-error] [--no-progress] [-admin-password ADMIN_PASSWORD] [-jans-max-mem JANS_MAX_MEM] [-properties-password PROPERTIES_PASSWORD] [-approved-issuer APPROVED_ISSUER] [--force-download] [--download-exit] [-jans-app-version JANS_APP_VERSION] [-jans-build JANS_BUILD] [-setup-branch SETUP_BRANCH] [--disable-config-api-security] [--cli-test-client] [--import-ldif IMPORT_LDIF] [-enable-script ENABLE_SCRIPT] [-disable-script DISABLE_SCRIPT] [-java-version {11,17}] [-stm] [-w] [-t] [-x] [--allow-pre-released-features] [--no-data] [--no-jsauth] [--no-config-api] [--no-scim] [--no-fido2] [--install-jans-ldap-link] [--install-jans-keycloak-link] [--with-casa] [--install-jans-saml] [--install-jans-lock] [--install-opa] [--load-config-api-test] [-config-patch-creds CONFIG_PATCH_CREDS] [-test-client-id TEST_CLIENT_ID] [-test-client-pw TEST_CLIENT_PW] [-test-client-redirect-uri TEST_CLIENT_REDIRECT_URI] [--test-client-trusted] Use this script to configure your Jans Server and to add initial data. If setup.properties is found in this folder, these properties will automatically be used instead of the interactive setup. Below are the optional arguments: Argument Description -h, --help show this help message and exit --version show program's version number and exit -c Use command line instead of TUI -d D Installation directory -f F Specify setup.properties file -n No interactive prompt before install starts. Run with -f -N, --no-httpd No apache httpd server -u Update hosts file with IP address / hostname -csx Collect setup properties, save and exit -remote-rdbm Enables using remote RDBM server -local-rdbm Enables installing/configuring local RDBM server -ip-address IP_ADDRESS Used primarily by Apache httpd for the Listen directive -host-name HOST_NAME Internet-facing FQDN that is used to generate certificates and metadata. -org-name ORG_NAME Organization name field used for generating X.509 certificates -email EMAIL Email address for support at your organization used for generating X.509 certificates -city CITY City field used for generating X.509 certificates -state STATE State field used for generating X.509 certificates -country COUNTRY Two letters country coude used for generating X.509 certificates -rdbm-user RDBM_USER RDBM username -rdbm-password RDBM_PASSWORD RDBM password -rdbm-port RDBM_PORT RDBM port -rdbm-db RDBM_DB RDBM database -rdbm-host RDBM_HOST RDBM host --reset-rdbm-db Deletes all tables on target database. Warning! You will lose all data on target database. --shell Drop into interactive shell before starting installation --dump-config-on-error Dump configuration on error --no-progress Use simple progress -admin-password ADMIN_PASSWORD Used as the Administrator password -jans-max-mem JANS_MAX_MEM Total memory (in KB) to be used by Jannsen Server -properties-password PROPERTIES_PASSWORD Encoded setup.properties file password -approved-issuer APPROVED_ISSUER Api Approved Issuer --force-download Force downloading files --download-exit Download files and exits -jans-app-version JANS_APP_VERSION Version for Jannsen applications -jans-build JANS_BUILD Build version for Janssen applications -setup-branch SETUP_BRANCH Jannsen setup github branch --disable-config-api-security Turn off oauth2 security validation for jans-config-api --cli-test-client Use config api test client for CLI --import-ldif IMPORT_LDIF Render ldif templates from directory and import them in Database -enable-script ENABLE_SCRIPT inum of script to enable -disable-script DISABLE_SCRIPT inum of script to disable -disable-selinux Disable SELinux -stm, --enable-scim-test-mode Enable Scim Test Mode -w Get the development head war files -t Load test data -x Load test data and exit --allow-pre-released-features Enable options to install experimental features, not yet officially supported --no-data Do not import any data to database backend, used for clustering --no-jsauth Do not install OAuth2 Authorization Server --no-config-api Do not install Jans Auth Config Api --no-scim Do not install Scim Server --no-fido2 Do not install Fido2 Server --install-jans-ldap-link Install LDAP Link Server --with-casa Install Gluu/Flex Casa Server --load-config-api-test Load Config Api Test Data --install-cache-refresh Install Cache Refresh Server -config-patch-creds CONFIG_PATCH_CREDS password:username for downloading auto test ciba password -test-client-id TEST_CLIENT_ID ID of test client which has all available scopes. Must be in UUID format. -test-client-pw TEST_CLIENT_PW Secret for test client -test-client-redirect-uri TEST_CLIENT_REDIRECT_URI Redirect URI for test client --test-client-trusted Make test client trusted", "title": "Setup Instructions"}, {"location": "janssen-server/install/setup/#janssen-setup-script", "text": "", "title": "Janssen Setup Script"}, {"location": "janssen-server/install/setup/#running-setup", "text": "After installation, executing setup.py will launch the SETUP Command Line by default. To run the script, run the following command: python3 /opt/jans/jans-setup/setup.py A warning will pop up if the free disk space is less than the recommended 40 GB. The installer will check that all dependant packages are installed or not, and if missing it will ask to install. When prompted Y/y at the command prompt will install all required packages. The installer will detect which operating system, init type, and Apache version are currently on the server. The setup script will bring up a prompt to provide information for certificates as well as the IP Address and the hostname for the Janssen Authorization Server. Hit Enter to accept the default values. Enter IP Address: Enter hostname: Enter your city or locality: Enter your state or province two letter code: Enter two letter Country Code Enter Organization name: Enter email address for support at your organization: Enter maximum RAM for applications in MB: Enter Password for Admin User: Next, pick a persistence mechanism. Choose from MySQL, PGSql that can be installed locally or remotely. Next, pick which services should be installed for this deployment: bash Install Jans Config API? [Yes] : Install Scim Server? [Yes] : Install Fido2 Server? [Yes] : Install Jans Link Server? [Yes] : Install Gluu Casa? [No] : Finally, review the summary screen that gives an overview of the selections made during the setup process. Note! After setup completed, you will be prompted to remove setup files (directories /opt/dist and /opt/jans/jans-setup ). If you are not going to do any post-setup operations, type yes to remove setup files. If you don't respond in 10 seconds, setup files will be preserved.", "title": "Running Setup"}, {"location": "janssen-server/install/setup/#avoiding-common-issues", "text": "Avoid setup issues by acknowledging the following: IP Address: Do not use localhost for either the IP address or hostname. Hostname: Make sure to choose the hostname carefully. Changing the hostname after installation is not a simple task. Use a real hostname--this can always be managed via host file entries if adding a DNS entry is too much work for testing. For clustered deployments, use the hostname of the cluster that will be used by applications connecting to Janssen Authorization Server. Warning Use a FQDN (fully qualified domain name) as hostname and refrain from using 127.0.0.1 as IP address or usage of private IP is not supported and not recommended.", "title": "Avoiding common issues"}, {"location": "janssen-server/install/setup/#script-command-line-options", "text": "To check usage of this script run help command python3 /opt/jans/jans-setup/setup.py --help usage: jans_setup.py [-h] [--version] [-c] [-d D] [-f F] [-n] [-N] [-u] [-csx] [-encode-salt ENCODE_SALT] [-remote-rdbm {mysql,pgsql} | -local-rdbm {mysql,pgsql}] [-ip-address IP_ADDRESS] [-host-name HOST_NAME] [-org-name ORG_NAME] [-email EMAIL] [-city CITY] [-state STATE] [-country COUNTRY] [-rdbm-user RDBM_USER] [-rdbm-password RDBM_PASSWORD] [-rdbm-port RDBM_PORT] [-rdbm-db RDBM_DB] [-rdbm-host RDBM_HOST] [--reset-rdbm-db] [--shell] [--dump-config-on-error] [--no-progress] [-admin-password ADMIN_PASSWORD] [-jans-max-mem JANS_MAX_MEM] [-properties-password PROPERTIES_PASSWORD] [-approved-issuer APPROVED_ISSUER] [--force-download] [--download-exit] [-jans-app-version JANS_APP_VERSION] [-jans-build JANS_BUILD] [-setup-branch SETUP_BRANCH] [--disable-config-api-security] [--cli-test-client] [--import-ldif IMPORT_LDIF] [-enable-script ENABLE_SCRIPT] [-disable-script DISABLE_SCRIPT] [-java-version {11,17}] [-stm] [-w] [-t] [-x] [--allow-pre-released-features] [--no-data] [--no-jsauth] [--no-config-api] [--no-scim] [--no-fido2] [--install-jans-ldap-link] [--install-jans-keycloak-link] [--with-casa] [--install-jans-saml] [--install-jans-lock] [--install-opa] [--load-config-api-test] [-config-patch-creds CONFIG_PATCH_CREDS] [-test-client-id TEST_CLIENT_ID] [-test-client-pw TEST_CLIENT_PW] [-test-client-redirect-uri TEST_CLIENT_REDIRECT_URI] [--test-client-trusted] Use this script to configure your Jans Server and to add initial data. If setup.properties is found in this folder, these properties will automatically be used instead of the interactive setup. Below are the optional arguments: Argument Description -h, --help show this help message and exit --version show program's version number and exit -c Use command line instead of TUI -d D Installation directory -f F Specify setup.properties file -n No interactive prompt before install starts. Run with -f -N, --no-httpd No apache httpd server -u Update hosts file with IP address / hostname -csx Collect setup properties, save and exit -remote-rdbm Enables using remote RDBM server -local-rdbm Enables installing/configuring local RDBM server -ip-address IP_ADDRESS Used primarily by Apache httpd for the Listen directive -host-name HOST_NAME Internet-facing FQDN that is used to generate certificates and metadata. -org-name ORG_NAME Organization name field used for generating X.509 certificates -email EMAIL Email address for support at your organization used for generating X.509 certificates -city CITY City field used for generating X.509 certificates -state STATE State field used for generating X.509 certificates -country COUNTRY Two letters country coude used for generating X.509 certificates -rdbm-user RDBM_USER RDBM username -rdbm-password RDBM_PASSWORD RDBM password -rdbm-port RDBM_PORT RDBM port -rdbm-db RDBM_DB RDBM database -rdbm-host RDBM_HOST RDBM host --reset-rdbm-db Deletes all tables on target database. Warning! You will lose all data on target database. --shell Drop into interactive shell before starting installation --dump-config-on-error Dump configuration on error --no-progress Use simple progress -admin-password ADMIN_PASSWORD Used as the Administrator password -jans-max-mem JANS_MAX_MEM Total memory (in KB) to be used by Jannsen Server -properties-password PROPERTIES_PASSWORD Encoded setup.properties file password -approved-issuer APPROVED_ISSUER Api Approved Issuer --force-download Force downloading files --download-exit Download files and exits -jans-app-version JANS_APP_VERSION Version for Jannsen applications -jans-build JANS_BUILD Build version for Janssen applications -setup-branch SETUP_BRANCH Jannsen setup github branch --disable-config-api-security Turn off oauth2 security validation for jans-config-api --cli-test-client Use config api test client for CLI --import-ldif IMPORT_LDIF Render ldif templates from directory and import them in Database -enable-script ENABLE_SCRIPT inum of script to enable -disable-script DISABLE_SCRIPT inum of script to disable -disable-selinux Disable SELinux -stm, --enable-scim-test-mode Enable Scim Test Mode -w Get the development head war files -t Load test data -x Load test data and exit --allow-pre-released-features Enable options to install experimental features, not yet officially supported --no-data Do not import any data to database backend, used for clustering --no-jsauth Do not install OAuth2 Authorization Server --no-config-api Do not install Jans Auth Config Api --no-scim Do not install Scim Server --no-fido2 Do not install Fido2 Server --install-jans-ldap-link Install LDAP Link Server --with-casa Install Gluu/Flex Casa Server --load-config-api-test Load Config Api Test Data --install-cache-refresh Install Cache Refresh Server -config-patch-creds CONFIG_PATCH_CREDS password:username for downloading auto test ciba password -test-client-id TEST_CLIENT_ID ID of test client which has all available scopes. Must be in UUID format. -test-client-pw TEST_CLIENT_PW Secret for test client -test-client-redirect-uri TEST_CLIENT_REDIRECT_URI Redirect URI for test client --test-client-trusted Make test client trusted", "title": "Script Command Line Options"}, {"location": "janssen-server/install/docker-install/compose/", "tags": ["administration", "installation", "quick-start", "docker compose", "docker image"], "text": "Warning This image is for testing and development purposes only. Use Janssen helm charts for production setups. Overview # Docker monolith image packaging for Janssen. This image packs janssen services including the auth-server, config-api, fido2, and scim. Pre-requisites # Docker Docker compose Environment Variables # Installation depends on the set of environment variables shown below. These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. ENV Description Default CN_HOSTNAME Hostname to install janssen with. demoexample.jans.io CN_ADMIN_PASS Password of the admin user. 1t5Fin3#security CN_ORG_NAME Organization name. Used for ssl cert generation. Janssen CN_EMAIL Email. Used for ssl cert generation. support@jans.io CN_CITY City. Used for ssl cert generation. Austin CN_STATE State. Used for ssl cert generation TX CN_COUNTRY Country. Used for ssl cert generation. US CN_INSTALL_MYSQL Install jans with mysql as the backend false CN_INSTALL_PGSQL Install jans with Postgres as the backend false CN_INSTALL_CONFIG_API Installs the Config API service. true CN_INSTALL_SCIM Installs the SCIM API service. true CN_INSTALL_FIDO2 Installs the FIDO2 API service. true RDBMS_DATABASE RDBMS jans database for MySQL or Postgres. jans RDBMS_USER RDBMS database user for MySQL or Postgres. jans RDBMS_PASSWORD RDBMS database user password for MySQL or Postgres. 1t5Fin3#security RDBMS_HOST RDBMS host for MySQL or Postgres. mysql which is the docker compose service name TEST_CLIENT_ID ID of test client in UUID which has all available scopes to access any jans API 9876baac-de39-4c23-8a78-674b59df8c09 TEST_CLIENT_SECRET Secret for test client 1t5Fin3#security TEST_CLIENT_TRUSTED Trust test client true TEST_CLIENT_REDIRECT_URI Not Implemented yet Redirect URI for test client. Multiple uri's with comma may be provided, if not provided redirect uris will be same as the config-api-client `` How to run # Download the compose file of your chosen persistence from mysql or postgres wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-mysql-compose.yml wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-postgres-compose.yml Download the script files wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/up.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/down.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/clean.sh Give execute permission to the scripts chmod u+x up.sh down.sh clean.sh This docker compose file runs two containers, the janssen monolith container and mysql container. To start the containers. ./up.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. To view the containers running docker compose -f jans-mysql-compose.yml ps To stop the containers. ./down.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. Configure Janssen Server # Access the Docker container shell using: docker compose -f jans-mysql-compose.yml exec jans /bin/bash #This opens a bash terminal in the running container You can grab client_id and client_pw (secret) pairs and other values from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Janssen as needed. For example you can run the TUI : python3 /opt/jans/jans-cli/config-cli-tui.py Access endpoints externally # Add to your /etc/hosts file the ip domain record which should be the ip of the instance docker is installed at and the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record you can hit endpoints such as https://demoexample.jans.io/.well-known/openid-configuration Clean up # Remove setup and volumes ./clean.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "Docker compose"}, {"location": "janssen-server/install/docker-install/compose/#overview", "text": "Docker monolith image packaging for Janssen. This image packs janssen services including the auth-server, config-api, fido2, and scim.", "title": "Overview"}, {"location": "janssen-server/install/docker-install/compose/#pre-requisites", "text": "Docker Docker compose", "title": "Pre-requisites"}, {"location": "janssen-server/install/docker-install/compose/#environment-variables", "text": "Installation depends on the set of environment variables shown below. These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. ENV Description Default CN_HOSTNAME Hostname to install janssen with. demoexample.jans.io CN_ADMIN_PASS Password of the admin user. 1t5Fin3#security CN_ORG_NAME Organization name. Used for ssl cert generation. Janssen CN_EMAIL Email. Used for ssl cert generation. support@jans.io CN_CITY City. Used for ssl cert generation. Austin CN_STATE State. Used for ssl cert generation TX CN_COUNTRY Country. Used for ssl cert generation. US CN_INSTALL_MYSQL Install jans with mysql as the backend false CN_INSTALL_PGSQL Install jans with Postgres as the backend false CN_INSTALL_CONFIG_API Installs the Config API service. true CN_INSTALL_SCIM Installs the SCIM API service. true CN_INSTALL_FIDO2 Installs the FIDO2 API service. true RDBMS_DATABASE RDBMS jans database for MySQL or Postgres. jans RDBMS_USER RDBMS database user for MySQL or Postgres. jans RDBMS_PASSWORD RDBMS database user password for MySQL or Postgres. 1t5Fin3#security RDBMS_HOST RDBMS host for MySQL or Postgres. mysql which is the docker compose service name TEST_CLIENT_ID ID of test client in UUID which has all available scopes to access any jans API 9876baac-de39-4c23-8a78-674b59df8c09 TEST_CLIENT_SECRET Secret for test client 1t5Fin3#security TEST_CLIENT_TRUSTED Trust test client true TEST_CLIENT_REDIRECT_URI Not Implemented yet Redirect URI for test client. Multiple uri's with comma may be provided, if not provided redirect uris will be same as the config-api-client ``", "title": "Environment Variables"}, {"location": "janssen-server/install/docker-install/compose/#how-to-run", "text": "Download the compose file of your chosen persistence from mysql or postgres wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-mysql-compose.yml wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-postgres-compose.yml Download the script files wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/up.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/down.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/clean.sh Give execute permission to the scripts chmod u+x up.sh down.sh clean.sh This docker compose file runs two containers, the janssen monolith container and mysql container. To start the containers. ./up.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. To view the containers running docker compose -f jans-mysql-compose.yml ps To stop the containers. ./down.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "How to run"}, {"location": "janssen-server/install/docker-install/compose/#configure-janssen-server", "text": "Access the Docker container shell using: docker compose -f jans-mysql-compose.yml exec jans /bin/bash #This opens a bash terminal in the running container You can grab client_id and client_pw (secret) pairs and other values from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Janssen as needed. For example you can run the TUI : python3 /opt/jans/jans-cli/config-cli-tui.py", "title": "Configure Janssen Server"}, {"location": "janssen-server/install/docker-install/compose/#access-endpoints-externally", "text": "Add to your /etc/hosts file the ip domain record which should be the ip of the instance docker is installed at and the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record you can hit endpoints such as https://demoexample.jans.io/.well-known/openid-configuration", "title": "Access endpoints externally"}, {"location": "janssen-server/install/docker-install/compose/#clean-up", "text": "Remove setup and volumes ./clean.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "Clean up"}, {"location": "janssen-server/install/docker-install/quick-start/", "tags": ["administration", "installation", "quick-start", "docker"], "text": "Warning This image is for testing and development purposes only. Use Janssen helm charts for production setups. Overview # The quickest way to get a Janssen Server up and running is to install a Docker container-based fully featured Janssen Server. System Requirements # System should meet minimum VM system requirements Install # Installation depends on a set of environment variables . These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. Run this command to start the installation: wget https://raw.githubusercontent.com/JanssenProject/jans/vreplace-janssen-version/automation/startjanssenmonolithdemo.sh && chmod u+x startjanssenmonolithdemo.sh && sudo bash startjanssenmonolithdemo.sh demoexample.jans.io MYSQL \"\" main Console messages like below confirms the successful installation: [+] Running 3/3 \u283f Network docker-jans-monolith_cloud_bridge Created 0.0s \u283f Container docker-jans-monolith-mysql-1 Started 0.6s \u283f Container docker-jans-monolith-jans-1 Started 0.9s Waiting for the Janssen server to come up. Depending on the resources it may take 3-5 mins for the services to be up. Testing openid-configuration endpoint.. As can be seen, the install script also accesses the well-known endpoints to varify that Janssen Server is responsive. Verify Installation By Accessing Standard Endpoints # To access Janssen Server standard endpoints from outside of the Docker container, systems /etc/hosts file needs to be updated. Open the file and add the IP domain record which should be the IP of the instance docker is installed. And the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record, hit the standard endpoints such as https://demoexample.jans.io/.well-known/openid-configuration Configure Janssen Server # Access the Docker container shell using: docker exec -ti docker-jans-monolith-jans-1 bash Grab a pair of client_id and client_pw(secret) from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Janssen Server as needed. For example you can run the TUI : jans tui Uninstall / Remove the Janssen Server # This docker based installation uses docker compose under the hood to create containers. Hence uninstalling Janssen server involves invoking docker compose with appropriate yml file. Run command below to stop and remove containers. docker compose -f /tmp/jans/docker-jans-monolith/jans-mysql-compose.yml down && rm -rf jans-* Console messages like below confirms the successful removal: [+] Running 3/3 \u283f Container docker-jans-monolith-jans-1 Removed 10.5s \u283f Container docker-jans-monolith-mysql-1 Removed 0.9s \u283f Network docker-jans-monolith_cloud_bridge Removed 0.1s", "title": "Quick Start"}, {"location": "janssen-server/install/docker-install/quick-start/#overview", "text": "The quickest way to get a Janssen Server up and running is to install a Docker container-based fully featured Janssen Server.", "title": "Overview"}, {"location": "janssen-server/install/docker-install/quick-start/#system-requirements", "text": "System should meet minimum VM system requirements", "title": "System Requirements"}, {"location": "janssen-server/install/docker-install/quick-start/#install", "text": "Installation depends on a set of environment variables . These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. Run this command to start the installation: wget https://raw.githubusercontent.com/JanssenProject/jans/vreplace-janssen-version/automation/startjanssenmonolithdemo.sh && chmod u+x startjanssenmonolithdemo.sh && sudo bash startjanssenmonolithdemo.sh demoexample.jans.io MYSQL \"\" main Console messages like below confirms the successful installation: [+] Running 3/3 \u283f Network docker-jans-monolith_cloud_bridge Created 0.0s \u283f Container docker-jans-monolith-mysql-1 Started 0.6s \u283f Container docker-jans-monolith-jans-1 Started 0.9s Waiting for the Janssen server to come up. Depending on the resources it may take 3-5 mins for the services to be up. Testing openid-configuration endpoint.. As can be seen, the install script also accesses the well-known endpoints to varify that Janssen Server is responsive.", "title": "Install"}, {"location": "janssen-server/install/docker-install/quick-start/#verify-installation-by-accessing-standard-endpoints", "text": "To access Janssen Server standard endpoints from outside of the Docker container, systems /etc/hosts file needs to be updated. Open the file and add the IP domain record which should be the IP of the instance docker is installed. And the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record, hit the standard endpoints such as https://demoexample.jans.io/.well-known/openid-configuration", "title": "Verify Installation By Accessing Standard Endpoints"}, {"location": "janssen-server/install/docker-install/quick-start/#configure-janssen-server", "text": "Access the Docker container shell using: docker exec -ti docker-jans-monolith-jans-1 bash Grab a pair of client_id and client_pw(secret) from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Janssen Server as needed. For example you can run the TUI : jans tui", "title": "Configure Janssen Server"}, {"location": "janssen-server/install/docker-install/quick-start/#uninstall-remove-the-janssen-server", "text": "This docker based installation uses docker compose under the hood to create containers. Hence uninstalling Janssen server involves invoking docker compose with appropriate yml file. Run command below to stop and remove containers. docker compose -f /tmp/jans/docker-jans-monolith/jans-mysql-compose.yml down && rm -rf jans-* Console messages like below confirms the successful removal: [+] Running 3/3 \u283f Container docker-jans-monolith-jans-1 Removed 10.5s \u283f Container docker-jans-monolith-mysql-1 Removed 0.9s \u283f Network docker-jans-monolith_cloud_bridge Removed 0.1s", "title": "Uninstall / Remove the Janssen Server"}, {"location": "janssen-server/install/helm-install/amazon-eks/", "tags": ["administration", "installation", "helm", "EKS", "Amazon Web Services", "AWS"], "text": "Install Janssen on EKS # System Requirements # The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0 Initial Setup # Install aws cli Configure your AWS user account using aws configure command. This makes you able to authenticate before creating the cluster. Note that this user account must have permissions to work with Amazon EKS IAM roles and service linked roles, AWS CloudFormation, and a VPC and related resources Install kubectl Install eksctl Create cluster using eksctl such as the following example: eksctl create cluster --name janssen-cluster --nodegroup-name jans-nodes --node-type NODE_TYPE --nodes 2 --managed --region REGION_CODE You can adjust node-type and nodes number as per your desired cluster size To be able to attach volumes to your pod, you need to install the Amazon EBS CSI driver Install Helm3 Create jans namespace where our resources will reside kubectl create namespace jans Jans Installation using Helm # Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer address: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].hostname}' Add the following yaml snippet to your override.yaml file: global : isFqdnRegistered : false config : configmap : lbAddr : http:// #Add LB address from previous command FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : lbAddr : http:// #Add LB address from previous command nginx : ingress : enabled : true path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Amazon RDS For testing purposes, you can deploy it on the EKS cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Amazon RDS For testing purposes, you can deploy it on the EKS cluster using the following commands: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : lbAddr : http:// #Add LB address from previous command cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml Configure Janssen # You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Amazon EKS"}, {"location": "janssen-server/install/helm-install/amazon-eks/#install-janssen-on-eks", "text": "", "title": "Install Janssen on EKS"}, {"location": "janssen-server/install/helm-install/amazon-eks/#system-requirements", "text": "The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0", "title": "System Requirements"}, {"location": "janssen-server/install/helm-install/amazon-eks/#initial-setup", "text": "Install aws cli Configure your AWS user account using aws configure command. This makes you able to authenticate before creating the cluster. Note that this user account must have permissions to work with Amazon EKS IAM roles and service linked roles, AWS CloudFormation, and a VPC and related resources Install kubectl Install eksctl Create cluster using eksctl such as the following example: eksctl create cluster --name janssen-cluster --nodegroup-name jans-nodes --node-type NODE_TYPE --nodes 2 --managed --region REGION_CODE You can adjust node-type and nodes number as per your desired cluster size To be able to attach volumes to your pod, you need to install the Amazon EBS CSI driver Install Helm3 Create jans namespace where our resources will reside kubectl create namespace jans", "title": "Initial Setup"}, {"location": "janssen-server/install/helm-install/amazon-eks/#jans-installation-using-helm", "text": "Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer address: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].hostname}' Add the following yaml snippet to your override.yaml file: global : isFqdnRegistered : false config : configmap : lbAddr : http:// #Add LB address from previous command FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : lbAddr : http:// #Add LB address from previous command nginx : ingress : enabled : true path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Amazon RDS For testing purposes, you can deploy it on the EKS cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Amazon RDS For testing purposes, you can deploy it on the EKS cluster using the following commands: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : lbAddr : http:// #Add LB address from previous command cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml", "title": "Jans Installation using Helm"}, {"location": "janssen-server/install/helm-install/amazon-eks/#configure-janssen", "text": "You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Configure Janssen"}, {"location": "janssen-server/install/helm-install/google-gke/", "tags": ["administration", "installation", "helm", "GKE", "Google Cloud", "GCP"], "text": "Install Janssen on GKE # System Requirements # The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0 Initial Setup # Enable GKE API if not enabled yet. If you are using Cloud Shell , you can skip to step 6. Install gcloud . Install kubectl using gcloud components install kubectl command. Install Helm3 . Create cluster using a command such as the following example: gcloud container clusters create janssen-cluster --num-nodes 2 --machine-type e2-standard-4 --zone us-west1-a You can adjust num-nodes and machine-type as per your desired cluster size Create jans namespace where our resources will reside kubectl create namespace jans Jans Installation using Helm # Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer IP: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].ip}' Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the Loadbalance IP from the previous command isFqdnRegistered : false FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the LoadBalancer IP from the previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Cloud SQL For testing purposes, you can deploy it on the GKE cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Cloud SQL For testing purposes, you can deploy it on the GKE cluster using the following command: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql lbIp : \"\" #Add the LoadBalancer IP from previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml Configure Janssen # You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Google GKE"}, {"location": "janssen-server/install/helm-install/google-gke/#install-janssen-on-gke", "text": "", "title": "Install Janssen on GKE"}, {"location": "janssen-server/install/helm-install/google-gke/#system-requirements", "text": "The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0", "title": "System Requirements"}, {"location": "janssen-server/install/helm-install/google-gke/#initial-setup", "text": "Enable GKE API if not enabled yet. If you are using Cloud Shell , you can skip to step 6. Install gcloud . Install kubectl using gcloud components install kubectl command. Install Helm3 . Create cluster using a command such as the following example: gcloud container clusters create janssen-cluster --num-nodes 2 --machine-type e2-standard-4 --zone us-west1-a You can adjust num-nodes and machine-type as per your desired cluster size Create jans namespace where our resources will reside kubectl create namespace jans", "title": "Initial Setup"}, {"location": "janssen-server/install/helm-install/google-gke/#jans-installation-using-helm", "text": "Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer IP: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].ip}' Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the Loadbalance IP from the previous command isFqdnRegistered : false FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the LoadBalancer IP from the previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Cloud SQL For testing purposes, you can deploy it on the GKE cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Cloud SQL For testing purposes, you can deploy it on the GKE cluster using the following command: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql lbIp : \"\" #Add the LoadBalancer IP from previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml", "title": "Jans Installation using Helm"}, {"location": "janssen-server/install/helm-install/google-gke/#configure-janssen", "text": "You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Configure Janssen"}, {"location": "janssen-server/install/helm-install/local/", "tags": ["administration", "installation", "helm"], "text": "Install Janssen Server Locally with minikube and MicroK8s # System Requirements # For local deployments like minikube and MicroK8s or cloud installations in demo mode, resources may be set to the minimum as below: 8 GB RAM 4 CPU cores 50 GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may increase or decrease. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0 Installation Steps # Start a fresh Ubuntu 18.04 / 20.04 / 22.04 VM with ports 443 and 80 open. Then execute the following: sudo su - wget https://raw.githubusercontent.com/JanssenProject/jans/vreplace-janssen-version/automation/startjanssendemo.sh && chmod u+x startjanssendemo.sh && ./startjanssendemo.sh This will install Docker, Microk8s, Helm and Janssen with the default settings that can be found inside values.yaml . The installer will automatically add a record to your hosts record in the VM but if you want to access the endpoints outside the VM you must map the ip of the instance running Ubuntu to the FQDN you provided and then access the endpoints at your browser such in the example in the table below. Service Example endpoint Auth server https://FQDN/.well-known/openid-configuration fido2 https://FQDN/.well-known/fido2-configuration scim https://FQDN/.well-known/scim-configuration Configure Janssen # You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Local Kubernetes Cluster"}, {"location": "janssen-server/install/helm-install/local/#install-janssen-server-locally-with-minikube-and-microk8s", "text": "", "title": "Install Janssen Server Locally with minikube and MicroK8s"}, {"location": "janssen-server/install/helm-install/local/#system-requirements", "text": "For local deployments like minikube and MicroK8s or cloud installations in demo mode, resources may be set to the minimum as below: 8 GB RAM 4 CPU cores 50 GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may increase or decrease. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0", "title": "System Requirements"}, {"location": "janssen-server/install/helm-install/local/#installation-steps", "text": "Start a fresh Ubuntu 18.04 / 20.04 / 22.04 VM with ports 443 and 80 open. Then execute the following: sudo su - wget https://raw.githubusercontent.com/JanssenProject/jans/vreplace-janssen-version/automation/startjanssendemo.sh && chmod u+x startjanssendemo.sh && ./startjanssendemo.sh This will install Docker, Microk8s, Helm and Janssen with the default settings that can be found inside values.yaml . The installer will automatically add a record to your hosts record in the VM but if you want to access the endpoints outside the VM you must map the ip of the instance running Ubuntu to the FQDN you provided and then access the endpoints at your browser such in the example in the table below. Service Example endpoint Auth server https://FQDN/.well-known/openid-configuration fido2 https://FQDN/.well-known/fido2-configuration scim https://FQDN/.well-known/scim-configuration", "title": "Installation Steps"}, {"location": "janssen-server/install/helm-install/local/#configure-janssen", "text": "You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Configure Janssen"}, {"location": "janssen-server/install/helm-install/microsoft-azure/", "tags": ["administration", "installation", "helm", "AKS", "Microsoft", "Azure"], "text": "Install Janssen on AKS # System Requirements # The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0 Initial Setup # Install Azure CLI Create a Resource Group az group create --name janssen-resource-group --location eastus Create an AKS cluster such as the following example: az aks create -g janssen-resource-group -n janssen-cluster --enable-managed-identity --node-vm-size NODE_TYPE --node-count 2 --enable-addons monitoring --enable-msi-auth-for-monitoring --generate-ssh-keys You can adjust node-count and node-vm-size as per your desired cluster size Connect to the cluster az aks install-cli az aks get-credentials --resource-group janssen-resource-group --name janssen-cluster Install Helm3 Create jans namespace where our resources will reside kubectl create namespace jans Jans Installation using Helm # Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer IP: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].ip}' Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the Loadbalance IP from the previous command isFqdnRegistered : false FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the LoadBalancer IP from the previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Azure Database for PostgreSQL For testing purposes, you can deploy it on the AKS cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Azure Database for MySQL For testing purposes, you can deploy it on the AKS cluster using the following command: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql lbIp : \"\" #Add the LoadBalancer IP from previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml Configure Janssen # You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Microsoft Azure AKS"}, {"location": "janssen-server/install/helm-install/microsoft-azure/#install-janssen-on-aks", "text": "", "title": "Install Janssen on AKS"}, {"location": "janssen-server/install/helm-install/microsoft-azure/#system-requirements", "text": "The resources may be set minimally to the below: 8-12 GB RAM based on the services deployed 8-10 CPU cores based on the services deployed 50GB hard-disk Use the listing below for a detailed estimation of minimum required resources. The table contains the default resources recommendation per service. Depending on the use of each service the resources need may be increased or decreased. Service CPU Unit RAM Disk Space Processor Type Required Auth server 2.5 2.5GB N/A 64 Bit Yes fido2 0.5 0.5GB N/A 64 Bit No scim 1 1GB N/A 64 Bit No config - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs persistence - job 0.3 0.3GB N/A 64 Bit Yes on fresh installs nginx 1 1GB N/A 64 Bit Yes ALB/Istio not used auth-key-rotation 0.3 0.3GB N/A 64 Bit No [Strongly recommended] config-api 1 1GB N/A 64 Bit No casa 0.5 0.5GB N/A 64 Bit No link 0.5 1GB N/A 64 Bit No saml 0.5 1GB N/A 64 Bit No kc-scheduler - job 0.3 0.3GB N/A 64 Bit No Releases of images are in style 1.0.0-beta.0, 1.0.0-0", "title": "System Requirements"}, {"location": "janssen-server/install/helm-install/microsoft-azure/#initial-setup", "text": "Install Azure CLI Create a Resource Group az group create --name janssen-resource-group --location eastus Create an AKS cluster such as the following example: az aks create -g janssen-resource-group -n janssen-cluster --enable-managed-identity --node-vm-size NODE_TYPE --node-count 2 --enable-addons monitoring --enable-msi-auth-for-monitoring --generate-ssh-keys You can adjust node-count and node-vm-size as per your desired cluster size Connect to the cluster az aks install-cli az aks get-credentials --resource-group janssen-resource-group --name janssen-cluster Install Helm3 Create jans namespace where our resources will reside kubectl create namespace jans", "title": "Initial Setup"}, {"location": "janssen-server/install/helm-install/microsoft-azure/#jans-installation-using-helm", "text": "Install Nginx-Ingress , if you are not using Istio ingress helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo add stable https://charts.helm.sh/stable helm repo update helm install nginx ingress-nginx/ingress-nginx Create a file named override.yaml and add changes as per your desired configuration: FQDN/domain is not registered: Get the Loadbalancer IP: kubectl get svc nginx-ingress-nginx-controller --output jsonpath='{.status.loadBalancer.ingress[0].ip}' Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the Loadbalance IP from the previous command isFqdnRegistered : false FQDN/domain is registered: Add the following yaml snippet to your override.yaml file: global : lbIp : #Add the LoadBalancer IP from the previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans PostgreSQL for persistence storage In a production environment, a production grade PostgreSQL server should be used such as Azure Database for PostgreSQL For testing purposes, you can deploy it on the AKS cluster using the following command: helm install my-release --set auth.postgresPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/postgresql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 5432 cnSqlDbDialect : pgsql cnSqlDbHost : my-release-postgresql.jans.svc cnSqlDbUser : postgres cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# MySQL for persistence storage In a production environment, a production grade MySQL server should be used such as Azure Database for MySQL For testing purposes, you can deploy it on the AKS cluster using the following command: helm install my-release --set auth.rootPassword=Test1234#,auth.database=jans -n jans oci://registry-1.docker.io/bitnamicharts/mysql Add the following yaml snippet to your override.yaml file: global : cnPersistenceType : sql config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# So if your desired configuration has FQDN and MySQL, the final override.yaml file will look something like that: global : cnPersistenceType : sql lbIp : \"\" #Add the LoadBalancer IP from previous command isFqdnRegistered : true fqdn : demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans nginx-ingress : ingress : path : / hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans tls : - secretName : tls-certificate hosts : - demoexample.jans.io #CHANGE-THIS to the FQDN used for Jans config : configmap : cnSqlDbName : jans cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : my-release-mysql.jans.svc cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# Install Jans After finishing all the tweaks to the override.yaml file, we can use it to install jans. helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml", "title": "Jans Installation using Helm"}, {"location": "janssen-server/install/helm-install/microsoft-azure/#configure-janssen", "text": "You can use the TUI to configure Janssen components. The TUI calls the Config API to perform ad hoc configuration.", "title": "Configure Janssen"}, {"location": "janssen-server/install/helm-install/rancher/", "tags": ["administration", "installation", "helm", "rancher"], "text": "Install Janssen Server Using Rancher Marketplace # For this quick start we will use a single node Kubernetes install in docker with a self-signed certificate . Note For a more generic setup, use Rancher UI to deploy the setup. For more options please follow this link . Installation Steps # Note If you are deploying an Ingress controller on a single node deployment, in which Ingress utilizes ports 80 and 443, then you have to adjust the host ports mapped for the rancher/rancher container. Here's an example on how to do that. Provision a Linux 4 CPU, 16 GB RAM, and 50GB SSD VM with ports 443 and 80 open. Save the VM IP address. For development environments, the VM can be set up using VMWare Workstation Player or VirtualBox with an Ubuntu 20.04 operating system running on a VM. Install Docker . Execute docker run -d --restart = unless-stopped -p 80 :80 -p 443 :443 --privileged rancher/rancher:latest The final line of the returned text is the container-id , which you'll need for the next step. Execute the following command to get the bootstrap password for login. docker logs <container-id> 2 > & 1 | grep \"Bootstrap Password:\" Head to https://<VM-IP-ADDRESS-FROM-FIRST-STEP> and log in with the username admin and the password from the previous step. If you are logging into Rancher for the first time, you'll need to enter just the password, and on the next step, Rancher will ask you to reset your current password. Next, you'll see the Rancher home page with a list of existing clusters. By default, the name of the newly created cluster would be local . Click on the cluster name to go to the dashboard. Add Janssen repository: From the top-left menu expand Apps > Repositories > Create > Add a repo name and the Index URL https://docs.jans.io/charts > Create From the top-left menu expand Apps and click Charts . Search for Janssen and begin your installation. During Step 1 of installation, be sure to select the Customize Helm options before install option. In Step 2, customize the settings for the Janssen installation. In Step 3, unselect the Wait option and start the installation.", "title": "Using Rancher Marketplace"}, {"location": "janssen-server/install/helm-install/rancher/#install-janssen-server-using-rancher-marketplace", "text": "For this quick start we will use a single node Kubernetes install in docker with a self-signed certificate . Note For a more generic setup, use Rancher UI to deploy the setup. For more options please follow this link .", "title": "Install Janssen Server Using Rancher Marketplace"}, {"location": "janssen-server/install/helm-install/rancher/#installation-steps", "text": "Note If you are deploying an Ingress controller on a single node deployment, in which Ingress utilizes ports 80 and 443, then you have to adjust the host ports mapped for the rancher/rancher container. Here's an example on how to do that. Provision a Linux 4 CPU, 16 GB RAM, and 50GB SSD VM with ports 443 and 80 open. Save the VM IP address. For development environments, the VM can be set up using VMWare Workstation Player or VirtualBox with an Ubuntu 20.04 operating system running on a VM. Install Docker . Execute docker run -d --restart = unless-stopped -p 80 :80 -p 443 :443 --privileged rancher/rancher:latest The final line of the returned text is the container-id , which you'll need for the next step. Execute the following command to get the bootstrap password for login. docker logs <container-id> 2 > & 1 | grep \"Bootstrap Password:\" Head to https://<VM-IP-ADDRESS-FROM-FIRST-STEP> and log in with the username admin and the password from the previous step. If you are logging into Rancher for the first time, you'll need to enter just the password, and on the next step, Rancher will ask you to reset your current password. Next, you'll see the Rancher home page with a list of existing clusters. By default, the name of the newly created cluster would be local . Click on the cluster name to go to the dashboard. Add Janssen repository: From the top-left menu expand Apps > Repositories > Create > Add a repo name and the Index URL https://docs.jans.io/charts > Create From the top-left menu expand Apps and click Charts . Search for Janssen and begin your installation. During Step 1 of installation, be sure to select the Customize Helm options before install option. In Step 2, customize the settings for the Janssen installation. In Step 3, unselect the Wait option and start the installation.", "title": "Installation Steps"}, {"location": "janssen-server/install/vm-install/dynamic-download/", "tags": ["administration", "installation", "vm", "dynamic"], "text": "Install Janssen Server using Dynamic Download # The dynamic download installs the latest development version of the Janssen Server. Note This method of installation is suitable only for testing, development, or feature exploration purposes. Not for production deployments. System Requirements # System should meet minimum VM system requirements Prerequisites # curl should be installed Install # Download the installer curl https://raw.githubusercontent.com/JanssenProject/jans/vreplace-janssen-version/jans-linux-setup/jans_setup/install.py > install.py Execute Installer To execute installer, run the command below: python3 install.py The installer can be invoked using various options to tailor the installation process. Invoke the commands below to know about all the available options. python3 install.py --help One particularly useful option for development environments is the one below which installs the Janssen Server with test data loaded. python3 install.py --args=\"-t\" Installer can be run with all the arguments provided via command-line at the time of invocking the install script. This enables prompt-less installation. For example, see the command below: python3 install.py --args = \"-n -ip-address 10.229.38.28 -host-name jans-opensuse -city ah -state gj -country in -org-name gluu -email dhaval@gluu.org -jans-max-mem 26349 -admin-password admin --with-casa --install-jans-keycloak-link -t\" Uninstall # Use the command below to uninstall the Janssen Server Note For removal of the attached persistence store, please refer to this note . python3 install.py -uninstall", "title": "Dynamic Download"}, {"location": "janssen-server/install/vm-install/dynamic-download/#install-janssen-server-using-dynamic-download", "text": "The dynamic download installs the latest development version of the Janssen Server. Note This method of installation is suitable only for testing, development, or feature exploration purposes. Not for production deployments.", "title": "Install Janssen Server using Dynamic Download"}, {"location": "janssen-server/install/vm-install/dynamic-download/#system-requirements", "text": "System should meet minimum VM system requirements", "title": "System Requirements"}, {"location": "janssen-server/install/vm-install/dynamic-download/#prerequisites", "text": "curl should be installed", "title": "Prerequisites"}, {"location": "janssen-server/install/vm-install/dynamic-download/#install", "text": "Download the installer curl https://raw.githubusercontent.com/JanssenProject/jans/vreplace-janssen-version/jans-linux-setup/jans_setup/install.py > install.py Execute Installer To execute installer, run the command below: python3 install.py The installer can be invoked using various options to tailor the installation process. Invoke the commands below to know about all the available options. python3 install.py --help One particularly useful option for development environments is the one below which installs the Janssen Server with test data loaded. python3 install.py --args=\"-t\" Installer can be run with all the arguments provided via command-line at the time of invocking the install script. This enables prompt-less installation. For example, see the command below: python3 install.py --args = \"-n -ip-address 10.229.38.28 -host-name jans-opensuse -city ah -state gj -country in -org-name gluu -email dhaval@gluu.org -jans-max-mem 26349 -admin-password admin --with-casa --install-jans-keycloak-link -t\"", "title": "Install"}, {"location": "janssen-server/install/vm-install/dynamic-download/#uninstall", "text": "Use the command below to uninstall the Janssen Server Note For removal of the attached persistence store, please refer to this note . python3 install.py -uninstall", "title": "Uninstall"}, {"location": "janssen-server/install/vm-install/rhel/", "tags": ["administration", "installation", "vm", "RHEL"], "text": "Red Hat EL Janssen Installation # Before you install, check the VM system requirements . Supported versions # Red Hat Enterprise Linux 8 (RHEL 8) Install the Package # Install EPEL and mod-auth-openidc as dependencies sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm sudo yum -y module enable mod_auth_openidc Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo rpm -import automation-jans-public-gpg.asc Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.el8.x86_64.rpm -P ~/ Verify integrity of the downloaded package using published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.el8.x86_64.rpm.sha256sum -P ~/ Check the hash if it is matching. sha256sum -c jans-replace-janssen-version-el8.x86_64.rpm.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans-replace-janssen-version-el8.x86_64.rpm: OK Install the package sudo yum install ~/jans-replace-janssen-version-el8.x86_64.rpm Run the setup script # Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py The installer should confirm successful installation with a message similar to the one shown below: See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode. Verify the Installation # After the successful completion of setup process, verify the system health . Log in to Text User Interface (TUI) # Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa Enabling HTTPS # To enable communication with Janssen Server over TLS (https) in a production environment, Janssen Server needs details about CA certificate. Update the HTTPS cofiguration file https_jans.conf as shown below: Note Want to use Let's Encrypt to get a certificate? Follow this guide . Open https_jans.conf sudo vi /etc/httpd/conf.d/https_jans.conf Update SSLCertificateFile and SSLCertificateKeyFile parameters values SSLCertificateFile location_of_fullchain.pem SSLCertificateKeyFile location_of_privkey.pem Restart httpd service for changes to take effect sudo service httpd restart Uninstall # Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Delete files installed by Janssen Remove and purge the jans package Use the command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall Console output like below will confirm the successful uninstallation of the Janssen Server This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Stopping OpenDj Server Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/opendj Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf Remove the linux package Use the command below to remove and purge jans package yum remove jans.x86_64 Successful removal will remove the Janssen Server package along with the removal of all the unused dependencies.", "title": "RHEL"}, {"location": "janssen-server/install/vm-install/rhel/#red-hat-el-janssen-installation", "text": "Before you install, check the VM system requirements .", "title": "Red Hat EL Janssen Installation"}, {"location": "janssen-server/install/vm-install/rhel/#supported-versions", "text": "Red Hat Enterprise Linux 8 (RHEL 8)", "title": "Supported versions"}, {"location": "janssen-server/install/vm-install/rhel/#install-the-package", "text": "Install EPEL and mod-auth-openidc as dependencies sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm sudo yum -y module enable mod_auth_openidc Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo rpm -import automation-jans-public-gpg.asc Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.el8.x86_64.rpm -P ~/ Verify integrity of the downloaded package using published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.el8.x86_64.rpm.sha256sum -P ~/ Check the hash if it is matching. sha256sum -c jans-replace-janssen-version-el8.x86_64.rpm.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans-replace-janssen-version-el8.x86_64.rpm: OK Install the package sudo yum install ~/jans-replace-janssen-version-el8.x86_64.rpm", "title": "Install the Package"}, {"location": "janssen-server/install/vm-install/rhel/#run-the-setup-script", "text": "Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py The installer should confirm successful installation with a message similar to the one shown below: See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode.", "title": "Run the setup script"}, {"location": "janssen-server/install/vm-install/rhel/#verify-the-installation", "text": "After the successful completion of setup process, verify the system health .", "title": "Verify the Installation"}, {"location": "janssen-server/install/vm-install/rhel/#log-in-to-text-user-interface-tui", "text": "Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa", "title": "Log in to Text User Interface (TUI)"}, {"location": "janssen-server/install/vm-install/rhel/#enabling-https", "text": "To enable communication with Janssen Server over TLS (https) in a production environment, Janssen Server needs details about CA certificate. Update the HTTPS cofiguration file https_jans.conf as shown below: Note Want to use Let's Encrypt to get a certificate? Follow this guide . Open https_jans.conf sudo vi /etc/httpd/conf.d/https_jans.conf Update SSLCertificateFile and SSLCertificateKeyFile parameters values SSLCertificateFile location_of_fullchain.pem SSLCertificateKeyFile location_of_privkey.pem Restart httpd service for changes to take effect sudo service httpd restart", "title": "Enabling HTTPS"}, {"location": "janssen-server/install/vm-install/rhel/#uninstall", "text": "Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Delete files installed by Janssen Remove and purge the jans package Use the command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall Console output like below will confirm the successful uninstallation of the Janssen Server This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Stopping OpenDj Server Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/opendj Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf Remove the linux package Use the command below to remove and purge jans package yum remove jans.x86_64 Successful removal will remove the Janssen Server package along with the removal of all the unused dependencies.", "title": "Uninstall"}, {"location": "janssen-server/install/vm-install/suse/", "tags": ["administration", "installation", "vm", "SUSE", "SLES", "Leap"], "text": "SUSE Janssen Installation # Before you install, check the VM system requirements . Supported versions # SUSE Linux Enterprise Server (SLES) 15 openSUSE Leap 15.5 Install the Package # If the server firewall is running, make sure you allow https , which is needed for OpenID and FIDO. sudo firewall-cmd --permanent --zone = public --add-service = https sudo firewall-cmd --reload for SLES, we need to enable PackageHub as per OSversion and architecture sudo SUSEConnect -p PackageHub/15.5/x86_64 Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo rpm -import automation-jans-public-gpg.asc Download the release package from the GitHub Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.suse15.x86_64.rpm Verify integrity of the downloaded package using published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.suse15.x86_64.rpm.sha256sum Check the hash if it is matching. You may need to change your working directory to where both the rpm and sha256sum file are located. sha256sum -c jans-replace-janssen-version.suse15.x86_64.rpm.sha256sum Output similar to below should confirm the integrity of the downloaded package. <package-name>: OK Install the package sudo zypper install ~/jans-replace-janssen-version.suse15.x86_64.rpm Run the setup script # Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode. Verify the Installation # After the successful completion of setup process, verify the system health . Log in to Text User Interface (TUI) # Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa Enabling HTTPS # To enable communication with Janssen Server over TLS (https) in a production environment, Janssen Server needs details about CA certificate. Update the HTTPS cofiguration file https_jans.conf as shown below: Note Want to use Let's Encrypt to get a certificate? Follow this guide . Open https_jans.conf sudo vi /etc/apache2/vhosts.d/_https_jans.conf Update SSLCertificateFile and SSLCertificateKeyFile parameters values SSLCertificateFile location_of_fullchain.pem SSLCertificateKeyFile location_of_privkey.pem Restart httpd service for changes to take effect sudo /usr/sbin/rcapache2 restart Uninstall # Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Uninstall Janssen Server Remove and purge the jans package If you have not run the Jans setup script, you can skip step 1 and just remove the package. First, run command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall You'll see the following confirmation: This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Stopping OpenDj Server Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/opendj Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf Second uninstall the package: rpm -qa | grep jans And then use zypper remove <package>", "title": "Suse"}, {"location": "janssen-server/install/vm-install/suse/#suse-janssen-installation", "text": "Before you install, check the VM system requirements .", "title": "SUSE Janssen Installation"}, {"location": "janssen-server/install/vm-install/suse/#supported-versions", "text": "SUSE Linux Enterprise Server (SLES) 15 openSUSE Leap 15.5", "title": "Supported versions"}, {"location": "janssen-server/install/vm-install/suse/#install-the-package", "text": "If the server firewall is running, make sure you allow https , which is needed for OpenID and FIDO. sudo firewall-cmd --permanent --zone = public --add-service = https sudo firewall-cmd --reload for SLES, we need to enable PackageHub as per OSversion and architecture sudo SUSEConnect -p PackageHub/15.5/x86_64 Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo rpm -import automation-jans-public-gpg.asc Download the release package from the GitHub Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.suse15.x86_64.rpm Verify integrity of the downloaded package using published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-replace-janssen-version-stable.suse15.x86_64.rpm.sha256sum Check the hash if it is matching. You may need to change your working directory to where both the rpm and sha256sum file are located. sha256sum -c jans-replace-janssen-version.suse15.x86_64.rpm.sha256sum Output similar to below should confirm the integrity of the downloaded package. <package-name>: OK Install the package sudo zypper install ~/jans-replace-janssen-version.suse15.x86_64.rpm", "title": "Install the Package"}, {"location": "janssen-server/install/vm-install/suse/#run-the-setup-script", "text": "Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode.", "title": "Run the setup script"}, {"location": "janssen-server/install/vm-install/suse/#verify-the-installation", "text": "After the successful completion of setup process, verify the system health .", "title": "Verify the Installation"}, {"location": "janssen-server/install/vm-install/suse/#log-in-to-text-user-interface-tui", "text": "Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa", "title": "Log in to Text User Interface (TUI)"}, {"location": "janssen-server/install/vm-install/suse/#enabling-https", "text": "To enable communication with Janssen Server over TLS (https) in a production environment, Janssen Server needs details about CA certificate. Update the HTTPS cofiguration file https_jans.conf as shown below: Note Want to use Let's Encrypt to get a certificate? Follow this guide . Open https_jans.conf sudo vi /etc/apache2/vhosts.d/_https_jans.conf Update SSLCertificateFile and SSLCertificateKeyFile parameters values SSLCertificateFile location_of_fullchain.pem SSLCertificateKeyFile location_of_privkey.pem Restart httpd service for changes to take effect sudo /usr/sbin/rcapache2 restart", "title": "Enabling HTTPS"}, {"location": "janssen-server/install/vm-install/suse/#uninstall", "text": "Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Uninstall Janssen Server Remove and purge the jans package If you have not run the Jans setup script, you can skip step 1 and just remove the package. First, run command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall You'll see the following confirmation: This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Stopping OpenDj Server Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/opendj Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf Second uninstall the package: rpm -qa | grep jans And then use zypper remove <package>", "title": "Uninstall"}, {"location": "janssen-server/install/vm-install/ubuntu/", "tags": ["administration", "installation", "vm", "ubuntu"], "text": "Ubuntu Janssen Installation # Supported Versions # Ubuntu 22.04 Ubuntu 20.04 Before you install, check the VM system requirements . Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo gpg --import automation-jans-public-gpg.asc ; Install the Package # Ubuntu 22.04 # Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu22.04_amd64.deb -P /tmp Verify integrity of the downloaded package by verifying published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu22.04_amd64.deb.sha256sum -P /tmp Check the hash if it is matching. cd /tmp sha256sum -c jans_replace-janssen-version.ubuntu22.04_amd64.deb.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans_replace-janssen-version.ubuntu22.04_amd64.deb.sha256sum: OK Install the package sudo apt install ./jans_replace-janssen-version.ubuntu22.04_amd64.deb Ubuntu 20.04 # Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu20.04_amd64.deb -P /tmp Verify integrity of the downloaded package by verifying published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu20.04_amd64.deb.sha256sum -P /tmp Check the hash if it is matching. cd /tmp sha256sum -c jans_replace-janssen-version.ubuntu20.04_amd64.deb.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans_replace-janssen-version.ubuntu20.04_amd64.deb.sha256sum: OK Install the package sudo apt install ./jans_replace-janssen-version.ubuntu20.04_amd64.deb Run the setup script # Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode. Verify the Installation # After the successful completion of setup process, verify the system health . Log in to Text User Interface (TUI) # Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa Let's Encrypt # To enable communication with Janssen Server over tls (https) in production environment, Janssen Server needs details about CA certificate. To generate Let\u2019s Encrypt CA certificate follow this let's encrypt . Uninstall # Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Delete files installed by Janssen Remove and purge the jans package Use the command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall You'll see the following confirmation: This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf The command below removes and purges the jans package apt-get --purge remove jans Which should result in the following: Reading package lists... Done Building dependency tree... Done Reading state information... Done The following packages were automatically installed and are no longer required: apache2 apache2-bin apache2-data apache2-utils libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.3-0 postgresql postgresql-contrib python3-pymysql python3-ruamel.yaml python3-ruamel.yaml.clib Use 'apt autoremove' to remove them. The following packages will be REMOVED: jans* 0 upgraded, 0 newly installed, 1 to remove and 2 not upgraded. After this operation, 1631 MB disk space will be freed. Do you want to continue? [Y/n] y (Reading database ... 166839 files and directories currently installed.) Removing jans (replace-janssen-version~ubuntu20.04) ... Checking to make sure service is down...", "title": "Ubuntu"}, {"location": "janssen-server/install/vm-install/ubuntu/#ubuntu-janssen-installation", "text": "", "title": "Ubuntu Janssen Installation"}, {"location": "janssen-server/install/vm-install/ubuntu/#supported-versions", "text": "Ubuntu 22.04 Ubuntu 20.04 Before you install, check the VM system requirements . Download the GPG key zip file , unzip and import GPG key wget https://github.com/JanssenProject/jans/files/11814522/automation-jans-public-gpg.zip unzip automation-jans-public-gpg.zip sudo gpg --import automation-jans-public-gpg.asc ;", "title": "Supported Versions"}, {"location": "janssen-server/install/vm-install/ubuntu/#install-the-package", "text": "", "title": "Install the Package"}, {"location": "janssen-server/install/vm-install/ubuntu/#ubuntu-2204", "text": "Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu22.04_amd64.deb -P /tmp Verify integrity of the downloaded package by verifying published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu22.04_amd64.deb.sha256sum -P /tmp Check the hash if it is matching. cd /tmp sha256sum -c jans_replace-janssen-version.ubuntu22.04_amd64.deb.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans_replace-janssen-version.ubuntu22.04_amd64.deb.sha256sum: OK Install the package sudo apt install ./jans_replace-janssen-version.ubuntu22.04_amd64.deb", "title": "Ubuntu 22.04"}, {"location": "janssen-server/install/vm-install/ubuntu/#ubuntu-2004", "text": "Download the release package from the Github Janssen Project Releases wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu20.04_amd64.deb -P /tmp Verify integrity of the downloaded package by verifying published sha256sum . Download sha256sum file for the package wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans_replace-janssen-version-stable.ubuntu20.04_amd64.deb.sha256sum -P /tmp Check the hash if it is matching. cd /tmp sha256sum -c jans_replace-janssen-version.ubuntu20.04_amd64.deb.sha256sum Output similar to below should confirm the integrity of the downloaded package. jans_replace-janssen-version.ubuntu20.04_amd64.deb.sha256sum: OK Install the package sudo apt install ./jans_replace-janssen-version.ubuntu20.04_amd64.deb", "title": "Ubuntu 20.04"}, {"location": "janssen-server/install/vm-install/ubuntu/#run-the-setup-script", "text": "Run the setup script in interactive mode: sudo python3 /opt/jans/jans-setup/setup.py See more detailed instructions on the setup script if you're confused how to answer any of the questions, for details about command line arguments, or you would prefer to use a properties file instead of interactive mode.", "title": "Run the setup script"}, {"location": "janssen-server/install/vm-install/ubuntu/#verify-the-installation", "text": "After the successful completion of setup process, verify the system health .", "title": "Verify the Installation"}, {"location": "janssen-server/install/vm-install/ubuntu/#log-in-to-text-user-interface-tui", "text": "Begin configuration by accessing the TUI with the following command: jans tui Full TUI documentation can be found here If you have selected casa during installation you can access casa using url https://<host>/jans-casa", "title": "Log in to Text User Interface (TUI)"}, {"location": "janssen-server/install/vm-install/ubuntu/#lets-encrypt", "text": "To enable communication with Janssen Server over tls (https) in production environment, Janssen Server needs details about CA certificate. To generate Let\u2019s Encrypt CA certificate follow this let's encrypt .", "title": "Let's Encrypt"}, {"location": "janssen-server/install/vm-install/ubuntu/#uninstall", "text": "Uninstall process involves two steps and removes all the Janssen Server components. Note For removal of the attached persistence store, please refer to this note . Delete files installed by Janssen Remove and purge the jans package Use the command below to uninstall the Janssen server sudo python3 /opt/jans/jans-setup/install.py -uninstall You'll see the following confirmation: This process is irreversible. You will lose all data related to Janssen Server. Are you sure to uninstall Janssen Server? [yes/N] yes Uninstalling Jannsen Server... Removing /etc/default/jans-config-api Stopping jans-config-api Removing /etc/default/jans-scim Stopping jans-scim Removing /etc/default/jans-fido2 Stopping jans-fido2 Removing /etc/default/jans-auth Stopping jans-auth Removing /etc/default/jans-client-api Stopping jans-client-api Executing rm -r -f /etc/certs Executing rm -r -f /etc/jans Executing rm -r -f /opt/jans Executing rm -r -f /opt/amazon-corretto* Executing rm -r -f /opt/jre Executing rm -r -f /opt/node* Executing rm -r -f /opt/jetty* Executing rm -r -f /opt/jython* Executing rm -r -f /opt/dist Removing /etc/apache2/sites-enabled/https_jans.conf Removing /etc/apache2/sites-available/https_jans.conf The command below removes and purges the jans package apt-get --purge remove jans Which should result in the following: Reading package lists... Done Building dependency tree... Done Reading state information... Done The following packages were automatically installed and are no longer required: apache2 apache2-bin apache2-data apache2-utils libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.3-0 postgresql postgresql-contrib python3-pymysql python3-ruamel.yaml python3-ruamel.yaml.clib Use 'apt autoremove' to remove them. The following packages will be REMOVED: jans* 0 upgraded, 0 newly installed, 1 to remove and 2 not upgraded. After this operation, 1631 MB disk space will be freed. Do you want to continue? [Y/n] y (Reading database ... 166839 files and directories currently installed.) Removing jans (replace-janssen-version~ubuntu20.04) ... Checking to make sure service is down...", "title": "Uninstall"}, {"location": "janssen-server/install/vm-install/vm-requirements/", "tags": ["requirements", "installation", "vm", "hardware"], "text": "VM System Requirements # The Janssen Project currently provides packages for these Linux distros: Ubuntu (versions: 20.04) SUSE (SLES or LEAP) (version: 15) RedHat Enterprise Linux (version: 8) Hardware Requirements # A single-VM deployment is where all services are running on one server. Although, the requirements can vary based on the size of the data and the required concurrency, the following guidelines can help you plan: Development and Test Environments # 8 GB RAM 4 CPU 20 GB Disk Production Environment Recommendation: # 8 GB RAM 4 CPU 4 GB swap space 50 GB Disk Port Configuration # Janssen Server requires the following ports to be open for incoming connections. Port Protocol Notes 443 TCP TLS/HTTP You may want to use a redirect on port 80 to 443, although it is not required. Of course you will also need some way to login to your server, but that is out of scope of these docs. Check your server firewall documentation to configure your firewall to allow https . Hostname / IP Address Configuration # It is recommended that you use a static ip address for your Janssen Server. Your server should also return the hostname for the hostname command, it's recommended that you add the hostname to the /etc/hosts file. File Descriptor Configuration (FD) # Like most database and Internet servers, you must have at least 65k file descriptors. If you don't, your server will hang. First, check the current file descriptor limit using command below. If the existing FD limit exceeds 65535, then you're good. # cat /proc/sys/fs/file-max If FD limit is less than 65535 (e.g. 1024), then follow the steps below to increase the value. 1) Set soft and hard limits by adding the following lines in the /etc/security/limits.conf file * soft nofile 65535 * hard nofile 262144 2) Add the following lines to /etc/pam.d/login if not already present session required pam_limits.so 3) Increase the FD limit in /proc/sys/fs/file-max echo 65535 > /proc/sys/fs/file-max** 4) Use the ulimit command to set the FD limit to the hard limit specified in /etc/security/limits.conf . If setting to hard limit doesn't work, then try to set it to the soft limit. ulimit -n 262144 5) Restart the system", "title": "VM Requirements"}, {"location": "janssen-server/install/vm-install/vm-requirements/#vm-system-requirements", "text": "The Janssen Project currently provides packages for these Linux distros: Ubuntu (versions: 20.04) SUSE (SLES or LEAP) (version: 15) RedHat Enterprise Linux (version: 8)", "title": "VM System Requirements"}, {"location": "janssen-server/install/vm-install/vm-requirements/#hardware-requirements", "text": "A single-VM deployment is where all services are running on one server. Although, the requirements can vary based on the size of the data and the required concurrency, the following guidelines can help you plan:", "title": "Hardware Requirements"}, {"location": "janssen-server/install/vm-install/vm-requirements/#development-and-test-environments", "text": "8 GB RAM 4 CPU 20 GB Disk", "title": "Development and Test Environments"}, {"location": "janssen-server/install/vm-install/vm-requirements/#production-environment-recommendation", "text": "8 GB RAM 4 CPU 4 GB swap space 50 GB Disk", "title": "Production Environment Recommendation:"}, {"location": "janssen-server/install/vm-install/vm-requirements/#port-configuration", "text": "Janssen Server requires the following ports to be open for incoming connections. Port Protocol Notes 443 TCP TLS/HTTP You may want to use a redirect on port 80 to 443, although it is not required. Of course you will also need some way to login to your server, but that is out of scope of these docs. Check your server firewall documentation to configure your firewall to allow https .", "title": "Port Configuration"}, {"location": "janssen-server/install/vm-install/vm-requirements/#hostname-ip-address-configuration", "text": "It is recommended that you use a static ip address for your Janssen Server. Your server should also return the hostname for the hostname command, it's recommended that you add the hostname to the /etc/hosts file.", "title": "Hostname / IP Address Configuration"}, {"location": "janssen-server/install/vm-install/vm-requirements/#file-descriptor-configuration-fd", "text": "Like most database and Internet servers, you must have at least 65k file descriptors. If you don't, your server will hang. First, check the current file descriptor limit using command below. If the existing FD limit exceeds 65535, then you're good. # cat /proc/sys/fs/file-max If FD limit is less than 65535 (e.g. 1024), then follow the steps below to increase the value. 1) Set soft and hard limits by adding the following lines in the /etc/security/limits.conf file * soft nofile 65535 * hard nofile 262144 2) Add the following lines to /etc/pam.d/login if not already present session required pam_limits.so 3) Increase the FD limit in /proc/sys/fs/file-max echo 65535 > /proc/sys/fs/file-max** 4) Use the ulimit command to set the FD limit to the hard limit specified in /etc/security/limits.conf . If setting to hard limit doesn't work, then try to set it to the soft limit. ulimit -n 262144 5) Restart the system", "title": "File Descriptor Configuration (FD)"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/", "tags": ["administration", "keycloak", "SAML", "inbound"], "text": "Overview # Janssen supports authentication against external SAML identity provider (IDP) namely inbound SAML/inbound identity. This document provides instructions for configuring Janssen server Enable inbound SAML # Make sure you have Janssen server with SAML plugin installed and enabled. SAML plugin can be enabled using TUI (Jans Saml -> Contribution) Inbound SAML Authentication Flow # The following is a high-level diagram depicting a typical inbound identity user authentication and provisioning workflow. Configure SAML IDP # Use Janssen Text-based UI(TUI) or Janssen command-line interface to create new IDP Keycloak Server. 1. Navigate to Jans SAML > Identity Providers Go to Add Identity Provider and press Enter Enter a name (unique identifier) for this provider (letters, digits, and underscore characters allowed). Enter a display name for the Add Identity Provider Upload IDP Metadata by selecting file for Metadata Source Type and press Enter after you navigated on Browse of Metadata File Or you can, optionally provide individual metadata elements by selecting manual for Metadata Source Type . See adding a sample idp in the following figure Save details SAML IDP is created in Keycloak server under realm jans . IDP details are also persisted in Jans DB. To edit IDP details later, you can navigate to the idp in the list and press Enter , you will get a popup screen as shown in the figure below: Configure IDP for inbound SAML # SAML IDP should have been configured as stated in above Use Agama Lab is an online visual editor to build authentication flows. Learn more about Agama Lab Fork existing agama-inbound-saml project from Agama Lab Projects In Agama orchestrator create a new flow by adding a RFAC (Redirect and fetch a callback) node for SAML IDP. Deploying .gama package on Janssen Server Testing the authentication flow using Jans Tarp. Install Tarp, check details here . Open Tarp extension. Enter URL of Keycloak OpenID configuration. Example http:///realms/keycloak-external-broker/.well-known/openid-configuration. Click Register. Registered Client details are displayed, enter Additional Params to hint Keycloak about IDP to be trigger. Example {\"kc_idp_hint\":\"gluu-saml-idp-1\"} Click \"Trigger Auth Code Flow. This should redirect to IDP login page. Enter user details and login.", "title": "Inbound SAML"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/#overview", "text": "Janssen supports authentication against external SAML identity provider (IDP) namely inbound SAML/inbound identity. This document provides instructions for configuring Janssen server", "title": "Overview"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/#enable-inbound-saml", "text": "Make sure you have Janssen server with SAML plugin installed and enabled. SAML plugin can be enabled using TUI (Jans Saml -> Contribution)", "title": "Enable inbound SAML"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/#inbound-saml-authentication-flow", "text": "The following is a high-level diagram depicting a typical inbound identity user authentication and provisioning workflow.", "title": "Inbound SAML Authentication Flow"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/#configure-saml-idp", "text": "Use Janssen Text-based UI(TUI) or Janssen command-line interface to create new IDP Keycloak Server. 1. Navigate to Jans SAML > Identity Providers Go to Add Identity Provider and press Enter Enter a name (unique identifier) for this provider (letters, digits, and underscore characters allowed). Enter a display name for the Add Identity Provider Upload IDP Metadata by selecting file for Metadata Source Type and press Enter after you navigated on Browse of Metadata File Or you can, optionally provide individual metadata elements by selecting manual for Metadata Source Type . See adding a sample idp in the following figure Save details SAML IDP is created in Keycloak server under realm jans . IDP details are also persisted in Jans DB. To edit IDP details later, you can navigate to the idp in the list and press Enter , you will get a popup screen as shown in the figure below:", "title": "Configure SAML IDP"}, {"location": "janssen-server/keycloak/keycloak-saml-inbound/#configure-idp-for-inbound-saml", "text": "SAML IDP should have been configured as stated in above Use Agama Lab is an online visual editor to build authentication flows. Learn more about Agama Lab Fork existing agama-inbound-saml project from Agama Lab Projects In Agama orchestrator create a new flow by adding a RFAC (Redirect and fetch a callback) node for SAML IDP. Deploying .gama package on Janssen Server Testing the authentication flow using Jans Tarp. Install Tarp, check details here . Open Tarp extension. Enter URL of Keycloak OpenID configuration. Example http:///realms/keycloak-external-broker/.well-known/openid-configuration. Click Register. Registered Client details are displayed, enter Additional Params to hint Keycloak about IDP to be trigger. Example {\"kc_idp_hint\":\"gluu-saml-idp-1\"} Click \"Trigger Auth Code Flow. This should redirect to IDP login page. Enter user details and login.", "title": "Configure IDP for inbound SAML"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/", "tags": ["administration", "keycloak", "SAML", "SSO"], "text": "Overview # The Janssen Server acts as a SAML Identity Provider to support outbound SAML single sign-on (SSO). It does this by leveraging the SAML features available in Keycloak , while leveraging the Janssen Server's authentication module to handle the user authentication part of SSO. Once authentication is successful, the user is redirected to the SP with personal attributes and an active SSO session. Installation # During installation of the Janssen Server, simply select the option Install Jans KC to install and setup SAML SSO for Keycloak. Instructions on how to setup SAML SSO with Keycloak post-install will eventually be provided. Managing SAML Service Providers Through the Jans-Cli # To act as an IDP to various SAML SPs (Service Providers), the latter need to be added to the Janssen Server. This can be done via the Jans TUI which is what we will cover in this section. Adding a SAML SP # Open Jans-TUI Select the menu item Jans SAML > Service Providers Then navigate and select <Add Service Provider> Input the following: Display Name : An identifiable name for the Service Provider Enable TR : Whether or not the Service Provider should be enabled Metadata Location : The location of the metadata. The supported options so far are file and manual . Released Attributes : The user attributes to be released via the SAML response if authentication is successful The configurable options are kept to the bare functional minimum but will be expanded gradually. The manual metadata option for Metadata Location , allows the possibility to specify SP metadata information manually. IDP Metadata Location # For SAML authentication to work, there is a need for the SPs to trust the IDP, which usually is done by using an IDP metadata file that will be used on the SP side. The metadata can be found at https://<server-hostname>/kc/realms/jans/protocol/saml/descriptor where <server-hostname> is the hostname of the Janssen server specified during installation. IDP Initiated Flows # This content is a work in progress IDP Key Management # This content is a work in progress Have questions in the meantime? # You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "SAML SSO"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#overview", "text": "The Janssen Server acts as a SAML Identity Provider to support outbound SAML single sign-on (SSO). It does this by leveraging the SAML features available in Keycloak , while leveraging the Janssen Server's authentication module to handle the user authentication part of SSO. Once authentication is successful, the user is redirected to the SP with personal attributes and an active SSO session.", "title": "Overview"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#installation", "text": "During installation of the Janssen Server, simply select the option Install Jans KC to install and setup SAML SSO for Keycloak. Instructions on how to setup SAML SSO with Keycloak post-install will eventually be provided.", "title": "Installation"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#managing-saml-service-providers-through-the-jans-cli", "text": "To act as an IDP to various SAML SPs (Service Providers), the latter need to be added to the Janssen Server. This can be done via the Jans TUI which is what we will cover in this section.", "title": "Managing SAML Service Providers Through the Jans-Cli"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#adding-a-saml-sp", "text": "Open Jans-TUI Select the menu item Jans SAML > Service Providers Then navigate and select <Add Service Provider> Input the following: Display Name : An identifiable name for the Service Provider Enable TR : Whether or not the Service Provider should be enabled Metadata Location : The location of the metadata. The supported options so far are file and manual . Released Attributes : The user attributes to be released via the SAML response if authentication is successful The configurable options are kept to the bare functional minimum but will be expanded gradually. The manual metadata option for Metadata Location , allows the possibility to specify SP metadata information manually.", "title": "Adding a SAML SP"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#idp-metadata-location", "text": "For SAML authentication to work, there is a need for the SPs to trust the IDP, which usually is done by using an IDP metadata file that will be used on the SP side. The metadata can be found at https://<server-hostname>/kc/realms/jans/protocol/saml/descriptor where <server-hostname> is the hostname of the Janssen server specified during installation.", "title": "IDP Metadata Location"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#idp-initiated-flows", "text": "This content is a work in progress", "title": "IDP Initiated Flows"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#idp-key-management", "text": "This content is a work in progress", "title": "IDP Key Management"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#have-questions-in-the-meantime", "text": "You can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/keycloak/keycloak-saml-sso/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/kubernetes-ops/backup-restore/", "tags": ["administration", "kubernetes", "operations", "backup", "restore"], "text": "The Jans Server should be backed up frequently, we recommend once daily . There are multiple methods for backing up jans server. One way is manually using imperative commands. The other is automatically using open source tools. Manual Backup and Restore # Manual Backup # Configmap backup: kubectl get configmap cn -n <namespace> -o yaml > configmap-backup.yaml Secret backup: kubectl get secret cn -n <namespace> -o yaml > secret-backup.yaml Get the user supplied values: Save the values.yaml that was used in the initial jans installation using helm. In the event that the user supplied or override values yaml was lost, you can obtain it by executing the following command: helm get values <release name> -n <namespace> Keep note of installed chart version: helm list -n <namespace> Keep note of the chart version. For example: replace-janssen-version Manual Restore # Create namespace kubectl create namespace <namespace> Configmap restore: kubectl create -f configmap-backup.yaml Secret restore: kubectl create -f secret-backup.yaml Insall jans using the override or user supplied values with the same chart version: helm install <release-name> janssen/janssen -f values.yaml --version = <replace-janssen-version> -n <namespace> Automatic Backup and Restore # There are several tools that helps in automatic backups and restore, like Kasten K10 . You can follow online guides to deploy it and use it to configure automatic backups.", "title": "Backup and Restore"}, {"location": "janssen-server/kubernetes-ops/backup-restore/#manual-backup-and-restore", "text": "", "title": "Manual Backup and Restore"}, {"location": "janssen-server/kubernetes-ops/backup-restore/#manual-backup", "text": "Configmap backup: kubectl get configmap cn -n <namespace> -o yaml > configmap-backup.yaml Secret backup: kubectl get secret cn -n <namespace> -o yaml > secret-backup.yaml Get the user supplied values: Save the values.yaml that was used in the initial jans installation using helm. In the event that the user supplied or override values yaml was lost, you can obtain it by executing the following command: helm get values <release name> -n <namespace> Keep note of installed chart version: helm list -n <namespace> Keep note of the chart version. For example: replace-janssen-version", "title": "Manual Backup"}, {"location": "janssen-server/kubernetes-ops/backup-restore/#manual-restore", "text": "Create namespace kubectl create namespace <namespace> Configmap restore: kubectl create -f configmap-backup.yaml Secret restore: kubectl create -f secret-backup.yaml Insall jans using the override or user supplied values with the same chart version: helm install <release-name> janssen/janssen -f values.yaml --version = <replace-janssen-version> -n <namespace>", "title": "Manual Restore"}, {"location": "janssen-server/kubernetes-ops/backup-restore/#automatic-backup-and-restore", "text": "There are several tools that helps in automatic backups and restore, like Kasten K10 . You can follow online guides to deploy it and use it to configure automatic backups.", "title": "Automatic Backup and Restore"}, {"location": "janssen-server/kubernetes-ops/cert-management/", "tags": ["administration", "kubernetes", "operations", "certificate management", "certification and key rotation"], "text": "Overview # Rotating Certificates and Keys in Kubernetes setup Note janssen-config-cm in all examples refer to jans installation configuration parameters where janssen is the helm-release-name . Web (Ingress) # Associated certificates and keys /etc/certs/web_https.crt /etc/certs/web_https.key Note During fresh installation, the config-job checks if SSL certificates and keys are mounted as files. If no mounted files are found, it attempts to download SSL certificates from the FQDN supplied. If the download is successful, an empty key file is generated. If no mounted or downloaded files are found, it generates self-signed SSL certificates, CA certificates, and keys. Rotate # Create a file named web-key-rotation.yaml with the following contents : apiVersion : batch/v1 kind : Job metadata : name : web-key-rotation spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : restartPolicy : Never containers : - name : web-key-rotation image : ghcr.io/janssenproject/jans/certmanager:replace-janssen-version-1 envFrom : - configMapRef : name : janssen-config-cm # This may be differnet in Helm args : [ \"patch\" , \"web\" , \"--opts\" , \"valid-to:365\" ] Apply job kubectl apply -f web-key-rotation.yaml -n <jans-namespace> Load from existing source # Note This will load web_https.crt and web_https.key from /etc/certs . Create a secret with web_https.crt and web_https.key . Note that this may already exist in your deployment. kubectl create secret generic web-cert-key --from-file = web_https.crt --from-file = web_https.key -n <jans-namespace> ` Create a file named load-web-key-rotation.yaml with the following contents : apiVersion : batch/v1 kind : Job metadata : name : load-web-key-rotation spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : restartPolicy : Never volumes : - name : web-cert secret : secretName : web-cert-key items : - key : web_https.crt path : web_https.crt - name : web-key secret : secretName : web-cert-key items : - key : web_https.key path : web_https.key containers : - name : load-web-key-rotation image : ghcr.io/janssenproject/jans/certmanager:replace-janssen-version-1 envFrom : - configMapRef : name : janssen-config-cm #This may be differnet in Helm volumeMounts : - name : web-cert mountPath : /etc/certs/web_https.crt subPath : web_https.crt - name : web-key mountPath : /etc/certs/web_https.key subPath : web_https.key args : [ \"patch\" , \"web\" , \"--opts\" , \"source:from-files\" ] Apply job kubectl apply -f load-web-key-rotation.yaml -n <jans-namespace> Auth-server # Warning key rotation CronJob is usually installed with jans. Please make sure before deploying using kubectl get cronjobs -n <jans-namespace> Associated certificates and keys /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Create a file named auth-key-rotation.yaml with the following contents : kind : CronJob apiVersion : batch/v1 metadata : name : auth-key-rotation spec : # runs the job every 48 hours schedule : \"@every 48h\" concurrencyPolicy : Forbid jobTemplate : spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : containers : - name : auth-key-rotation image : ghcr.io/janssenproject/jans/certmanager:replace-janssen-version-1 resources : requests : memory : \"300Mi\" cpu : \"300m\" limits : memory : \"300Mi\" cpu : \"300m\" envFrom : - configMapRef : name : janssen-config-cm args : [ \"patch\" , \"auth\" , \"--opts\" , \"interval:48\" , \"--opts\" , \"key-strategy:OLDER\" , \"--opts\" , \"privkey-push-delay:300\" , \"--opts\" , \"privkey-push-strategy:NEWER\" ] restartPolicy : Never Apply cron job kubectl apply -f auth-key-rotation.yaml -n <jans-namespace>", "title": "Certificate Management"}, {"location": "janssen-server/kubernetes-ops/cert-management/#overview", "text": "Rotating Certificates and Keys in Kubernetes setup Note janssen-config-cm in all examples refer to jans installation configuration parameters where janssen is the helm-release-name .", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/cert-management/#web-ingress", "text": "Associated certificates and keys /etc/certs/web_https.crt /etc/certs/web_https.key Note During fresh installation, the config-job checks if SSL certificates and keys are mounted as files. If no mounted files are found, it attempts to download SSL certificates from the FQDN supplied. If the download is successful, an empty key file is generated. If no mounted or downloaded files are found, it generates self-signed SSL certificates, CA certificates, and keys.", "title": "Web (Ingress)"}, {"location": "janssen-server/kubernetes-ops/cert-management/#rotate", "text": "Create a file named web-key-rotation.yaml with the following contents : apiVersion : batch/v1 kind : Job metadata : name : web-key-rotation spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : restartPolicy : Never containers : - name : web-key-rotation image : ghcr.io/janssenproject/jans/certmanager:replace-janssen-version-1 envFrom : - configMapRef : name : janssen-config-cm # This may be differnet in Helm args : [ \"patch\" , \"web\" , \"--opts\" , \"valid-to:365\" ] Apply job kubectl apply -f web-key-rotation.yaml -n <jans-namespace>", "title": "Rotate"}, {"location": "janssen-server/kubernetes-ops/cert-management/#load-from-existing-source", "text": "Note This will load web_https.crt and web_https.key from /etc/certs . Create a secret with web_https.crt and web_https.key . Note that this may already exist in your deployment. kubectl create secret generic web-cert-key --from-file = web_https.crt --from-file = web_https.key -n <jans-namespace> ` Create a file named load-web-key-rotation.yaml with the following contents : apiVersion : batch/v1 kind : Job metadata : name : load-web-key-rotation spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : restartPolicy : Never volumes : - name : web-cert secret : secretName : web-cert-key items : - key : web_https.crt path : web_https.crt - name : web-key secret : secretName : web-cert-key items : - key : web_https.key path : web_https.key containers : - name : load-web-key-rotation image : ghcr.io/janssenproject/jans/certmanager:replace-janssen-version-1 envFrom : - configMapRef : name : janssen-config-cm #This may be differnet in Helm volumeMounts : - name : web-cert mountPath : /etc/certs/web_https.crt subPath : web_https.crt - name : web-key mountPath : /etc/certs/web_https.key subPath : web_https.key args : [ \"patch\" , \"web\" , \"--opts\" , \"source:from-files\" ] Apply job kubectl apply -f load-web-key-rotation.yaml -n <jans-namespace>", "title": "Load from existing source"}, {"location": "janssen-server/kubernetes-ops/cert-management/#auth-server", "text": "Warning key rotation CronJob is usually installed with jans. Please make sure before deploying using kubectl get cronjobs -n <jans-namespace> Associated certificates and keys /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Create a file named auth-key-rotation.yaml with the following contents : kind : CronJob apiVersion : batch/v1 metadata : name : auth-key-rotation spec : # runs the job every 48 hours schedule : \"@every 48h\" concurrencyPolicy : Forbid jobTemplate : spec : template : metadata : annotations : sidecar.istio.io/inject : \"false\" spec : containers : - name : auth-key-rotation image : ghcr.io/janssenproject/jans/certmanager:replace-janssen-version-1 resources : requests : memory : \"300Mi\" cpu : \"300m\" limits : memory : \"300Mi\" cpu : \"300m\" envFrom : - configMapRef : name : janssen-config-cm args : [ \"patch\" , \"auth\" , \"--opts\" , \"interval:48\" , \"--opts\" , \"key-strategy:OLDER\" , \"--opts\" , \"privkey-push-delay:300\" , \"--opts\" , \"privkey-push-strategy:NEWER\" ] restartPolicy : Never Apply cron job kubectl apply -f auth-key-rotation.yaml -n <jans-namespace>", "title": "Auth-server"}, {"location": "janssen-server/kubernetes-ops/custom-attributes/", "tags": ["administration", "kubernetes", "operations", "custom attributes", "schema", "claim"], "text": "Overview # Making changes in the schema to add custom columns/attributes Download the custom_schema.json file: wget https://raw.githubusercontent.com/JanssenProject/jans/main/jans-linux-setup/jans_setup/schema/custom_schema.json Make your edits in custom_schema.json : For example we will add 4 attributes and define them as int, json, bool, and text Firstly, add the attribute names to the object class: \"objectClasses\": [ { \"kind\": \"AUXILIARY\", \"may\": [ \"intAttribute\", \"jsonAttribute\", \"boolAttribute\", \"textAttribute\" Describe the attributes inside attributeTypes . You can refer to RFC 4517 : \"attributeTypes\": [ { \"desc\": \"int desc\", \"equality\": \"integerMatch\", \"names\": [ \"intAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.27\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"json desc\", \"equality\": \"caseIgnoreSubstringsMatch\", \"names\": [ \"jsonAttribute\" ], \"multivalued\": true, \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.15\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"bool desc\", \"equality\": \"booleanMatch\", \"names\": [ \"boolAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.7\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"text desc\", \"equality\": \"caseIgnoreMatch\", \"names\": [ \"textAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.15\", \"x_origin\": \"Jans created attribute\" } ], Create a configmap with the schema file: kubectl create cm custom-schema-cm --from-file=custom_schema.json -n <namespace> Mount the configmap in your override.yaml under persistence.volumes and persistence.volumeMounts : persistence: volumeMounts: - name: schema mountPath: /app/schema/custom_schema.json subPath: custom_schema.json volumes: - name: schema configMap: name: custom-schema-cm Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f override.yaml --version = 1 .0.x", "title": "Custom Attributes"}, {"location": "janssen-server/kubernetes-ops/custom-attributes/#overview", "text": "Making changes in the schema to add custom columns/attributes Download the custom_schema.json file: wget https://raw.githubusercontent.com/JanssenProject/jans/main/jans-linux-setup/jans_setup/schema/custom_schema.json Make your edits in custom_schema.json : For example we will add 4 attributes and define them as int, json, bool, and text Firstly, add the attribute names to the object class: \"objectClasses\": [ { \"kind\": \"AUXILIARY\", \"may\": [ \"intAttribute\", \"jsonAttribute\", \"boolAttribute\", \"textAttribute\" Describe the attributes inside attributeTypes . You can refer to RFC 4517 : \"attributeTypes\": [ { \"desc\": \"int desc\", \"equality\": \"integerMatch\", \"names\": [ \"intAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.27\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"json desc\", \"equality\": \"caseIgnoreSubstringsMatch\", \"names\": [ \"jsonAttribute\" ], \"multivalued\": true, \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.15\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"bool desc\", \"equality\": \"booleanMatch\", \"names\": [ \"boolAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.7\", \"x_origin\": \"Jans created attribute\" }, { \"desc\": \"text desc\", \"equality\": \"caseIgnoreMatch\", \"names\": [ \"textAttribute\" ], \"oid\": \"jansAttr\", \"syntax\": \"1.3.6.1.4.1.1466.115.121.1.15\", \"x_origin\": \"Jans created attribute\" } ], Create a configmap with the schema file: kubectl create cm custom-schema-cm --from-file=custom_schema.json -n <namespace> Mount the configmap in your override.yaml under persistence.volumes and persistence.volumeMounts : persistence: volumeMounts: - name: schema mountPath: /app/schema/custom_schema.json subPath: custom_schema.json volumes: - name: schema configMap: name: custom-schema-cm Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f override.yaml --version = 1 .0.x", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/customization/", "tags": ["administration", "developer", "operations", "kubernetes", "customization"], "text": "Most organizations will want to edit and customize the look and feel of public-facing jans server pages to match their own corporate branding. The following documentation provides the file locations of public facing pages, as well as instructions for adding custom HTML, CSS, and Javascript files to your jans server. Overview # All web pages are xhtml files. Default pages bundled in the jans-auth.war are: # Login page: login.xhtml Authorization page: authorize.xhtml Logout page: logout.xhtml Error page: error.xhtml To override default pages listed above: # Put a modified login.xhtml or authorize.xhtml or error.xhtml or logout.xhtml under /opt/jans/jetty/jans-auth/custom/pages/ Directory structure for customization # /opt/jans/jetty/jans-auth/ |-- custom | |-- i18n (resource bundles) | |-- libs (library files used by custom script) | |-- pages (web pages) | |-- static (images and css files) Adding a new web page for Person Authentication scripts # If enterOTP.xhtml is your webpage for step 2 of authentication, place it under /opt/jans/jetty/jans-auth/custom/pages/auth/enterOTP.xhtml Reference it in the custom script as follows: def getPageForStep(self, configurationAttributes, step): # Used to specify the page you want to return for a given step if (step == 1): return \"/auth/login.xhtml\" if (step == 2) return \"/auth/enterOTP.xhtml\" Reference login pages # Here you will find several login pages for different authentication methods. Customized resource bundles # Resource bundles that are present in the jans-auth.war are present in this folder To override the defaults, custom .properties files should be placed in the following file under this path : /opt/jans/jetty/jans-auth/custom/i18n/jans-auth.properties Resource bundle names to support other languages should be placed under the same folder /opt/jans/jetty/jans-auth/custom/i18n/ . Some examples of file names are : jans-auth_en.properties jans-auth_bg.properties jans-auth_de.properties jans-auth_es.properties jans-auth_fr.properties jans-auth_it.properties jans-auth_ru.properties jans-auth_tr.properties To add translation for a language that is not yet supported, create new properties file in resource folder and name it jans-auth_[language_code].properties, then add language code as supported-locale to the faces-config.xml present in the same folder. Custom CSS files # Place the file in /opt/jans/jetty/jans-auth/custom/static/stylesheet/theme.css Reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/stylesheet/theme.css or /jans-auth/ext/resources/stylesheet/theme.css Custom image files # All images should be placed under /opt/jans/jetty/jans-auth/custom/static/img Reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/img/fileName.png or /jans-auth/ext/resources/img/fileName.jpg Page layout, header, footer (xhtml Template) customization # Templates refers to the common interface layout and style. For example, a banner, logo in common header and copyright information in footer. All templates should be placed under /opt/jans/jetty/jans-auth/custom/pages/WEB-INF/incl/layout/ Place a modified template.xhtml in the above location which will override the default template file from the war Custom Jar file for scripts # for JARs less than 1MB # Create a configmap with the custom jar file: kubectl -n <namespace> create cm my-custom-jar --from-file=mycustom.jar Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts auth-server: volumeMounts: - name: my-custom-jar-volume mountPath: /opt/jans/jetty/jans-auth/custom/libs/mycustom.jar subPath: mycustom.jar volumes: - name: my-custom-jar-volume configMap: name: my-custom-jar Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x For JARs greater than 1MB # Create a configmap or secret for a shell script that contains instructions to pull the custom jar file: #!/bin/sh # This script will pull the custom jar file from a remote location # and place it in the correct location for the Jans Auth server to use it wget -O /opt/jans/jetty/jans-auth/custom/libs/mycustom.jar https://mydomain.com/mycustom.jar kubectl -n <namespace> create cm my-custom-jar --from-file=mycustomjar.sh Mount the configmap or secret in your values.yaml under auth-server.volumes and auth-server.volumeMounts auth-server: volumeMounts: - name: my-custom-jar-volume mountPath: /tmp/mycustomjar.sh subPath: mycustomjar.sh volumes: - name: my-custom-jar-volume configMap: name: my-custom-jar defaultMode: 0755 customScripts: - /tmp/mycustomjar.sh Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Customized pages examples # Custom Login page # This guide will demonstrate how to customize the html and css of the default login page. Here's a screenshot of the default login page. As an example, we will add text to the top of the form and change the color of the button using the following steps: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the login.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/login.xhtml login.xhtml Modify the file locally: < h:form id = \"loginForm\" class = \"bg-highlight position-relative d-flex flex-column align-items-center justify-content-center\" style = \"height: 100vh; gap: 2rem\" > <!-- customization --> < div class = \"row\" >< p id = \"creds-title\" > Enter Credentials </ p ></ div > <!-- end of customization --> Get the login-template.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/WEB-INF/incl/layout/login-template.xhtml login-template.xhtml Modify the file locally: < h:head > < link type = \"text/css\" rel = \"stylesheet\" href = \"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" /> <!-- customization --> < link rel = \"stylesheet\" href = \"/jans-auth/ext/resources/stylesheet/custom.css\" /> <!-- end of customization --> </ h:head > Copy the following text and save it as custom.css : # creds-title { font-style : italic ; font-weight : bolder ; color : white ; font-size : 2 em ; } Create configmaps to store the content of login.xhtml , login-template.xhtml and custom.css . kubectl -n <namespace> create cm auth-server-custom-html --from-file = login.xhtml kubectl -n <namespace> create cm auth-server-custom-layout-html --from-file = login-template.xhtml kubectl -n <namespace> create cm auth-server-custom-css --from-file = custom.css Mount the configmaps in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : auth-server-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # login.xthml will be mounted under this directory - name : auth-server-layout-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages/WEB-INF/incl/layout # login-template.xthml will be mounted under this directory - name : auth-server-static-volume mountPath : /tmp/static #custom.css will be mounted in the temporary location lifecycle : postStart : exec : command : [ \"sh\" , \"-c\" , \"mkdir /opt/jans/jetty/jans-auth/custom/static/stylesheet/ && cp /tmp/static/custom.css /opt/jans/jetty/jans-auth/custom/static/stylesheet/\" ] # custom.css will be copied from the temporary to the desired location volumes : - name : auth-server-pages-volume configMap : name : auth-server-custom-html - name : auth-server-layout-volume configMap : name : auth-server-custom-layout-html - name : auth-server-static-volume configMap : name : auth-server-custom-css Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized login page. Custom Device-code page # This guide will demonstrate how to customize the html and css of the device-code page. Here's a screenshot of the device-code page. As an example, we will change the color of the button to blue using the following steps: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the device_authorization.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/device_authorization.xhtml device_authorization.xhtml Modify the file locally: < div class = \"device-authz-button\" > < div style = \"width: 100%\" > <!-- customization --> < div style = \"text-align: center;\" > < h:commandButton id = \"continueButton\" style = \"background-color: red; color: white;\" value = \"#{msgs['device.authorization.confirm.button']}\" iconAwesome = \"fa-sign-in\" > < f:ajax execute = \"@form\" render = \"@form messages\" listener = \"#{deviceAuthorizationAction.processUserCodeVerification}\" /> </ h:commandButton > </ div > <!-- end of customization --> Create a configmap to store the content of device_authorization.xhtml . kubectl -n <namespace> create cm device-code-custom-html --from-file = device_authorization.xhtml Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : device-code-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # device_authorization.xthml will be mounted under this directory volumes : - name : device-code-pages-volume configMap : name : device-code-custom-html Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized device-code page. Custom Error page # This guide will demonstrate how to customize the html and css of the error page. Here's a screenshot of the default Error page. As an example, we will change the color of the text at the top of the error page: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the error.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/error.xhtml error.xhtml Modify the file locally: < div class = \"section\" > <!-- customization --> < h1 style = \"color: red; font-size: 3em; font-weight: bold; font-family: Arial\" > OOPS </ h1 > <!-- end of customization --> </ div > Create a configmap to store the content of error.xhtml . kubectl -n <namespace> create cm error-custom-html --from-file = error.xhtml Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : error-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # error.xthml will be mounted under this directory volumes : - name : error-pages-volume configMap : name : error-custom-html Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized error page.", "title": "Customization"}, {"location": "janssen-server/kubernetes-ops/customization/#overview", "text": "All web pages are xhtml files.", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/customization/#default-pages-bundled-in-the-jans-authwar-are", "text": "Login page: login.xhtml Authorization page: authorize.xhtml Logout page: logout.xhtml Error page: error.xhtml", "title": "Default pages bundled in the jans-auth.war are:"}, {"location": "janssen-server/kubernetes-ops/customization/#to-override-default-pages-listed-above", "text": "Put a modified login.xhtml or authorize.xhtml or error.xhtml or logout.xhtml under /opt/jans/jetty/jans-auth/custom/pages/", "title": "To override default pages listed above:"}, {"location": "janssen-server/kubernetes-ops/customization/#directory-structure-for-customization", "text": "/opt/jans/jetty/jans-auth/ |-- custom | |-- i18n (resource bundles) | |-- libs (library files used by custom script) | |-- pages (web pages) | |-- static (images and css files)", "title": "Directory structure for customization"}, {"location": "janssen-server/kubernetes-ops/customization/#adding-a-new-web-page-for-person-authentication-scripts", "text": "If enterOTP.xhtml is your webpage for step 2 of authentication, place it under /opt/jans/jetty/jans-auth/custom/pages/auth/enterOTP.xhtml Reference it in the custom script as follows: def getPageForStep(self, configurationAttributes, step): # Used to specify the page you want to return for a given step if (step == 1): return \"/auth/login.xhtml\" if (step == 2) return \"/auth/enterOTP.xhtml\"", "title": "Adding a new web page for Person Authentication scripts"}, {"location": "janssen-server/kubernetes-ops/customization/#reference-login-pages", "text": "Here you will find several login pages for different authentication methods.", "title": "Reference login pages"}, {"location": "janssen-server/kubernetes-ops/customization/#customized-resource-bundles", "text": "Resource bundles that are present in the jans-auth.war are present in this folder To override the defaults, custom .properties files should be placed in the following file under this path : /opt/jans/jetty/jans-auth/custom/i18n/jans-auth.properties Resource bundle names to support other languages should be placed under the same folder /opt/jans/jetty/jans-auth/custom/i18n/ . Some examples of file names are : jans-auth_en.properties jans-auth_bg.properties jans-auth_de.properties jans-auth_es.properties jans-auth_fr.properties jans-auth_it.properties jans-auth_ru.properties jans-auth_tr.properties To add translation for a language that is not yet supported, create new properties file in resource folder and name it jans-auth_[language_code].properties, then add language code as supported-locale to the faces-config.xml present in the same folder.", "title": "Customized resource bundles"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-css-files", "text": "Place the file in /opt/jans/jetty/jans-auth/custom/static/stylesheet/theme.css Reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/stylesheet/theme.css or /jans-auth/ext/resources/stylesheet/theme.css", "title": "Custom CSS files"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-image-files", "text": "All images should be placed under /opt/jans/jetty/jans-auth/custom/static/img Reference it in .xhtml file using the URL https://your.jans.server/jans-auth/ext/resources/img/fileName.png or /jans-auth/ext/resources/img/fileName.jpg", "title": "Custom image files"}, {"location": "janssen-server/kubernetes-ops/customization/#page-layout-header-footer-xhtml-template-customization", "text": "Templates refers to the common interface layout and style. For example, a banner, logo in common header and copyright information in footer. All templates should be placed under /opt/jans/jetty/jans-auth/custom/pages/WEB-INF/incl/layout/ Place a modified template.xhtml in the above location which will override the default template file from the war", "title": "Page layout, header, footer (xhtml Template) customization"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-jar-file-for-scripts", "text": "", "title": "Custom Jar file for scripts"}, {"location": "janssen-server/kubernetes-ops/customization/#for-jars-less-than-1mb", "text": "Create a configmap with the custom jar file: kubectl -n <namespace> create cm my-custom-jar --from-file=mycustom.jar Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts auth-server: volumeMounts: - name: my-custom-jar-volume mountPath: /opt/jans/jetty/jans-auth/custom/libs/mycustom.jar subPath: mycustom.jar volumes: - name: my-custom-jar-volume configMap: name: my-custom-jar Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x", "title": "for JARs less than 1MB"}, {"location": "janssen-server/kubernetes-ops/customization/#for-jars-greater-than-1mb", "text": "Create a configmap or secret for a shell script that contains instructions to pull the custom jar file: #!/bin/sh # This script will pull the custom jar file from a remote location # and place it in the correct location for the Jans Auth server to use it wget -O /opt/jans/jetty/jans-auth/custom/libs/mycustom.jar https://mydomain.com/mycustom.jar kubectl -n <namespace> create cm my-custom-jar --from-file=mycustomjar.sh Mount the configmap or secret in your values.yaml under auth-server.volumes and auth-server.volumeMounts auth-server: volumeMounts: - name: my-custom-jar-volume mountPath: /tmp/mycustomjar.sh subPath: mycustomjar.sh volumes: - name: my-custom-jar-volume configMap: name: my-custom-jar defaultMode: 0755 customScripts: - /tmp/mycustomjar.sh Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x", "title": "For JARs greater than 1MB"}, {"location": "janssen-server/kubernetes-ops/customization/#customized-pages-examples", "text": "", "title": "Customized pages examples"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-login-page", "text": "This guide will demonstrate how to customize the html and css of the default login page. Here's a screenshot of the default login page. As an example, we will add text to the top of the form and change the color of the button using the following steps: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the login.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/login.xhtml login.xhtml Modify the file locally: < h:form id = \"loginForm\" class = \"bg-highlight position-relative d-flex flex-column align-items-center justify-content-center\" style = \"height: 100vh; gap: 2rem\" > <!-- customization --> < div class = \"row\" >< p id = \"creds-title\" > Enter Credentials </ p ></ div > <!-- end of customization --> Get the login-template.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/WEB-INF/incl/layout/login-template.xhtml login-template.xhtml Modify the file locally: < h:head > < link type = \"text/css\" rel = \"stylesheet\" href = \"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" /> <!-- customization --> < link rel = \"stylesheet\" href = \"/jans-auth/ext/resources/stylesheet/custom.css\" /> <!-- end of customization --> </ h:head > Copy the following text and save it as custom.css : # creds-title { font-style : italic ; font-weight : bolder ; color : white ; font-size : 2 em ; } Create configmaps to store the content of login.xhtml , login-template.xhtml and custom.css . kubectl -n <namespace> create cm auth-server-custom-html --from-file = login.xhtml kubectl -n <namespace> create cm auth-server-custom-layout-html --from-file = login-template.xhtml kubectl -n <namespace> create cm auth-server-custom-css --from-file = custom.css Mount the configmaps in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : auth-server-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # login.xthml will be mounted under this directory - name : auth-server-layout-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages/WEB-INF/incl/layout # login-template.xthml will be mounted under this directory - name : auth-server-static-volume mountPath : /tmp/static #custom.css will be mounted in the temporary location lifecycle : postStart : exec : command : [ \"sh\" , \"-c\" , \"mkdir /opt/jans/jetty/jans-auth/custom/static/stylesheet/ && cp /tmp/static/custom.css /opt/jans/jetty/jans-auth/custom/static/stylesheet/\" ] # custom.css will be copied from the temporary to the desired location volumes : - name : auth-server-pages-volume configMap : name : auth-server-custom-html - name : auth-server-layout-volume configMap : name : auth-server-custom-layout-html - name : auth-server-static-volume configMap : name : auth-server-custom-css Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized login page.", "title": "Custom Login page"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-device-code-page", "text": "This guide will demonstrate how to customize the html and css of the device-code page. Here's a screenshot of the device-code page. As an example, we will change the color of the button to blue using the following steps: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the device_authorization.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/device_authorization.xhtml device_authorization.xhtml Modify the file locally: < div class = \"device-authz-button\" > < div style = \"width: 100%\" > <!-- customization --> < div style = \"text-align: center;\" > < h:commandButton id = \"continueButton\" style = \"background-color: red; color: white;\" value = \"#{msgs['device.authorization.confirm.button']}\" iconAwesome = \"fa-sign-in\" > < f:ajax execute = \"@form\" render = \"@form messages\" listener = \"#{deviceAuthorizationAction.processUserCodeVerification}\" /> </ h:commandButton > </ div > <!-- end of customization --> Create a configmap to store the content of device_authorization.xhtml . kubectl -n <namespace> create cm device-code-custom-html --from-file = device_authorization.xhtml Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : device-code-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # device_authorization.xthml will be mounted under this directory volumes : - name : device-code-pages-volume configMap : name : device-code-custom-html Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized device-code page.", "title": "Custom Device-code page"}, {"location": "janssen-server/kubernetes-ops/customization/#custom-error-page", "text": "This guide will demonstrate how to customize the html and css of the error page. Here's a screenshot of the default Error page. As an example, we will change the color of the text at the top of the error page: Locate the directory that contains exploded auth-server WAR kubectl exec -n <namespace> <auth-server-pod-name> -- ls /opt/jetty/temp Output example: jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753 Get the error.xhtml from the auth-server pod: kubectl -n jans cp <auth-server-pod-name>:opt/jetty/temp/jetty-0_0_0_0-8080-jans-auth_war-_jans-auth-any-15449359106458251753/webapp/error.xhtml error.xhtml Modify the file locally: < div class = \"section\" > <!-- customization --> < h1 style = \"color: red; font-size: 3em; font-weight: bold; font-family: Arial\" > OOPS </ h1 > <!-- end of customization --> </ div > Create a configmap to store the content of error.xhtml . kubectl -n <namespace> create cm error-custom-html --from-file = error.xhtml Mount the configmap in your values.yaml under auth-server.volumes and auth-server.volumeMounts : auth-server : volumeMounts : - name : error-pages-volume mountPath : /opt/jans/jetty/jans-auth/custom/pages # error.xthml will be mounted under this directory volumes : - name : error-pages-volume configMap : name : error-custom-html Run helm install or helm upgrade if Jans has been already installed. helm upgrade <helm-release-name> janssen/janssen -n <namespace> -f values.yaml --version = 1 .0.x Here's a screenshot of the customized error page.", "title": "Custom Error page"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/", "text": "Overview # This guide shows how to store and retrieve jans configmaps and secrets externally in AWS Secrets Manager , GCP Secret Manager and Vault . Note Configmaps and Secrets are stored as a collection of key-value pairs. A secret in AWS/GCP Secret Manager has a max size of 65536 bytes. So the collection of key-value pairs is splitted between secrets, and thus note that during secrets retrieval it's possible that a single key-value pair is to be splitted between 2 AWS/GCP secrets. Create Secrets # AWS # There are 2 types of Secrets in AWS: String Secret where the secret can be created and retrieved from the console. Binary Secret where the secret is binary-encoded and can be created and retrieved only using the CLI/SDK. Configmaps are stored in a single String Secret . It follows the naming convention of janssen_configs Secrets are splitted and stored in multiple Binary Secrets due to the max size limitation. Secrets follows the naming convention of janssen_secrets , janssen_secrets_1 , janssen_secrets_2 ..etc Every single secret doesn't have to be a valid json, but instead the collection of all secrets should have a valid json. For example: janssen_secrets : {\"key1\":\"value1\", janssen_secrets_1 : \"key2\":\"value2\", janssen_secrets_2 : \"key3\":\"value3\"} Fresh Installation # You will need the ACCESS_KEY_ID and SECRET_ACCESS_KEY of an IAM user with a SecretsManagerReadWrite policy attached. Add the following configuration to your override.yaml : global : configAdapterName : aws configSecretAdapter : aws config : configmap : cnAwsAccessKeyId : L30E10OME18S1220S221 cnAwsSecretAccessKey : Z1A1M9A1L1EKALIeHHN~o cnAwsDefaultRegion : us-east-1 #Choose based on the desired region cnAwsSecretsEndpointUrl : https://secretsmanager.us-east-1.amazonaws.com #Choose based on the desired region cnAwsSecretsNamePrefix : janssen cnAwsProfile : janssen #Choose based on your aws named profile cnAwsSecretsReplicaRegions : [] #Optional if you want secrets to be replicated. [{\"Region\": \"us-west-1\"}, {\"Region\": \"us-west-2\"}] Run helm install or helm upgrade if Janssen is already installed: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> Export/Migration # Configmaps # Get the json of the configmap kubectl get configmap -n <namespace> cn -o json Configmaps in AWS are stored as StringSecret , they can be created and retrieved from the console: Click Create Secret > Choose Other type of Secret > Click on Plaintext tab > Paste the json of the key-value pairs. Secrets # Get the json of the secret kubectl get secret -n <namespace> cn -o json Secrets in AWS are splitted across multiple BinarySecrets which is created and retrieved using the CLI/SDK Assuming the json is stored in a file named binary-secrets.json : aws secretsmanager create-secret --name <secret-name> --secret-binary fileb://binary-secrets.json --region <secret-region> GCP # Fresh Installation # Make sure you enabled Secret Manager API . You will need a Service account with the roles/secretmanager.admin role. This service account json should then be base64 encoded. Add the following configuration to your override.yaml : global : configAdapterName : google configSecretAdapter : google config : configmap : cnGoogleSecretManagerServiceAccount : SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo= #base64 encoded service account json cnGoogleProjectId : google-project-to-save-config-and-secrets-to cnSecretGoogleSecretVersionId : \"latest\" # Secret version to be used for secret configuration. Defaults to latest and should normally always stay that way. cnSecretGoogleSecretNamePrefix : janssen cnGoogleSecretManagerPassPhrase : Test1234# #Passphrase for Janssen secret in Google Secret Manager. Used for encrypting and decrypting data from Google's Secret Manager. cnConfigGoogleSecretVersionId : \"latest\" #Secret version to be used for configuration. Defaults to latest and should normally always stay that way. cnConfigGoogleSecretNamePrefix : janssen Run helm install or helm upgrade if Janssen is already installed: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> Export/Migration # Get the json of the secret/configmap kubectl get configmap -n <namespace> cn -o json From the console, Go to Secret Manager > Click on Create Secret > Add a name > Upload a json file or add the json to the Secret value field > Create Managing Versions # While there's no limitation on how many versions a secret can have, the recommendation is to keep the number as low as possible, e.g. 5 active versions. If there are too many secret versions, it's best to destroy older versions manually, for example: gcloud secrets versions list jans-secret --filter = \"state = enabled\" --filter = \"createTime < '2024-03-02'\" | grep \"NAME:\" | tr -d \"NAME: \" > versions_to_destroy.txt while read -r line ; do gcloud secrets versions destroy \" $line \" --secret = jans-secret done < \"versions_to_destroy.txt\" Vault # Note The deployment of Vault is hosted on-premises, not within the HashiCorp Cloud Platform service Enable the KV secrets engine version 1 in Vault. For example: vault secrets enable -path=secret -version=1 kv Note that the path i.e. secret will be mapped to cnVaultKvPath later. Create a policy , which will be attached later to the appRole . Create first a file named policy.hcl with the required capabilities. path \"secret/<name>/*\" { capabilities = [\"create\", \"list\", \"read\", \"delete\", \"update\"] } Note that <name> will be mapped to cnVaultPrefix later. Create the policy: vault policy write <name> /path/to/policy.hcl Enable and configure appRole . You have also to reference the previously created policy. For example: vault auth enable -path=approle approle vault write auth/approle/role/<role-name> token_policies=\"<policy-name>\" The default appRole path is approle which will be mapped to cnVaultAppRolePath later. Add the following configuration to your override.yaml : global : configSecretAdapter : vault config : configmap : # -- Vault AppRole RoleID. cnVaultRoleId : \"\" # -- Vault AppRole SecretID. cnVaultSecretId : \"\" # -- Base URL of Vault. cnVaultAddr : http://localhost:8200 # -- Verify connection to Vault. cnVaultVerify : false # -- Path to file contains Vault AppRole role ID. cnVaultRoleIdFile : /etc/certs/vault_role_id # -- Path to file contains Vault AppRole secret ID. cnVaultSecretIdFile : /etc/certs/vault_secret_id # -- Vault namespace used to access the secrets. cnVaultNamespace : \"\" # -- Path to Vault KV secrets engine. cnVaultKvPath : secret # -- Base prefix name used to access secrets. cnVaultPrefix : jans # -- Path to Vault AppRole. cnVaultAppRolePath : approle 5. Run helm install or helm upgrade Retrieve Secrets # AWS # String Secret : To retrieve the secret value from the Console, click on the secret name and then click on Retrieve Secret Value Binary Secret : To retrieve the secret value using the cli aws secretsmanager get-secret-value --secret-id <secret-name> --query 'SecretBinary' --output text --region <secret-region> Note that the secret is binary encoded, so in order to have a decoded value, you can run the following aws secretsmanager get-secret-value --secret-id <secret-name> --query 'SecretBinary' --output text --region <secret-region> | base64 --decode Repeat these commands across all the secrets, to get the full key-value pairs. GCP # Review this to check multiple ways to retrieve secrets stored in GCP Secret Manager.", "title": "External Secrets and Configmaps"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#overview", "text": "This guide shows how to store and retrieve jans configmaps and secrets externally in AWS Secrets Manager , GCP Secret Manager and Vault . Note Configmaps and Secrets are stored as a collection of key-value pairs. A secret in AWS/GCP Secret Manager has a max size of 65536 bytes. So the collection of key-value pairs is splitted between secrets, and thus note that during secrets retrieval it's possible that a single key-value pair is to be splitted between 2 AWS/GCP secrets.", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#create-secrets", "text": "", "title": "Create Secrets"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#aws", "text": "There are 2 types of Secrets in AWS: String Secret where the secret can be created and retrieved from the console. Binary Secret where the secret is binary-encoded and can be created and retrieved only using the CLI/SDK. Configmaps are stored in a single String Secret . It follows the naming convention of janssen_configs Secrets are splitted and stored in multiple Binary Secrets due to the max size limitation. Secrets follows the naming convention of janssen_secrets , janssen_secrets_1 , janssen_secrets_2 ..etc Every single secret doesn't have to be a valid json, but instead the collection of all secrets should have a valid json. For example: janssen_secrets : {\"key1\":\"value1\", janssen_secrets_1 : \"key2\":\"value2\", janssen_secrets_2 : \"key3\":\"value3\"}", "title": "AWS"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#fresh-installation", "text": "You will need the ACCESS_KEY_ID and SECRET_ACCESS_KEY of an IAM user with a SecretsManagerReadWrite policy attached. Add the following configuration to your override.yaml : global : configAdapterName : aws configSecretAdapter : aws config : configmap : cnAwsAccessKeyId : L30E10OME18S1220S221 cnAwsSecretAccessKey : Z1A1M9A1L1EKALIeHHN~o cnAwsDefaultRegion : us-east-1 #Choose based on the desired region cnAwsSecretsEndpointUrl : https://secretsmanager.us-east-1.amazonaws.com #Choose based on the desired region cnAwsSecretsNamePrefix : janssen cnAwsProfile : janssen #Choose based on your aws named profile cnAwsSecretsReplicaRegions : [] #Optional if you want secrets to be replicated. [{\"Region\": \"us-west-1\"}, {\"Region\": \"us-west-2\"}] Run helm install or helm upgrade if Janssen is already installed: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace>", "title": "Fresh Installation"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#exportmigration", "text": "", "title": "Export/Migration"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#configmaps", "text": "Get the json of the configmap kubectl get configmap -n <namespace> cn -o json Configmaps in AWS are stored as StringSecret , they can be created and retrieved from the console: Click Create Secret > Choose Other type of Secret > Click on Plaintext tab > Paste the json of the key-value pairs.", "title": "Configmaps"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#secrets", "text": "Get the json of the secret kubectl get secret -n <namespace> cn -o json Secrets in AWS are splitted across multiple BinarySecrets which is created and retrieved using the CLI/SDK Assuming the json is stored in a file named binary-secrets.json : aws secretsmanager create-secret --name <secret-name> --secret-binary fileb://binary-secrets.json --region <secret-region>", "title": "Secrets"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#gcp", "text": "", "title": "GCP"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#fresh-installation_1", "text": "Make sure you enabled Secret Manager API . You will need a Service account with the roles/secretmanager.admin role. This service account json should then be base64 encoded. Add the following configuration to your override.yaml : global : configAdapterName : google configSecretAdapter : google config : configmap : cnGoogleSecretManagerServiceAccount : SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo= #base64 encoded service account json cnGoogleProjectId : google-project-to-save-config-and-secrets-to cnSecretGoogleSecretVersionId : \"latest\" # Secret version to be used for secret configuration. Defaults to latest and should normally always stay that way. cnSecretGoogleSecretNamePrefix : janssen cnGoogleSecretManagerPassPhrase : Test1234# #Passphrase for Janssen secret in Google Secret Manager. Used for encrypting and decrypting data from Google's Secret Manager. cnConfigGoogleSecretVersionId : \"latest\" #Secret version to be used for configuration. Defaults to latest and should normally always stay that way. cnConfigGoogleSecretNamePrefix : janssen Run helm install or helm upgrade if Janssen is already installed: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace>", "title": "Fresh Installation"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#exportmigration_1", "text": "Get the json of the secret/configmap kubectl get configmap -n <namespace> cn -o json From the console, Go to Secret Manager > Click on Create Secret > Add a name > Upload a json file or add the json to the Secret value field > Create", "title": "Export/Migration"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#managing-versions", "text": "While there's no limitation on how many versions a secret can have, the recommendation is to keep the number as low as possible, e.g. 5 active versions. If there are too many secret versions, it's best to destroy older versions manually, for example: gcloud secrets versions list jans-secret --filter = \"state = enabled\" --filter = \"createTime < '2024-03-02'\" | grep \"NAME:\" | tr -d \"NAME: \" > versions_to_destroy.txt while read -r line ; do gcloud secrets versions destroy \" $line \" --secret = jans-secret done < \"versions_to_destroy.txt\"", "title": "Managing Versions"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#vault", "text": "Note The deployment of Vault is hosted on-premises, not within the HashiCorp Cloud Platform service Enable the KV secrets engine version 1 in Vault. For example: vault secrets enable -path=secret -version=1 kv Note that the path i.e. secret will be mapped to cnVaultKvPath later. Create a policy , which will be attached later to the appRole . Create first a file named policy.hcl with the required capabilities. path \"secret/<name>/*\" { capabilities = [\"create\", \"list\", \"read\", \"delete\", \"update\"] } Note that <name> will be mapped to cnVaultPrefix later. Create the policy: vault policy write <name> /path/to/policy.hcl Enable and configure appRole . You have also to reference the previously created policy. For example: vault auth enable -path=approle approle vault write auth/approle/role/<role-name> token_policies=\"<policy-name>\" The default appRole path is approle which will be mapped to cnVaultAppRolePath later. Add the following configuration to your override.yaml : global : configSecretAdapter : vault config : configmap : # -- Vault AppRole RoleID. cnVaultRoleId : \"\" # -- Vault AppRole SecretID. cnVaultSecretId : \"\" # -- Base URL of Vault. cnVaultAddr : http://localhost:8200 # -- Verify connection to Vault. cnVaultVerify : false # -- Path to file contains Vault AppRole role ID. cnVaultRoleIdFile : /etc/certs/vault_role_id # -- Path to file contains Vault AppRole secret ID. cnVaultSecretIdFile : /etc/certs/vault_secret_id # -- Vault namespace used to access the secrets. cnVaultNamespace : \"\" # -- Path to Vault KV secrets engine. cnVaultKvPath : secret # -- Base prefix name used to access secrets. cnVaultPrefix : jans # -- Path to Vault AppRole. cnVaultAppRolePath : approle 5. Run helm install or helm upgrade", "title": "Vault"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#retrieve-secrets", "text": "", "title": "Retrieve Secrets"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#aws_1", "text": "String Secret : To retrieve the secret value from the Console, click on the secret name and then click on Retrieve Secret Value Binary Secret : To retrieve the secret value using the cli aws secretsmanager get-secret-value --secret-id <secret-name> --query 'SecretBinary' --output text --region <secret-region> Note that the secret is binary encoded, so in order to have a decoded value, you can run the following aws secretsmanager get-secret-value --secret-id <secret-name> --query 'SecretBinary' --output text --region <secret-region> | base64 --decode Repeat these commands across all the secrets, to get the full key-value pairs.", "title": "AWS"}, {"location": "janssen-server/kubernetes-ops/external-secrets-configmaps/#gcp_1", "text": "Review this to check multiple ways to retrieve secrets stored in GCP Secret Manager.", "title": "GCP"}, {"location": "janssen-server/kubernetes-ops/health-check/", "tags": ["administration", "kubernetes", "operations", "health-checks"], "text": "Overview # Health checks are used to determine if a container is working as it should or not. This is done in Kubernetes using probes. Jans deployed components uses two types of probes: Readiness probes : used to know when a container is ready to start accepting traffic Liveness probes : used to know when to restart a container Jans Liveness and Readiness probes # Here is a list of the liveness and readiness probes of the deployed jans components auth-server # Auth-sever executes the python3 healthcheck.py in liveness and readiness probes. This python scripts parses the healthcheck endpoint to make sure the status is up. livenessProbe : # Executes the python3 healthcheck. exec : command : - python3 - /app/scripts/healthcheck.py # Configure the liveness healthcheck for the auth-server if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : # Executes the python3 healthcheck. exec : command : - python3 - /app/scripts/healthcheck.py # Configure the readiness healthcheck for the auth-server if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5 config-api # The health check of liveness and readiness probes is a HTTP GET request against a config-api endpoint livenessProbe : # http liveness probe endpoint httpGet : path : /jans-config-api/api/v1/health/live port : 8074 # Configure the liveness healthcheck for the config-api if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : # http readiness probe endpoint httpGet : path : jans-config-api/api/v1/health/ready port : 8074 # Configure the readiness healthcheck for the config-api if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5 fido2 # The health check of liveness and readiness probes is a HTTP GET request against a fido2 endpoint livenessProbe : # http liveness probe endpoint httpGet : path : /jans-fido2/sys/health-check port : http-fido2 # Configure the liveness healthcheck for the fido2 if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5 readinessProbe : # http readiness probe endpoint httpGet : path : /jans-fido2/sys/health-check port : http-fido2 # Configure the readiness healthcheck for the fido2 if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 scim # The health check of liveness and readiness probes is a HTTP GET request against a scim endpoint livenessProbe : httpGet : # http liveness probe endpoint path : /jans-scim/sys/health-check port : 8080 # Configure the liveness healthcheck for the SCIM if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : httpGet : # http readiness probe endpoint path : /jans-scim/sys/health-check port : 8080 # Configure the readiness healthcheck for the SCIM if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5", "title": "Health Check"}, {"location": "janssen-server/kubernetes-ops/health-check/#overview", "text": "Health checks are used to determine if a container is working as it should or not. This is done in Kubernetes using probes. Jans deployed components uses two types of probes: Readiness probes : used to know when a container is ready to start accepting traffic Liveness probes : used to know when to restart a container", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/health-check/#jans-liveness-and-readiness-probes", "text": "Here is a list of the liveness and readiness probes of the deployed jans components", "title": "Jans Liveness and Readiness probes"}, {"location": "janssen-server/kubernetes-ops/health-check/#auth-server", "text": "Auth-sever executes the python3 healthcheck.py in liveness and readiness probes. This python scripts parses the healthcheck endpoint to make sure the status is up. livenessProbe : # Executes the python3 healthcheck. exec : command : - python3 - /app/scripts/healthcheck.py # Configure the liveness healthcheck for the auth-server if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : # Executes the python3 healthcheck. exec : command : - python3 - /app/scripts/healthcheck.py # Configure the readiness healthcheck for the auth-server if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5", "title": "auth-server"}, {"location": "janssen-server/kubernetes-ops/health-check/#config-api", "text": "The health check of liveness and readiness probes is a HTTP GET request against a config-api endpoint livenessProbe : # http liveness probe endpoint httpGet : path : /jans-config-api/api/v1/health/live port : 8074 # Configure the liveness healthcheck for the config-api if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : # http readiness probe endpoint httpGet : path : jans-config-api/api/v1/health/ready port : 8074 # Configure the readiness healthcheck for the config-api if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5", "title": "config-api"}, {"location": "janssen-server/kubernetes-ops/health-check/#fido2", "text": "The health check of liveness and readiness probes is a HTTP GET request against a fido2 endpoint livenessProbe : # http liveness probe endpoint httpGet : path : /jans-fido2/sys/health-check port : http-fido2 # Configure the liveness healthcheck for the fido2 if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5 readinessProbe : # http readiness probe endpoint httpGet : path : /jans-fido2/sys/health-check port : http-fido2 # Configure the readiness healthcheck for the fido2 if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5", "title": "fido2"}, {"location": "janssen-server/kubernetes-ops/health-check/#scim", "text": "The health check of liveness and readiness probes is a HTTP GET request against a scim endpoint livenessProbe : httpGet : # http liveness probe endpoint path : /jans-scim/sys/health-check port : 8080 # Configure the liveness healthcheck for the SCIM if needed. initialDelaySeconds : 30 periodSeconds : 30 timeoutSeconds : 5 readinessProbe : httpGet : # http readiness probe endpoint path : /jans-scim/sys/health-check port : 8080 # Configure the readiness healthcheck for the SCIM if needed. initialDelaySeconds : 25 periodSeconds : 25 timeoutSeconds : 5", "title": "scim"}, {"location": "janssen-server/kubernetes-ops/jans-saml/", "tags": ["administration", "kubernetes", "operations", "jans-saml", "keycloak"], "text": "Overview # Jans-SAML/Keycloak has the flexibility to be deployed using either MySQL or PostgreSQL as its backend. MySQL # Make the following changes in your values.yaml : global : saml : enabled : true ingress : samlEnabled : true config : configmap : kcDbVendor : mysql kcDbUsername : keycloak kcDbPassword : Test1234# kcDbSchema : keycloak kcDbUrlHost : mysql.kc.svc.cluster.local kcDbUrlPort : 3306 kcDbUrlDatabase : keycloak If you provide a non-root MySQL user to Keycloak, you will encounter the following error and warnings: SQLException: XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency WARNING - jans-saml - 2024-02-05 16:54:04,256 - Unable to grant XA_RECOVER_ADMIN privilege to 'keycloak' user; reason=Access denied; you need (at least one of) the GRANT OPTION privilege(s) for this operation WARNING - jans-saml - 2024-02-05 16:54:04,256 - Got insufficient permission, please try using user with XA_RECOVER_ADMIN privilege and running the following query manually via MySQL client: \"GRANT XA_RECOVER_ADMIN ON *.* TO 'keycloak'@'%'; FLUSH PRIVILEGES;\" To resolve this issue, it's necessary to adhere to the guidance provided in the logs. PostgreSQL # Make the following changes in your values.yaml : global : saml : enabled : true ingress : samlEnabled : true config : configmap : kcDbVendor : postgres kcDbUsername : keycloak kcDbPassword : Test1234# kcDbSchema : public kcDbUrlHost : postgres.kc.svc.cluster.local kcDbUrlPort : 5432 kcDbUrlDatabase : keycloak kcDbUrlProperties : \"\"", "title": "Jans SAML/Keycloak"}, {"location": "janssen-server/kubernetes-ops/jans-saml/#overview", "text": "Jans-SAML/Keycloak has the flexibility to be deployed using either MySQL or PostgreSQL as its backend.", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/jans-saml/#mysql", "text": "Make the following changes in your values.yaml : global : saml : enabled : true ingress : samlEnabled : true config : configmap : kcDbVendor : mysql kcDbUsername : keycloak kcDbPassword : Test1234# kcDbSchema : keycloak kcDbUrlHost : mysql.kc.svc.cluster.local kcDbUrlPort : 3306 kcDbUrlDatabase : keycloak If you provide a non-root MySQL user to Keycloak, you will encounter the following error and warnings: SQLException: XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency WARNING - jans-saml - 2024-02-05 16:54:04,256 - Unable to grant XA_RECOVER_ADMIN privilege to 'keycloak' user; reason=Access denied; you need (at least one of) the GRANT OPTION privilege(s) for this operation WARNING - jans-saml - 2024-02-05 16:54:04,256 - Got insufficient permission, please try using user with XA_RECOVER_ADMIN privilege and running the following query manually via MySQL client: \"GRANT XA_RECOVER_ADMIN ON *.* TO 'keycloak'@'%'; FLUSH PRIVILEGES;\" To resolve this issue, it's necessary to adhere to the guidance provided in the logs.", "title": "MySQL"}, {"location": "janssen-server/kubernetes-ops/jans-saml/#postgresql", "text": "Make the following changes in your values.yaml : global : saml : enabled : true ingress : samlEnabled : true config : configmap : kcDbVendor : postgres kcDbUsername : keycloak kcDbPassword : Test1234# kcDbSchema : public kcDbUrlHost : postgres.kc.svc.cluster.local kcDbUrlPort : 5432 kcDbUrlDatabase : keycloak kcDbUrlProperties : \"\"", "title": "PostgreSQL"}, {"location": "janssen-server/kubernetes-ops/logs/", "tags": ["administration", "kubernetes", "operations", "logs"], "text": "Overview # The Janssen logs can be viewed using the following command: kubectl logs <pod-name> -n <namespace> Log Levels # The following log levels can be configured through the configuration CLI: Log Level Messages Logged Trace All messages Debug Debug level and above Info Informational level and above Warn Warning level and above Error Error level and above Fatal Only fatal errors Off Logging is disabled Configuring Log Levels # To get the current log level of any component, run the following command: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_<service-name>_APP_LOGGERS auth-server # To get the current log level of auth-server: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_AUTH_APP_LOGGERS Example output: CN_AUTH_APP_LOGGERS : '{ \"audit_log_level\":\"INFO\", \"audit_log_target\":\"FILE\", \"auth_log_level\":\"INFO\", \"auth_log_target\":\"STDOUT\", \"http_log_level\":\"INFO\", \"http_log_target\":\"FILE\", \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in auth-server, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : auth-server : appLoggers : authLogLevel : \"TRACE\" httpLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" auditStatsLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of auth-server: kubectl logs -f deployment/<helm-release-name>-auth-server -n <namespace> config-api # To get the current log level of config-api: kubectl get configmap -n <namspace> <helm-release-name>-config-cm -o yaml | grep CN_CONFIG_API_APP_LOGGERS Example output: CN_CONFIG_API_APP_LOGGERS : '{ \"config_api_log_level\":\"INFO\", \"config_api_log_target\":\"STDOUT\", \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in config-api, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : config-api : appLoggers : configApiLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of config-api: kubectl logs -f deployment/<helm-release-name>-config-api -n <namespace> fido2 # To get the current log level of fido2: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_FIDO2_APP_LOGGERS Example output: CN_FIDO2_APP_LOGGERS : '{ \"fido2_log_level\":\"INFO\", \"fido2_log_target\":\"STDOUT\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\" }' To override the current logging level in fido2, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : fido2 : appLoggers : fido2LogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of fido2: kubectl logs -f deployment/<helm-release-name>-fido2 -n <namespace> scim # To get the current log level of scim: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_SCIM_APP_LOGGERS Example output: CN_SCIM_APP_LOGGERS : '{ \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"scim_log_level\":\"INFO\", \"scim_log_target\":\"STDOUT\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in scim, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : scim : appLoggers : scimLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of scim: kubectl logs -f deployment/<helm-release-name>-scim -n <namespace> Hack it # Warning This can cause deployments to break, but if you wish you may edit it directly and restart the wanted deployment Edit using the following command: kubectl edit configmap <helm-release-name>-config-cm -n <namespace> Restart the wanted deployment: kubectl rollout restart deployment <deployment-name> -n <namespace>", "title": "Logs"}, {"location": "janssen-server/kubernetes-ops/logs/#overview", "text": "The Janssen logs can be viewed using the following command: kubectl logs <pod-name> -n <namespace>", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/logs/#log-levels", "text": "The following log levels can be configured through the configuration CLI: Log Level Messages Logged Trace All messages Debug Debug level and above Info Informational level and above Warn Warning level and above Error Error level and above Fatal Only fatal errors Off Logging is disabled", "title": "Log Levels"}, {"location": "janssen-server/kubernetes-ops/logs/#configuring-log-levels", "text": "To get the current log level of any component, run the following command: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_<service-name>_APP_LOGGERS", "title": "Configuring Log Levels"}, {"location": "janssen-server/kubernetes-ops/logs/#auth-server", "text": "To get the current log level of auth-server: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_AUTH_APP_LOGGERS Example output: CN_AUTH_APP_LOGGERS : '{ \"audit_log_level\":\"INFO\", \"audit_log_target\":\"FILE\", \"auth_log_level\":\"INFO\", \"auth_log_target\":\"STDOUT\", \"http_log_level\":\"INFO\", \"http_log_target\":\"FILE\", \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in auth-server, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : auth-server : appLoggers : authLogLevel : \"TRACE\" httpLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" auditStatsLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of auth-server: kubectl logs -f deployment/<helm-release-name>-auth-server -n <namespace>", "title": "auth-server"}, {"location": "janssen-server/kubernetes-ops/logs/#config-api", "text": "To get the current log level of config-api: kubectl get configmap -n <namspace> <helm-release-name>-config-cm -o yaml | grep CN_CONFIG_API_APP_LOGGERS Example output: CN_CONFIG_API_APP_LOGGERS : '{ \"config_api_log_level\":\"INFO\", \"config_api_log_target\":\"STDOUT\", \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in config-api, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : config-api : appLoggers : configApiLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of config-api: kubectl logs -f deployment/<helm-release-name>-config-api -n <namespace>", "title": "config-api"}, {"location": "janssen-server/kubernetes-ops/logs/#fido2", "text": "To get the current log level of fido2: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_FIDO2_APP_LOGGERS Example output: CN_FIDO2_APP_LOGGERS : '{ \"fido2_log_level\":\"INFO\", \"fido2_log_target\":\"STDOUT\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\" }' To override the current logging level in fido2, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : fido2 : appLoggers : fido2LogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of fido2: kubectl logs -f deployment/<helm-release-name>-fido2 -n <namespace>", "title": "fido2"}, {"location": "janssen-server/kubernetes-ops/logs/#scim", "text": "To get the current log level of scim: kubectl get configmap -n <namespace> <helm-release-name>-config-cm -o yaml | grep CN_SCIM_APP_LOGGERS Example output: CN_SCIM_APP_LOGGERS : '{ \"persistence_duration_log_level\":\"INFO\", \"persistence_duration_log_target\":\"FILE\", \"persistence_log_level\":\"INFO\", \"persistence_log_target\":\"FILE\", \"scim_log_level\":\"INFO\", \"scim_log_target\":\"STDOUT\", \"script_log_level\":\"INFO\", \"script_log_target\":\"FILE\" }' To override the current logging level in scim, you can either add the desired changes to a yaml file and apply it using helm , or change it directly using kubectl edit command: Add changes to yaml: add these changes to your override.yaml file: ............ ............ global : scim : appLoggers : scimLogLevel : \"TRACE\" persistenceLogLevel : \"TRACE\" persistenceDurationLogLevel : \"TRACE\" scriptLogLevel : \"TRACE\" ............ ............ Apply the changes: helm upgrade <helm-release-name> janssen/janssen -f override.yaml -n <namespace> View the logs of scim: kubectl logs -f deployment/<helm-release-name>-scim -n <namespace>", "title": "scim"}, {"location": "janssen-server/kubernetes-ops/logs/#hack-it", "text": "Warning This can cause deployments to break, but if you wish you may edit it directly and restart the wanted deployment Edit using the following command: kubectl edit configmap <helm-release-name>-config-cm -n <namespace> Restart the wanted deployment: kubectl rollout restart deployment <deployment-name> -n <namespace>", "title": "Hack it"}, {"location": "janssen-server/kubernetes-ops/memory-dump/", "tags": ["administration", "kubernetes", "operations", "memory", "dump", "heap"], "text": "Overview # This document will demonstrate how to generate a memory dump so that you can analyze your memory usage. Services supported # This operation can be made in the following Java-based services: Service JAVA_OPTIONS environment variable auth-server CN_AUTH_JAVA_OPTIONS casa CN_CASA_JAVA_OPTIONS config-api CN_CONFIG_API_JAVA_OPTIONS fido2 CN_FIDO2_JAVA_OPTIONS link CN_LINK_JAVA_OPTIONS saml CN_SAML_JAVA_OPTIONS scim CN_SCIM_JAVA_OPTIONS Steps # Let's go through the steps needed to generate a dump in config-api : Increase the pod's memory request and limit to something larger than the default. Edit the config-api deployment and modify the JAVA_OPTIONS: env: - name: CN_CONFIG_API_JAVA_OPTIONS value: -XX:MaxDirectMemorySize=400m -Xmx150m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -XX:MaxRAMPercentage=0 Modify the command key in the deployment to add the following: command: - /bin/sh - -c - | /app/scripts/entrypoint.sh & sleep 900000000 You can view the heap usage using the following command: kubectl exec -n <namespace> pod-name -- jcmd 7 GC.heap_info Now once the process meets its limit, the process should shut down without the pod getting an OOM, allowing you to get the dump from within the pod. Copy the generated dump from the pod: kubectl cp -n <namespace> pod-name:tmp/java_pid7.hprof java_pid7.hprof", "title": "Memory Dump"}, {"location": "janssen-server/kubernetes-ops/memory-dump/#overview", "text": "This document will demonstrate how to generate a memory dump so that you can analyze your memory usage.", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/memory-dump/#services-supported", "text": "This operation can be made in the following Java-based services: Service JAVA_OPTIONS environment variable auth-server CN_AUTH_JAVA_OPTIONS casa CN_CASA_JAVA_OPTIONS config-api CN_CONFIG_API_JAVA_OPTIONS fido2 CN_FIDO2_JAVA_OPTIONS link CN_LINK_JAVA_OPTIONS saml CN_SAML_JAVA_OPTIONS scim CN_SCIM_JAVA_OPTIONS", "title": "Services supported"}, {"location": "janssen-server/kubernetes-ops/memory-dump/#steps", "text": "Let's go through the steps needed to generate a dump in config-api : Increase the pod's memory request and limit to something larger than the default. Edit the config-api deployment and modify the JAVA_OPTIONS: env: - name: CN_CONFIG_API_JAVA_OPTIONS value: -XX:MaxDirectMemorySize=400m -Xmx150m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -XX:MaxRAMPercentage=0 Modify the command key in the deployment to add the following: command: - /bin/sh - -c - | /app/scripts/entrypoint.sh & sleep 900000000 You can view the heap usage using the following command: kubectl exec -n <namespace> pod-name -- jcmd 7 GC.heap_info Now once the process meets its limit, the process should shut down without the pod getting an OOM, allowing you to get the dump from within the pod. Copy the generated dump from the pod: kubectl cp -n <namespace> pod-name:tmp/java_pid7.hprof java_pid7.hprof", "title": "Steps"}, {"location": "janssen-server/kubernetes-ops/scaling/", "tags": ["administration", "kubernetes", "operations", "scaling"], "text": "Overview # Scaling is the ability to handle the increase in usage by expanding the existing resources(nodes/pods). Scaling types # Scaling in Kubernetes can be done automatically and manually . Automatic Scaling # Kubernetes has the capability to provision resources automatically in order to match the needed demand. Horizontal Pod Autoscaler (HPA) # HPA automatically resizes the number of pods to match demand. In order for hpa to work, you have to: Install metrics server kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml Define requests for the metric used It is configured and enabled by default in the deployed jans components. The default configuration scales in and out based on the CPU utilization of the pods. <component-name> : hpa : enabled : true minReplicas : 1 maxReplicas : 10 targetCPUUtilizationPercentage : 50 # -- metrics if targetCPUUtilizationPercentage is not set metrics : [] # -- Scaling Policies behavior : {} Cluster Autoscaler # Cluster Autoscaler automatically resizes the number of nodes in a given node pool, based on the demands of your workloads. Cluster Autoscaler is available in AWS , GCP , and Azure . Manual Scaling # Kubernetes also offers the option to manually scale your resources. For example, you can increase manually the pod replicas of auth-server deployment using the following command: kubectl scale --replicas = 3 deployment/auth-server -n <namespace>", "title": "Scaling"}, {"location": "janssen-server/kubernetes-ops/scaling/#overview", "text": "Scaling is the ability to handle the increase in usage by expanding the existing resources(nodes/pods).", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/scaling/#scaling-types", "text": "Scaling in Kubernetes can be done automatically and manually .", "title": "Scaling types"}, {"location": "janssen-server/kubernetes-ops/scaling/#automatic-scaling", "text": "Kubernetes has the capability to provision resources automatically in order to match the needed demand.", "title": "Automatic Scaling"}, {"location": "janssen-server/kubernetes-ops/scaling/#horizontal-pod-autoscaler-hpa", "text": "HPA automatically resizes the number of pods to match demand. In order for hpa to work, you have to: Install metrics server kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml Define requests for the metric used It is configured and enabled by default in the deployed jans components. The default configuration scales in and out based on the CPU utilization of the pods. <component-name> : hpa : enabled : true minReplicas : 1 maxReplicas : 10 targetCPUUtilizationPercentage : 50 # -- metrics if targetCPUUtilizationPercentage is not set metrics : [] # -- Scaling Policies behavior : {}", "title": "Horizontal Pod Autoscaler (HPA)"}, {"location": "janssen-server/kubernetes-ops/scaling/#cluster-autoscaler", "text": "Cluster Autoscaler automatically resizes the number of nodes in a given node pool, based on the demands of your workloads. Cluster Autoscaler is available in AWS , GCP , and Azure .", "title": "Cluster Autoscaler"}, {"location": "janssen-server/kubernetes-ops/scaling/#manual-scaling", "text": "Kubernetes also offers the option to manually scale your resources. For example, you can increase manually the pod replicas of auth-server deployment using the following command: kubectl scale --replicas = 3 deployment/auth-server -n <namespace>", "title": "Manual Scaling"}, {"location": "janssen-server/kubernetes-ops/start-order/", "tags": ["administration", "kubernetes", "operations", "start-order"], "text": "Service Start Order # Network traffic between Jans services # Database Access: all Jans services require access to the database. Pod-2-Pod Communication: Jans services communicate with each other as depicted. External/Internet Communication : Auth-server: should be publically accessible. Rest of the pods: We recommend to only keep the .well-known endpoints public and protect the rest.", "title": "Start Order"}, {"location": "janssen-server/kubernetes-ops/start-order/#service-start-order", "text": "", "title": "Service Start Order"}, {"location": "janssen-server/kubernetes-ops/start-order/#network-traffic-between-jans-services", "text": "Database Access: all Jans services require access to the database. Pod-2-Pod Communication: Jans services communicate with each other as depicted. External/Internet Communication : Auth-server: should be publically accessible. Rest of the pods: We recommend to only keep the .well-known endpoints public and protect the rest.", "title": "Network traffic between Jans services"}, {"location": "janssen-server/kubernetes-ops/tui-k8s/", "tags": ["administration", "kubernetes", "operations", "tui"], "text": "Overview # Using the TUI with a Janssen Kubernetes Setup - Watch Video Installing TUI and connecting to a Kubernetes installation. Download jans-cli-tui from the release assets depending on your OS. For example: wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-cli-tui-linux-ubuntu-X86-64.pyz Now we have jans-cli-tui-linux-ubuntu-X86-64.pyz downloaded. Now we can grab the FQDN, client-id, client-secret, and connect using the following commands: FQDN= #Add your FQDN here TUI_CLIENT_ID=$(kubectl get cm cn -n <namespace> --template={{.data.tui_client_id}}) TUI_CLIENT_SECRET=$(kubectl get secret cn -n <namespace> --template={{.data.tui_client_pw}} | base64 -d) #add -noverify if your FQDN is not registered python3 jans-cli-tui-linux-ubuntu-X86-64.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET", "title": "TUI K8s"}, {"location": "janssen-server/kubernetes-ops/tui-k8s/#overview", "text": "Using the TUI with a Janssen Kubernetes Setup - Watch Video Installing TUI and connecting to a Kubernetes installation. Download jans-cli-tui from the release assets depending on your OS. For example: wget https://github.com/JanssenProject/jans/releases/download/vreplace-janssen-version/jans-cli-tui-linux-ubuntu-X86-64.pyz Now we have jans-cli-tui-linux-ubuntu-X86-64.pyz downloaded. Now we can grab the FQDN, client-id, client-secret, and connect using the following commands: FQDN= #Add your FQDN here TUI_CLIENT_ID=$(kubectl get cm cn -n <namespace> --template={{.data.tui_client_id}}) TUI_CLIENT_SECRET=$(kubectl get secret cn -n <namespace> --template={{.data.tui_client_pw}} | base64 -d) #add -noverify if your FQDN is not registered python3 jans-cli-tui-linux-ubuntu-X86-64.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET", "title": "Overview"}, {"location": "janssen-server/kubernetes-ops/upgrade/", "tags": ["administration", "kubernetes", "operations", "helm", "upgrade"], "text": "This guide shows how to upgrade a Janssen helm deployment. helm ls -n <namepsace> Keep note of the helm release version Add your changes to override.yaml Apply your upgrade: helm upgrade <janssen-release-name> janssen/janssen -n <namespace> -f override.yaml --version=replace-janssen-version", "title": "Upgrade"}, {"location": "janssen-server/link/jans-keycloak-link/", "tags": ["administration", "link", "keycloak"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Jans Keycloak Link"}, {"location": "janssen-server/link/jans-keycloak-link/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/link/jans-keycloak-link/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/link/jans-keycloak-link/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/link/jans-link/", "tags": ["administration", "link", "jans-ldap-link"], "text": "Jans LDAP Link # The Jans LDAPLink synchronization service updates the Janssen User Store when authoritative data is managed in an external LDAP store. Installation # The API is available as the Jans Link component of Jans Server. Upon installation you can select if you want to install this Service along with other Janssen Server components. Post installation, to add Jans-Link component, use the following: python3 /opt/jans/jans-setup/setup.py --install-jans-link ` Jans LDAP link gets installed as a service that can be managed using below commands. To Satrt Jans-Link systemctl start jans-link To check status systemctl status jans-link To Stop Jans-Link systemctl stop jans-link Jans LDAP Link Configuration # Using Jans CLI # Janssen Server CLI provides number of operations and metadata information about Jans LDAP link. To see Jans-Link info using Jans CLI /opt/jans/jans-cli/config-cli.py --info JansLinkConfiguration To see Jans Link properties using below command. /opt/jans/jans-cli/config-cli.py --operation-id get-jans-link-properties To see basic schema of Jans-Link use below command /opt/jans/jans-cli/config-cli.py --schema \"Jans Link Plugin:AppConfiguration\" Output of above command will be similar to this: { \"inumConfig\" : { \"configId\" : \"local_inum\" , \"bindDN\" : \"cn=directory manager\" , \"bindPassword\" : \"+iChsQofo6Y=\" , \"servers\" : [ \"localhost:1636\" ], \"maxConnections\" : 10 , \"useSSL\" : true , \"baseDNs\" : [ \"ou=link,o=site\" ], \"useAnonymousBind\" : false , \"enabled\" : true , \"version\" : 0 , \"level\" : 0 }, \"targetConfig\" : { \"maxConnections\" : 2 , \"useSSL\" : false , \"useAnonymousBind\" : false , \"enabled\" : false , \"version\" : 0 , \"level\" : 0 }, \"ldapSearchSizeLimit\" : 1000 , \"keyAttributes\" : [ \"uid\" ], \"keyObjectClasses\" : [ \"gluuPerson\" ], \"sourceAttributes\" : [ \"mail\" , \"cn\" , \"sn\" ], \"updateMethod\" : \"copy\" , \"defaultInumServer\" : true , \"keepExternalPerson\" : true , \"useSearchLimit\" : false , \"attributeMapping\" : [ { \"source\" : \"uid\" , \"destination\" : \"uid\" }, { \"source\" : \"cn\" , \"destination\" : \"cn\" }, { \"source\" : \"sn\" , \"destination\" : \"sn\" } ], \"snapshotFolder\" : \"/var/jans/link-snapshots\" , \"snapshotMaxCount\" : 10 , \"baseDN\" : \"o=jans\" , \"personObjectClassTypes\" : [ \"jansCustomPerson\" , \"jansPerson\" , \"eduPerson\" ], \"personCustomObjectClass\" : \"jansCustomPerson\" , \"allowPersonModification\" : false , \"supportedUserStatus\" : [ \"active\" , \"inactive\" ], \"metricReporterInterval\" : 0 , \"metricReporterKeepDataDays\" : 0 , \"disableJdkLogger\" : true , \"cleanServiceInterval\" : 0 , \"linkEnabled\" : false , \"serverIpAddress\" : \"255.255.255.255\" , \"lastUpdate\" : \"2023-07-05T18:27:28\" , \"lastUpdateCount\" : \"0\" , \"problemCount\" : \"3\" , \"useLocalCache\" : false } Using Jans TUI # Janssen Server TUI provides ability configure Jans LDAP link component with a menu option as shown below: Section below covers Jans LDAP link configuration in more details. Configuration Using TUI # In order to configre Jans LDAP Link, the administrator needs to know various values of the backend LDAP(or Active Directory). For example, host & port , bindDN , user information, password , Objectclasses , attributes which will be pulled, etc. In addition, the administrator needs to know generic information about the Jans Server's LDAP. By default, the deployer can use localhost:1636 , cn=directory manager , password chosen during installation, ou=people,o=site as server information, bindDN , bindDN password and baseDN respectively. Let's move forward with the Jans-Link setup. Enabled : Enable your Jans-link configuration. Refresh Method : There have two refresh mode copy and VDS . If the organization has any kind of Active Directory/LDAP server, they are strongly recommended to use the Copy Method from the drop-down menu. Any organization with a database like mysql can use the VDS method. This option can be enabled via the drop-down menu in Refresh Method option. Mapping : In the source attribute to destination attribute mapping field, you can enter the source attribute value on the left, and the destination attribute on the right. In other words, you can specify what the attribute is on the backend in the left field, and what it should be rendered as when it comes through the Jans Server in the right field. Server IP address : Proviede your server IP address. Polling Interval (minutes) : This is the interval value for running the link mechanism in the Jans Server. It is recommended to be kept higher than 15 minutes. Keep External Persons : Enable it during Jans-Link setup. This will allow your default user 'admin' to log into Jans Server after initial linking iteration. If you do not enable 'Keep External Person', your 'admin' user including all other test users will be gone after first linking iteration. Snapshot Directory : Every cycle of Jans Server link cycle saves an overall snapshot and problem-list record on a specified location. This is where the Jans Server Administrator can specify the location. You can easily decide whether link synchronizes all users or not. Generally the rejected users are enclosed in the problem-list file. Snapshot Count : This defines the total number of snapshots that are allowed to be saved in the hard drive of the VM. It is recommended to be kept to 10 snapshots. Load Source Data withLimited Search Customer Backend Key Attribute Key Attributes : This is the unique key attribute of backend Active Directory/LDAP Server such as MikeAccountname for any Active Directory. Key Object Classes : This contains the Object Classes of the backend Active Directory/LDAP which has permission to talk to Jans Server link such as person, organizationalPerson, user etc. Source Attributes : This contains the list of attributes which will be pulled and read by the Jans Server. Custom LDAP Filter : If there is any custom search required, this filtering mechanism can be used such as \"sn=*\" whereas the value of this field ensures that every user must contain an attribute named SN . Source Backend LDAP Server This section allows the Jans Server to connect to the backend Active Directory/LDAP server of the organization. Add new Source LDAP Config Name : Input source as the value Bind DN : This contains the username to connect to the backend server. You need to use full DN here. As for example, cn=jans , dc=company , dc=org . Bind Password : This is your server password. Max Connections : This value defines the maximum number of connections that are allowed to read the backend Active Directory/LDAP server. It is recommended to keep the value of 2 or 3. Server:Port : provide your server name and port number. Base DNs : This contains the location of the Active Directory/LDAP tree from where the Jans Server shall read the user information. Use SSL : Use this feature if the backend server allows SSL connectivity. Enable : This check-box is used to save and push the changes. Do not use this unless the server administrator has entered all the required values. Inum DB Server This section of the application allows the server administrator to connect to the internal LDAP of the Jans Server. As Jans Server administrator, you do not need to insert anything here in this section as new Gluu Server versions automatically populates this for you (unlessyou try to manually configure it anyway). Things To Remember # The Jans Server supports two LDAP modes: Authentication Identity mapping To synchronize user accounts from an external LDAP directory server, you can use the built-in Jans CLI or Jans TUI features for Service Link, which supports mapping identities from one or more source directory servers. After configuring Jans Link, you should give it some time to run and populate the LDAP server. Here are some tips before you get started: Make sure you are using LDAP authentication Check the snapshots folder to see if files are being created. Use the Jans TUI to browse users. Use the command ldapsearch to check to see if results are starting to come in. The following command will search for the total number of users in the Jans LDAP: /opt/opendj/bin/ldapsearch -h localhost -p 1636 -Z -X -D \"cn=directory manager\" -w <pass> -b \"ou=people,o=DA....,o=jans\" dn | grep \"dn\\:\" | wc -l Try to log in with one of these users. We assume that you have also set up your Jans Server to use the correct LDAP server for authentication. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Jans LDAP Link"}, {"location": "janssen-server/link/jans-link/#jans-ldap-link", "text": "The Jans LDAPLink synchronization service updates the Janssen User Store when authoritative data is managed in an external LDAP store.", "title": "Jans LDAP Link"}, {"location": "janssen-server/link/jans-link/#installation", "text": "The API is available as the Jans Link component of Jans Server. Upon installation you can select if you want to install this Service along with other Janssen Server components. Post installation, to add Jans-Link component, use the following: python3 /opt/jans/jans-setup/setup.py --install-jans-link ` Jans LDAP link gets installed as a service that can be managed using below commands. To Satrt Jans-Link systemctl start jans-link To check status systemctl status jans-link To Stop Jans-Link systemctl stop jans-link", "title": "Installation"}, {"location": "janssen-server/link/jans-link/#jans-ldap-link-configuration", "text": "", "title": "Jans LDAP Link Configuration"}, {"location": "janssen-server/link/jans-link/#using-jans-cli", "text": "Janssen Server CLI provides number of operations and metadata information about Jans LDAP link. To see Jans-Link info using Jans CLI /opt/jans/jans-cli/config-cli.py --info JansLinkConfiguration To see Jans Link properties using below command. /opt/jans/jans-cli/config-cli.py --operation-id get-jans-link-properties To see basic schema of Jans-Link use below command /opt/jans/jans-cli/config-cli.py --schema \"Jans Link Plugin:AppConfiguration\" Output of above command will be similar to this: { \"inumConfig\" : { \"configId\" : \"local_inum\" , \"bindDN\" : \"cn=directory manager\" , \"bindPassword\" : \"+iChsQofo6Y=\" , \"servers\" : [ \"localhost:1636\" ], \"maxConnections\" : 10 , \"useSSL\" : true , \"baseDNs\" : [ \"ou=link,o=site\" ], \"useAnonymousBind\" : false , \"enabled\" : true , \"version\" : 0 , \"level\" : 0 }, \"targetConfig\" : { \"maxConnections\" : 2 , \"useSSL\" : false , \"useAnonymousBind\" : false , \"enabled\" : false , \"version\" : 0 , \"level\" : 0 }, \"ldapSearchSizeLimit\" : 1000 , \"keyAttributes\" : [ \"uid\" ], \"keyObjectClasses\" : [ \"gluuPerson\" ], \"sourceAttributes\" : [ \"mail\" , \"cn\" , \"sn\" ], \"updateMethod\" : \"copy\" , \"defaultInumServer\" : true , \"keepExternalPerson\" : true , \"useSearchLimit\" : false , \"attributeMapping\" : [ { \"source\" : \"uid\" , \"destination\" : \"uid\" }, { \"source\" : \"cn\" , \"destination\" : \"cn\" }, { \"source\" : \"sn\" , \"destination\" : \"sn\" } ], \"snapshotFolder\" : \"/var/jans/link-snapshots\" , \"snapshotMaxCount\" : 10 , \"baseDN\" : \"o=jans\" , \"personObjectClassTypes\" : [ \"jansCustomPerson\" , \"jansPerson\" , \"eduPerson\" ], \"personCustomObjectClass\" : \"jansCustomPerson\" , \"allowPersonModification\" : false , \"supportedUserStatus\" : [ \"active\" , \"inactive\" ], \"metricReporterInterval\" : 0 , \"metricReporterKeepDataDays\" : 0 , \"disableJdkLogger\" : true , \"cleanServiceInterval\" : 0 , \"linkEnabled\" : false , \"serverIpAddress\" : \"255.255.255.255\" , \"lastUpdate\" : \"2023-07-05T18:27:28\" , \"lastUpdateCount\" : \"0\" , \"problemCount\" : \"3\" , \"useLocalCache\" : false }", "title": "Using Jans CLI"}, {"location": "janssen-server/link/jans-link/#using-jans-tui", "text": "Janssen Server TUI provides ability configure Jans LDAP link component with a menu option as shown below: Section below covers Jans LDAP link configuration in more details.", "title": "Using Jans TUI"}, {"location": "janssen-server/link/jans-link/#configuration-using-tui", "text": "In order to configre Jans LDAP Link, the administrator needs to know various values of the backend LDAP(or Active Directory). For example, host & port , bindDN , user information, password , Objectclasses , attributes which will be pulled, etc. In addition, the administrator needs to know generic information about the Jans Server's LDAP. By default, the deployer can use localhost:1636 , cn=directory manager , password chosen during installation, ou=people,o=site as server information, bindDN , bindDN password and baseDN respectively. Let's move forward with the Jans-Link setup. Enabled : Enable your Jans-link configuration. Refresh Method : There have two refresh mode copy and VDS . If the organization has any kind of Active Directory/LDAP server, they are strongly recommended to use the Copy Method from the drop-down menu. Any organization with a database like mysql can use the VDS method. This option can be enabled via the drop-down menu in Refresh Method option. Mapping : In the source attribute to destination attribute mapping field, you can enter the source attribute value on the left, and the destination attribute on the right. In other words, you can specify what the attribute is on the backend in the left field, and what it should be rendered as when it comes through the Jans Server in the right field. Server IP address : Proviede your server IP address. Polling Interval (minutes) : This is the interval value for running the link mechanism in the Jans Server. It is recommended to be kept higher than 15 minutes. Keep External Persons : Enable it during Jans-Link setup. This will allow your default user 'admin' to log into Jans Server after initial linking iteration. If you do not enable 'Keep External Person', your 'admin' user including all other test users will be gone after first linking iteration. Snapshot Directory : Every cycle of Jans Server link cycle saves an overall snapshot and problem-list record on a specified location. This is where the Jans Server Administrator can specify the location. You can easily decide whether link synchronizes all users or not. Generally the rejected users are enclosed in the problem-list file. Snapshot Count : This defines the total number of snapshots that are allowed to be saved in the hard drive of the VM. It is recommended to be kept to 10 snapshots. Load Source Data withLimited Search Customer Backend Key Attribute Key Attributes : This is the unique key attribute of backend Active Directory/LDAP Server such as MikeAccountname for any Active Directory. Key Object Classes : This contains the Object Classes of the backend Active Directory/LDAP which has permission to talk to Jans Server link such as person, organizationalPerson, user etc. Source Attributes : This contains the list of attributes which will be pulled and read by the Jans Server. Custom LDAP Filter : If there is any custom search required, this filtering mechanism can be used such as \"sn=*\" whereas the value of this field ensures that every user must contain an attribute named SN . Source Backend LDAP Server This section allows the Jans Server to connect to the backend Active Directory/LDAP server of the organization. Add new Source LDAP Config Name : Input source as the value Bind DN : This contains the username to connect to the backend server. You need to use full DN here. As for example, cn=jans , dc=company , dc=org . Bind Password : This is your server password. Max Connections : This value defines the maximum number of connections that are allowed to read the backend Active Directory/LDAP server. It is recommended to keep the value of 2 or 3. Server:Port : provide your server name and port number. Base DNs : This contains the location of the Active Directory/LDAP tree from where the Jans Server shall read the user information. Use SSL : Use this feature if the backend server allows SSL connectivity. Enable : This check-box is used to save and push the changes. Do not use this unless the server administrator has entered all the required values. Inum DB Server This section of the application allows the server administrator to connect to the internal LDAP of the Jans Server. As Jans Server administrator, you do not need to insert anything here in this section as new Gluu Server versions automatically populates this for you (unlessyou try to manually configure it anyway).", "title": "Configuration Using TUI"}, {"location": "janssen-server/link/jans-link/#things-to-remember", "text": "The Jans Server supports two LDAP modes: Authentication Identity mapping To synchronize user accounts from an external LDAP directory server, you can use the built-in Jans CLI or Jans TUI features for Service Link, which supports mapping identities from one or more source directory servers. After configuring Jans Link, you should give it some time to run and populate the LDAP server. Here are some tips before you get started: Make sure you are using LDAP authentication Check the snapshots folder to see if files are being created. Use the Jans TUI to browse users. Use the command ldapsearch to check to see if results are starting to come in. The following command will search for the total number of users in the Jans LDAP: /opt/opendj/bin/ldapsearch -h localhost -p 1636 -Z -X -D \"cn=directory manager\" -w <pass> -b \"ou=people,o=DA....,o=jans\" dn | grep \"dn\\:\" | wc -l Try to log in with one of these users. We assume that you have also set up your Jans Server to use the correct LDAP server for authentication.", "title": "Things To Remember"}, {"location": "janssen-server/link/jans-link/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/lock/lock-server/", "tags": ["administration", "lock", "authorization / authz", "Cedar", "Cedarling"], "text": "Jans Lock Overview # Lock Server is a Java Weld application that connects ephemeral Cedarlings to the enterprise by providing a number of endpoints Installation # Admins can deploy Lock Server as part of Jans Auth Server or as a stanalone web server. Configuration # A list of server-level configuration properties. Logs # Lock Server creates the following logs: lock_server_config.log lock_server_audit.log -- RDBMS option lock_server_jwt_status.log CLI / TUI # Admins can manage Lock Server runtime configuration and see activity using the Jans CLI or TUI. Create/Read/Update/Delete Policy Stores Total Number of Authz requests per day View/Search current Cedarling clients by searching for username View authz activity for this Cedarling client OAuth Security # Cedarling should present an SSA during client registration. This will enable Cedarlings to obtain access tokens with scopes for OAuth protected Lock Server endpoints.", "title": "Lock Server"}, {"location": "janssen-server/lock/lock-server/#jans-lock-overview", "text": "Lock Server is a Java Weld application that connects ephemeral Cedarlings to the enterprise by providing a number of endpoints", "title": "Jans Lock Overview"}, {"location": "janssen-server/lock/lock-server/#installation", "text": "Admins can deploy Lock Server as part of Jans Auth Server or as a stanalone web server.", "title": "Installation"}, {"location": "janssen-server/lock/lock-server/#configuration", "text": "A list of server-level configuration properties.", "title": "Configuration"}, {"location": "janssen-server/lock/lock-server/#logs", "text": "Lock Server creates the following logs: lock_server_config.log lock_server_audit.log -- RDBMS option lock_server_jwt_status.log", "title": "Logs"}, {"location": "janssen-server/lock/lock-server/#cli-tui", "text": "Admins can manage Lock Server runtime configuration and see activity using the Jans CLI or TUI. Create/Read/Update/Delete Policy Stores Total Number of Authz requests per day View/Search current Cedarling clients by searching for username View authz activity for this Cedarling client", "title": "CLI / TUI"}, {"location": "janssen-server/lock/lock-server/#oauth-security", "text": "Cedarling should present an SSA during client registration. This will enable Cedarlings to obtain access tokens with scopes for OAuth protected Lock Server endpoints.", "title": "OAuth Security"}, {"location": "janssen-server/planning/application-portal/", "tags": ["administration", "planning", "portal"], "text": "An application portal (\"portal\") is a website that displays all the protected applications available for an end user to access. The Janssen Project does not provide a portal. But you can build your own. Each application that you want in your portal should be configured as an OpenID Connect RP. Build a simple website (any CMS will do) that is also an RP. The OP can provide the roles of the user, or another claim, which will enable your portal to determine which websites to display. Iterate and display the websites (or icons) with the respective URLs.", "title": "Application Portal"}, {"location": "janssen-server/planning/benchmarking/", "tags": ["administration", "planning", "benchmarking"], "text": "Want confidence that your Janssen platform will perform with the latency and concurrency you need in production? If so, then you MUST benchmark properly. It's critical that your test data and transactions mock what you need to prove in production. For cloud-native deployments, benchmarking is also essential to test auto-scaling and failover. Ideally, you'll test the same hardware and network. Remember that OAuth has different flows, which have a different number of steps, and different requirements for compute and persistence. For example, the OAuth Client Credential Grant is very short: there is one token request and one token response. The OpenID Code Flow has many more steps: it has a request/response to the authorization, token, Userinfo and logout endpoints. It's really important to test the exact flow you intend to use in production. Benchmarking also has the benefit of testing the index configuration in your database. Every database trades disk space for performance by using indexes. If you miss an index, performance sometimes comes to a grinding halt. Your service may even crash. Having confidence that all potential index scenarios get executed in your benchmarking is essential. Auth Server publishes JUnit tests and some tools for generating test data. Because each page rendered by Auth Server has a state, you cannot use a static load generation page tool. Don't forget to gather data on compute, storage, and memory. Also, watch the resources consumed by each web service and system service (e.g. database). You can't find the bottleneck without this data. System libraries and hardware choices may also impact your results. Benchmarking is an iterative process. Inevitably, things never go exactly how you guessed they would. And you make changes to your environment and run the benchmarking tests again-- ad nauseam . Leave enough time for benchmarking. However much time you think it will take, triple your estimate. Make sure you look at both short tests and long running tests. A slow memory leak may only present after many hours of high load. Also, run some crazy tests, just so you know what happens. Some organizations benchmark for ten times the normal volume. But when an incident happens, they see 1,000 times the normal volume. Think outside-the-box. It's tricky load testing some newer two-factor authentication services, especially if they rely on new features of the browser. Hopefully the tools to benchmark these will evolve. Janssen Auth Server supports a number of deployment models--both VM and cloud-native. While cloud-native architecture enables true horizontal scalability, it comes at a cost. Benchmarking can help you understand if that cost is justified. Load test # In cloud-native architecture, the load testing is executed via k8s pods. Authorization Code Flow jmeter load test # For load testing with Authorization Code Flow jmeter test, the following script is used. See Authorization code flow recipe for details. Resource Owner Password Grant (ROPC) Flow jmeter load test # For load testing with Resource Owner Password Grant (ROPC) Flow jmeter test, the following script is used. See ROPC flow recipe for details.", "title": "Benchmarking"}, {"location": "janssen-server/planning/benchmarking/#load-test", "text": "In cloud-native architecture, the load testing is executed via k8s pods.", "title": "Load test"}, {"location": "janssen-server/planning/benchmarking/#authorization-code-flow-jmeter-load-test", "text": "For load testing with Authorization Code Flow jmeter test, the following script is used. See Authorization code flow recipe for details.", "title": "Authorization Code Flow jmeter load test"}, {"location": "janssen-server/planning/benchmarking/#resource-owner-password-grant-ropc-flow-jmeter-load-test", "text": "For load testing with Resource Owner Password Grant (ROPC) Flow jmeter test, the following script is used. See ROPC flow recipe for details.", "title": "Resource Owner Password Grant (ROPC) Flow jmeter load test"}, {"location": "janssen-server/planning/caching/", "tags": ["administration", "planning", "caching", "Redis", "Memcached"], "text": "There are two reasons to use caching. First, to improve performance by reducing the number of writes to the disk. Second, to share session data in a clustered deployment. Janssen supports a few different options for caching, as controlled by the cacheProviderType . Also keep in mind that unless the sessionIdPersistInCache is set to True , Auth Server will store sessions in the database. In-Memory If you only have one server, you can use RAM as the cache. Watch the memory usage of Auth Server--if it gets too high you may want to switch to another cache mechanism. Database A \"database cache\" is an oxymoron. But in cases where you don't want another component or service, but you need the session replication for a cluster, it may be convenient to persist the \"cache\" data in the database. Redis The best choice if you need a cache service for RDBMS, or Spanner. Great performance and low cache miss rate. Commercial Redis supports TLS, which is a good option if you need secure communication. Memcached Still a good choice, especially if that's what you already run for other applications. We have observed a slightly higher cache miss rate under high load, which is fairly atypical for most login applications. Cloud Cache Amazon ElastiCache or Google Memorystore offers both Redis and Memcached managed services. They work fine.", "title": "Caching"}, {"location": "janssen-server/planning/central-auth-service/", "tags": ["administration", "planning", "integration"], "text": "Older monolithic web access management platforms from the 2000s had features to allow central policy management--what users can access what resources. But modern federated digital identity platforms generally do not. That's true for two reasons. First implementing all the OAuth and OpenID features is already a wide swath of requirements. Second, policy management, or authorization, has itself become a nice market. Note the policy management platforms list in the RBAC planning guide page. With that said, if the number of policies is low, there are some ways to use Jans Auth Server as a central policy decision point. You could use the presence of OAuth scopes to signal to the policy enforcement point the extent of access. In this case, policies could be implemented as code in the Update Token interception script. A similar strategy is to use UMA access tokens (\"RPT tokens\"), in which case you would use either the RPT interception script or the claims gathering interception script to implement your policies (or a combination of both). But this approach should be used with caution. Most of the policy management tools today use a declarative language for policies. Maintaining policies in code does not scale as well.", "title": "Central Authorization Service Integration"}, {"location": "janssen-server/planning/certificates-keys/", "tags": ["administration", "planning", "certificates", "keys", "cryptography", "JCE", "HSM", "FIPS"], "text": "JSON Signing and Encryption # Janssen uses keys for signing and encryption, primarily concerning JSON documents. There are six IETF RFCs that provide considerable detail: RFC 7515 JSON Web Signing (JWS) RFC 7516 JSON Web Encryption (JWE) RFC 7517 JSON Web Key (JWK) RFC 7518 JSON Web Algorithms (JWA) RFC 7519 JSON Web Signing (JWT) RFC 7520 Examples of Protecting Content Using JSON Object Signing and Encryption (JOSE) Auth Server Supported Signing # JWT Type Algorithms DPOP RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Authorization HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, ES512, PS256, PS384, PS512 Request Object HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Userinfo HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Token Endpoint Auth HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 ID Token HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Auth Server Supported Encryption # Encryption Methods Algorithms Authorization A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM id_token A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Request object A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Userinfo A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Encryption Algorithms Algorithms Userinfo RSA1_5, RSA-OAEP, A128KW, A256KW id_token RSA1_5, RSA-OAEP, A128KW, A256KW authorization RSA1_5, RSA-OAEP, A128KW, A256KW request object RSA1_5, RSA-OAEP, A128KW, A256KW Java Cryptographic Engine (JCE) # Janssen projects ships and tests with the Bouncy Castle Crypto API's JCE. However, you may substitute your own JCE as long as it has implementations for the algorithms used by Auth Server. Key Rotation # OpenID Connect clients must support the rotation of both signing and encryption keys. The best practice is to rotate often--the default configuration in a VM installation of Auth Server is every two days . The reason for such a frequent rotation is to make sure developer account for rotation at the time they create applications--lest they forget and their software breaks a year later when rotation happens. In a single VM deployment, key rotation is controlled by Auth Server. But in a clustered deployment, key rotation has to happen centrally. Janssen includes a key rotation service for cloud deployments. Certificates # X.509 is used extensively for web server TLS. But it is also used for Mutual Transport Layer Security (MTLS), either initiated by a software client, or presented by a person (i.e. a personal certificate). MTLS is generally implemented in the web tier. FIPS # To support FIPS 140-2 conformance, you must use a FIPS approved JCE, and preferably, use an operating system that has FIPS Enforcement, like RHEL 8 .", "title": "Certificates/Keys"}, {"location": "janssen-server/planning/certificates-keys/#json-signing-and-encryption", "text": "Janssen uses keys for signing and encryption, primarily concerning JSON documents. There are six IETF RFCs that provide considerable detail: RFC 7515 JSON Web Signing (JWS) RFC 7516 JSON Web Encryption (JWE) RFC 7517 JSON Web Key (JWK) RFC 7518 JSON Web Algorithms (JWA) RFC 7519 JSON Web Signing (JWT) RFC 7520 Examples of Protecting Content Using JSON Object Signing and Encryption (JOSE)", "title": "JSON Signing and Encryption"}, {"location": "janssen-server/planning/certificates-keys/#auth-server-supported-signing", "text": "JWT Type Algorithms DPOP RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Authorization HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, ES512, PS256, PS384, PS512 Request Object HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Userinfo HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 Token Endpoint Auth HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512 ID Token HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512", "title": "Auth Server Supported Signing"}, {"location": "janssen-server/planning/certificates-keys/#auth-server-supported-encryption", "text": "Encryption Methods Algorithms Authorization A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM id_token A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Request object A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Userinfo A128CBC+HS256, A256CBC+HS512, A128GCM, A256GCM Encryption Algorithms Algorithms Userinfo RSA1_5, RSA-OAEP, A128KW, A256KW id_token RSA1_5, RSA-OAEP, A128KW, A256KW authorization RSA1_5, RSA-OAEP, A128KW, A256KW request object RSA1_5, RSA-OAEP, A128KW, A256KW", "title": "Auth Server Supported Encryption"}, {"location": "janssen-server/planning/certificates-keys/#java-cryptographic-engine-jce", "text": "Janssen projects ships and tests with the Bouncy Castle Crypto API's JCE. However, you may substitute your own JCE as long as it has implementations for the algorithms used by Auth Server.", "title": "Java Cryptographic Engine (JCE)"}, {"location": "janssen-server/planning/certificates-keys/#key-rotation", "text": "OpenID Connect clients must support the rotation of both signing and encryption keys. The best practice is to rotate often--the default configuration in a VM installation of Auth Server is every two days . The reason for such a frequent rotation is to make sure developer account for rotation at the time they create applications--lest they forget and their software breaks a year later when rotation happens. In a single VM deployment, key rotation is controlled by Auth Server. But in a clustered deployment, key rotation has to happen centrally. Janssen includes a key rotation service for cloud deployments.", "title": "Key Rotation"}, {"location": "janssen-server/planning/certificates-keys/#certificates", "text": "X.509 is used extensively for web server TLS. But it is also used for Mutual Transport Layer Security (MTLS), either initiated by a software client, or presented by a person (i.e. a personal certificate). MTLS is generally implemented in the web tier.", "title": "Certificates"}, {"location": "janssen-server/planning/certificates-keys/#fips", "text": "To support FIPS 140-2 conformance, you must use a FIPS approved JCE, and preferably, use an operating system that has FIPS Enforcement, like RHEL 8 .", "title": "FIPS"}, {"location": "janssen-server/planning/components/", "tags": ["administration", "planning", "components", "architecture"], "text": "This page has a brief description of the major components of a Janssen deployment. Auth Server : This component is the OAuth Authorization Server, the OpenID Connect Provider, and the UMA Authorization Server--this is the main Internet-facing component of Janssen. It's the service that returns tokens, JWTs, and identity assertions. This service must be Internet-facing. Database : Like most IAM platforms, Janssen requires some kind of persistence service to store configuration and other entity data (client, person, scope, attribute, FIDO device, etc.) As different databases are good for different deployments, Janssen supports MySQL and Postgres. Cache : Getting data from a disk is still the slowest part of any web platform. If you want higher transaction speeds, one strategy is to use a memory cache instead of the disk (i.e. database). Janssen was designed to store short-lived objects in the cache, like the code in the OpenID code flow (which is only used one time) or access tokens, which only live for a few minutes. Currently, Janssen has three options for cache: in-memory , which is suitable only for one node VM deployments; redis which is probably your best option; and memcached which you should use if a Redis cache service is not available (and tends to have more cache misses under high volume). Key Management Janssen does a lot of cryptographic signing and encryption. Where you store the private keys has an impact on the security of your Janssen platform. For cloud deployments, many providers are providing key storage as a service. You could also use the file system or an HSM. FIDO2 : This component provides the server side endpoints to enroll and validate devices that use FIDO. It provides both FIDO U2F (register, authenticate) and FIDO 2 (attestation, assertion) endpoints. This service must be internet facing. Config API : The API to configure the auth-server and other components is consolidated in this component. This service should not be Internet-facing. SCIM : SCIM is JSON/REST API to manage user data. Use it to add, edit and update user information. This service should not be Internet facing. CLI : While you can use curl to call the Config API, CLI is a command line tool that provides a simple single line options for configuration. In the background, it is just calling the Config API. To authenticate, you'll use the OAuth Device flow. The CLI need not be on the same server as any of the components (you can run it from your desktop). But you will need network connectivity to the Config API and the Auth Server. TUI : A menu-driven interactive tool for configuration, the \"TUI\" or \"text user interface\" might resemble a 90's BIOS configuration, but it gets the job done without the need for a web browser. Like the CLI, you can run it from anywhere, but need connectivity to the Config API and Auth Server. The TUI writes a \"CLI log\"--the one-liner you could have executed to do whatever you just did in the interface. This will help you if you want to script stuff later on. Jans Core : This library has code that is shared across several Janssen projects. You will most likely need this project when you build other Janssen components. Jans ORM : This is the library for persistence and caching implementations in Janssen. Currently,only RDBMS is supported. Agama : The Agama module offers an alternative way to build authentication flows in Janssen Server. With Agama, flows are coded in a DSL (domain specific language) designed for the sole purpose of writing web flows. Setup : Configuring a Janssen Auth Server platform is complicated. How do you generate the keys and certificates? How do you generate the minimal data set to start your system? The setup component helps you bootstrap a minimal system.", "title": "Components"}, {"location": "janssen-server/planning/customization/", "tags": ["administration", "planning", "localization", "international", "language"], "text": "Customization and Localization # You can customize just about everything in the Janssen Platform. That's pretty much the point of running your own identity platform. This includes the look and feel of the web pages, the language of the user-facing content, the behavior of endpoints, error messages, and more. Behavior of endpoints # Almost every endpoint has an interception script, which enables you to implement custom business logic. For a more general discussion of the extensibility of the Janssen platform, see the Developer Guide . Web content # There are several front channel flows in Auth Server (front channel = web browser): OpenID User Authentication OpenID Consent Post-Authentication UMA Claims Gathering Each of these scripts contains a method which is similar to getPageForStep which fetches the respective Facelets xhtml file for that step. Facelets is very friendly to designers, as it's possible to mix content such as regular HTML with JSF components. Thus Facelets pages can have both static and dynamic content and leverage all your \"normal\" web design tools like CSS and JavaScript. Facelets also support templates. Each .xhtml page has access to the authentication context, and you can insert data from the respective interception script. Also, each .xhtml page is unique and has a built-in state identifier, preventing Auth Server from responding to any page which it did not render. For more information, see the Developer Guide . Note, in the getPageForStep method, you can have a conditional statement to return different pages based either on the detected or requested language of the subject. Error messages # You can change the descriptions for the various front-channel Auth Server error messages, for example, what would Auth Server return for a bad request to the Authorization Endpoint. Of course, you can also customize the web server error messages, like 404, by configuring your web server. Auth Server should never return a stackTrace. Localization for OpenID Connect client metadata # Because client information may be displayed via the OpenID protocol, language support is needed at the client level. For example, the client name, description, terms of service URI, or logo may differ based on the end user's language. Section 2.1 of OpenID Connect Client Registration, Metadata Languages and Scripts states: Human-readable Client Metadata values and Client Metadata values that reference human-readable values MAY be represented in multiple languages and scripts. For example, values such as client_name, tos_uri, policy_uri, logo_uri, and client_uri might have multiple locale-specific values in some Client registrations. To specify the languages and scripts, BCP47 language tags are added to Client Metadata member names, delimited by a # character. For example, the value for tos_uri#ja-Hani-JP would direct the subject to the terms of service agreement in Japanese. Janssen does not yet support languages syntax for OpenID user claims, as described in OpenID Core Section 5.2, Claims Languages and Scripts .", "title": "Customization/Localization"}, {"location": "janssen-server/planning/customization/#customization-and-localization", "text": "You can customize just about everything in the Janssen Platform. That's pretty much the point of running your own identity platform. This includes the look and feel of the web pages, the language of the user-facing content, the behavior of endpoints, error messages, and more.", "title": "Customization and Localization"}, {"location": "janssen-server/planning/customization/#behavior-of-endpoints", "text": "Almost every endpoint has an interception script, which enables you to implement custom business logic. For a more general discussion of the extensibility of the Janssen platform, see the Developer Guide .", "title": "Behavior of endpoints"}, {"location": "janssen-server/planning/customization/#web-content", "text": "There are several front channel flows in Auth Server (front channel = web browser): OpenID User Authentication OpenID Consent Post-Authentication UMA Claims Gathering Each of these scripts contains a method which is similar to getPageForStep which fetches the respective Facelets xhtml file for that step. Facelets is very friendly to designers, as it's possible to mix content such as regular HTML with JSF components. Thus Facelets pages can have both static and dynamic content and leverage all your \"normal\" web design tools like CSS and JavaScript. Facelets also support templates. Each .xhtml page has access to the authentication context, and you can insert data from the respective interception script. Also, each .xhtml page is unique and has a built-in state identifier, preventing Auth Server from responding to any page which it did not render. For more information, see the Developer Guide . Note, in the getPageForStep method, you can have a conditional statement to return different pages based either on the detected or requested language of the subject.", "title": "Web content"}, {"location": "janssen-server/planning/customization/#error-messages", "text": "You can change the descriptions for the various front-channel Auth Server error messages, for example, what would Auth Server return for a bad request to the Authorization Endpoint. Of course, you can also customize the web server error messages, like 404, by configuring your web server. Auth Server should never return a stackTrace.", "title": "Error messages"}, {"location": "janssen-server/planning/customization/#localization-for-openid-connect-client-metadata", "text": "Because client information may be displayed via the OpenID protocol, language support is needed at the client level. For example, the client name, description, terms of service URI, or logo may differ based on the end user's language. Section 2.1 of OpenID Connect Client Registration, Metadata Languages and Scripts states: Human-readable Client Metadata values and Client Metadata values that reference human-readable values MAY be represented in multiple languages and scripts. For example, values such as client_name, tos_uri, policy_uri, logo_uri, and client_uri might have multiple locale-specific values in some Client registrations. To specify the languages and scripts, BCP47 language tags are added to Client Metadata member names, delimited by a # character. For example, the value for tos_uri#ja-Hani-JP would direct the subject to the terms of service agreement in Japanese. Janssen does not yet support languages syntax for OpenID user claims, as described in OpenID Core Section 5.2, Claims Languages and Scripts .", "title": "Localization for OpenID Connect client metadata"}, {"location": "janssen-server/planning/delegated-user-admin/", "tags": ["administration", "planning"], "text": "Delegated user administration is normally implemented via a website where a privileged user can search / add / edit / delete people in their organization. You will not be surprised to hear that this is an identity management use case that Janssen Auth Server does not provide out of the box. But if you wanted to build a website that performed this function, you could use the SCIM protocol to do so. In your application, you could read the user claims to find out the organization, role, or other information about the person managing data. Then your web application could use this information to make filters when making SCIM calls. Or another handy trick is to put the person's role information in an OAuth access token (using the Update Token script), and then use the SCIM interception script to add the respective filters.", "title": "Delegated User Administration"}, {"location": "janssen-server/planning/discovery/", "tags": ["administration", "planning", "discovery"], "text": "In a federated identity topology, you can authenticate a person by redirecting their browser to the correct IDP. But what happens when there is more then one IDP? Before the person authenticates, how do you know to which IDP to send them? This challenge is called \"discovery\", \"where are you from\", or \"WAYF\". There are a few ways to handle discovery. Here are a few: Display a list of logos and enable the end user to pick the IDP. If you ever clicked on a social login button, you've experienced this approach. Use a different URL for each IDP, like https://customer1.saas.com or https://saas.com/customer2 . Based on which URL the person hits, you know where to send them. Prompt the person to enter something identifying, like their email address. You can use this to look up their home IDP. Use contextual information, like network address, geolocation, or browser data. Once you've figured out the person behind the browser, it may make sense to write a cookie so next time, you don't have to bother them. While it's possible to implement a discovery workflow using an Agama script or an Auth Server person authentication interception script, you also write a simple web application, and then redirect to the authorization endpoint with a hint as an extra parameter and a specific acr_values .", "title": "Discovery"}, {"location": "janssen-server/planning/dns/", "tags": ["administration", "planning", "DNS", "hostname", "TLS", "X.509"], "text": "Trust in the Internet is largely derived from TLS. Like it or not, we are highly reliant on making a secure connection from a web browser using X.509 security to ensure that we are connecting to a trusted web server. The cn of that web server certificate is the hostname of the server. There is no guarantee that a two distinct trusted root CA's have not issued duplicate certificates for the same hostname. Thus, if your DNS server is hacked, bad things may ensue. This is not a hypothetical risk. Actual attacks have been implemented by adding entries to a DNS server that look real, but point to the attacker's website. DNS attacks are very difficult for the end-user to detect. For example, https://account.acme.com v. https://accounts.acme.com --both would look ok to a typical end user. So rule number one: PROTECT DNS--the whole integrity of your identity platform is otherwise vulnerable. From a deployment perspective, remember that in most cases the hostname of your IDP points to the HTTP load balancer (unless you have a single VM deployment). In most cases, you will also terminate TLS in the load balancer. The DNS hostname is baked into the protocols. For example, the authorization endpoint may look like this: \"authorization_endpoint\" : \"https://account.acme.com/jans-auth/restv1/authorize\" Note that the hostname is built into the protocol, not just the Web TLS layer. If you were to change the hostname of your web server, your deployment would break, because you would have to update all the configuration data in the IDP that contains the hostname too. And you'd have to regenerate any X.509 certificates. For this reason, you should think carefully about the hostname before you run setup and create the base installation of your Janssen Platform. To change the hostname, we recommend you re-install. If you want to promote your configuration from development to production, you may also need to consider keeping the hostname the same--although be careful you don't hit production by mistake in your testing.", "title": "DNS"}, {"location": "janssen-server/planning/identity-access-governance/", "tags": ["administration", "planning", "IAG", "Identity Governance"], "text": "Janssen is not a governance platform, so it does not do any of the following: Role Management # Role Based Access Control (RBAC) is a strategy used by many organizations to authorize access to resources. However, RBAC has a dark side: if roles are used to reference each unique access requirement the number of roles can grow exponentially. In fact, some organizations have more roles than people! This is known as \"role explosion.\" Role Management is an enterprise workforce governance practice which correlates roles across all applications to reduce their number to the lowest common denominator of \"enterprise roles\". Access Certification # The role request and approval processes tend to result in a person accumulating many roles over time. However, because removal of roles no-longer-needed is often overlooked, it's important for organizations to regularly perform access certification campaigns (i.e. \"recertification\" or \"attestation\"). For example, once per year, managers may need to decide if the roles assigned to subordinate employees are still needed. Removal of a non-sensitive role is not an urgent matter. However, certain situations might require faster action, for example if an employee is moved to a different organizational unit with a different manager. The new manager assumes responsibility for the employee's roles, and should execute an ad-hoc recertification process for that specific user. Segregation of Duties # Sometimes an organization should prevent a person from having two roles simultaneously. For example, there could be an account rule that a person can't both sign and approve checks. Or a person can't perform both financial advisory and equity trading. The governance platform may enable organizations to define these Segregation of Duties to prevent such conflicts of interest.", "title": "Identity Access Governance"}, {"location": "janssen-server/planning/identity-access-governance/#role-management", "text": "Role Based Access Control (RBAC) is a strategy used by many organizations to authorize access to resources. However, RBAC has a dark side: if roles are used to reference each unique access requirement the number of roles can grow exponentially. In fact, some organizations have more roles than people! This is known as \"role explosion.\" Role Management is an enterprise workforce governance practice which correlates roles across all applications to reduce their number to the lowest common denominator of \"enterprise roles\".", "title": "Role Management"}, {"location": "janssen-server/planning/identity-access-governance/#access-certification", "text": "The role request and approval processes tend to result in a person accumulating many roles over time. However, because removal of roles no-longer-needed is often overlooked, it's important for organizations to regularly perform access certification campaigns (i.e. \"recertification\" or \"attestation\"). For example, once per year, managers may need to decide if the roles assigned to subordinate employees are still needed. Removal of a non-sensitive role is not an urgent matter. However, certain situations might require faster action, for example if an employee is moved to a different organizational unit with a different manager. The new manager assumes responsibility for the employee's roles, and should execute an ad-hoc recertification process for that specific user.", "title": "Access Certification"}, {"location": "janssen-server/planning/identity-access-governance/#segregation-of-duties", "text": "Sometimes an organization should prevent a person from having two roles simultaneously. For example, there could be an account rule that a person can't both sign and approve checks. Or a person can't perform both financial advisory and equity trading. The governance platform may enable organizations to define these Segregation of Duties to prevent such conflicts of interest.", "title": "Segregation of Duties"}, {"location": "janssen-server/planning/identity-management/", "tags": ["administration", "planning", "IDM", "Identity Management", "SCIM"], "text": "Identity Management # In Janssen docs, the term Identity Management or \"IDM\" is the process of adding, editing and deleting data in various domain systems. Ideally, identity data would exist in only one place. But this ideal is currently undesirable. For performance, data joins, auditing, and many other reasons (for the foreseeable future) identity data is sprinkled across many systems. So when we update identity data, how do we keep all our infrastructure up-to-date? This task has been the realm of IDM platforms, which enable organizations to define workflows to update identity information, and through the use of \"connectors\", to push this data to all disparate databases. IDM platforms range in size and complexity. An admin could write a Python script to automate adding new users to a domain. Large enterprises may implement a commercial IDM platform, like Sailpoint or an open-source IDM platform like Evolveum Midpoint . Or you might have a human IDM--\"Hey Bob, we hired a new person. Can you add her?\" The Janssen platform does not include an IDM component. Fundamentally, Janssen is a consumer of identity data. One of the most common ways for identity data to make its way to the Janssen database is via the SCIM interface. This is an API that has a /users endpoint, to which an IDM system can send updates. For example, the IDM system may POST to the /users endpoint to add a new user to the Janssen database, or DELETE to the /users endpoint to remove a user. With that said, sometimes organizations might encode IDM business logic in the Janssen platform. This is particularly true for consumer-facing applications. In general, it only works for relatively simple requirements, particularly when the Janssen platform is the authoritative source of identity data. Using the various interception scripts, it's possible to send identity data from the Janssen platform to external systems. For example, let's say an organization has only two silos of identity data: Jans Auth Server and a MongoDB database record. In a case like this, when a person registers through a Person Authn Interception Script or Agama flow, you could call an API which updates the MongoDB database. It's also possible to implement approval workflows using UMA. For example, an API might require an UMA access token (i.e. an RPT token), and obtaining this token may require the consent of two different individuals. But it is worth remembering that the Janssen Platform was not purpose-built for IDM, and therefore any implementation for such use cases should be tactical. You may have to build many features yourself. Especially for enterprise workforce applications, you should seriously consider using off-the-shelf software before writing too much code in Janssen.", "title": "Identity Management"}, {"location": "janssen-server/planning/identity-management/#identity-management", "text": "In Janssen docs, the term Identity Management or \"IDM\" is the process of adding, editing and deleting data in various domain systems. Ideally, identity data would exist in only one place. But this ideal is currently undesirable. For performance, data joins, auditing, and many other reasons (for the foreseeable future) identity data is sprinkled across many systems. So when we update identity data, how do we keep all our infrastructure up-to-date? This task has been the realm of IDM platforms, which enable organizations to define workflows to update identity information, and through the use of \"connectors\", to push this data to all disparate databases. IDM platforms range in size and complexity. An admin could write a Python script to automate adding new users to a domain. Large enterprises may implement a commercial IDM platform, like Sailpoint or an open-source IDM platform like Evolveum Midpoint . Or you might have a human IDM--\"Hey Bob, we hired a new person. Can you add her?\" The Janssen platform does not include an IDM component. Fundamentally, Janssen is a consumer of identity data. One of the most common ways for identity data to make its way to the Janssen database is via the SCIM interface. This is an API that has a /users endpoint, to which an IDM system can send updates. For example, the IDM system may POST to the /users endpoint to add a new user to the Janssen database, or DELETE to the /users endpoint to remove a user. With that said, sometimes organizations might encode IDM business logic in the Janssen platform. This is particularly true for consumer-facing applications. In general, it only works for relatively simple requirements, particularly when the Janssen platform is the authoritative source of identity data. Using the various interception scripts, it's possible to send identity data from the Janssen platform to external systems. For example, let's say an organization has only two silos of identity data: Jans Auth Server and a MongoDB database record. In a case like this, when a person registers through a Person Authn Interception Script or Agama flow, you could call an API which updates the MongoDB database. It's also possible to implement approval workflows using UMA. For example, an API might require an UMA access token (i.e. an RPT token), and obtaining this token may require the consent of two different individuals. But it is worth remembering that the Janssen Platform was not purpose-built for IDM, and therefore any implementation for such use cases should be tactical. You may have to build many features yourself. Especially for enterprise workforce applications, you should seriously consider using off-the-shelf software before writing too much code in Janssen.", "title": "Identity Management"}, {"location": "janssen-server/planning/kubernetes/", "tags": ["administration", "planning", "kubernetes"], "text": "Overview # This planning guide helps you learn about when to use Jans with Kubernetes, why to use it, an overview of best practices around it, platforms supported and important tools that can help ease the operations. The When and Why? # Whether to use Kubernetes , VM or a cluster of VMs depends on answering several key questions some of which are: What's the size of my organization/customer serving base? # Answering this question gives the load of authentications per second expected which determines if you are in the threshold of operating a VM for Jans. Anything past 50 auths per second points to a cluster setup which is curerntly Kuberentes. We do plan to support more cloud-native setups soon. Can my organization handle min-hrs of downtime? # This ties to question 1 but even with the best operational automation VM setups restoring/patching a VM will result in downtime. Does my organization function in different regions? # If your organization works in several regions a VM setup is almost immediately ruled out. Does my organization expect to double in growth each year? or possibly faster? # If your organization or your customer base is growing fast rule out a VM setup. Is this an on-premise vs hybrid vs cloud deployment? # This question weighs on the current infrastructure of your organization. Operating on-premise Kubernetes setups needs generally more technical resources than operating a cloud setup. Comparing that to a VM setup, operating a VM setup is much easier in on-premise setups. The more the momentum of your org pulls to cloud vs onpremise the more it pulls to Kuberetnes vs a VM setup respectively. What's my organizations technical expertise level on Kubernetes vs VMs? # This determines the amount of investment needed to overcome the learning curve to operate a Kubernetes cluster. If your Kubernetes technical resources are low and the above questions point to a VM setup you should think about going with a vm setup. If you got conflicting answers above, for example if the customer size dedicated that you should operate a Kubernetes cluster you need to invest in your technical staff. If you are on the borderline invest in your Kubernetes technical staff while operating a vm setup and prepare to move in the near future. Does the deployment need to be highly available(HA)? # We recommend using Kubernetes-based CN deployments for situations where high availability is a critical factor. Though VM cluster can provide high availability, we do not recommend the HA setup with VMs. Primarily because effort required to upgrade multiple servers and configuring them is much more as compared to a cloud native deployment and it is error-prone. We recommend you follow the CN setup for HA as you will get automatic upgrades, patches with a single helm upgrade command. In general the Kubernetes deployment offers an easy deployment strategy with a helm chart and an easy upgrade path but taking the above into account is very important. The Supported Clouds # We support several clouds managed Kubernetes solutions but that doesn't mean our setup will not work with other managed Kubernetes solutions. In fact, our Kubernetes setup is expected to work across almost all managed solutions however those not listed below were not tested. AWS GCP Azure DOKS Local/Hybrid # Rancher # Rancher UI can be deployed to several clouds / multi-clouds and also be used to manage local setups. Important tools and tech to consider # Helm Terraform Prometheus and Grafana Pipeline tech such as Jenkins, Ansible, Cloud Build ..etc", "title": "Kubernetes"}, {"location": "janssen-server/planning/kubernetes/#overview", "text": "This planning guide helps you learn about when to use Jans with Kubernetes, why to use it, an overview of best practices around it, platforms supported and important tools that can help ease the operations.", "title": "Overview"}, {"location": "janssen-server/planning/kubernetes/#the-when-and-why", "text": "Whether to use Kubernetes , VM or a cluster of VMs depends on answering several key questions some of which are:", "title": "The When and Why?"}, {"location": "janssen-server/planning/kubernetes/#whats-the-size-of-my-organizationcustomer-serving-base", "text": "Answering this question gives the load of authentications per second expected which determines if you are in the threshold of operating a VM for Jans. Anything past 50 auths per second points to a cluster setup which is curerntly Kuberentes. We do plan to support more cloud-native setups soon.", "title": "What's the size of my organization/customer serving base?"}, {"location": "janssen-server/planning/kubernetes/#can-my-organization-handle-min-hrs-of-downtime", "text": "This ties to question 1 but even with the best operational automation VM setups restoring/patching a VM will result in downtime.", "title": "Can my organization handle min-hrs of downtime?"}, {"location": "janssen-server/planning/kubernetes/#does-my-organization-function-in-different-regions", "text": "If your organization works in several regions a VM setup is almost immediately ruled out.", "title": "Does my organization function in different regions?"}, {"location": "janssen-server/planning/kubernetes/#does-my-organization-expect-to-double-in-growth-each-year-or-possibly-faster", "text": "If your organization or your customer base is growing fast rule out a VM setup.", "title": "Does my organization expect to double in growth each year? or possibly faster?"}, {"location": "janssen-server/planning/kubernetes/#is-this-an-on-premise-vs-hybrid-vs-cloud-deployment", "text": "This question weighs on the current infrastructure of your organization. Operating on-premise Kubernetes setups needs generally more technical resources than operating a cloud setup. Comparing that to a VM setup, operating a VM setup is much easier in on-premise setups. The more the momentum of your org pulls to cloud vs onpremise the more it pulls to Kuberetnes vs a VM setup respectively.", "title": "Is this an on-premise vs hybrid vs cloud deployment?"}, {"location": "janssen-server/planning/kubernetes/#whats-my-organizations-technical-expertise-level-on-kubernetes-vs-vms", "text": "This determines the amount of investment needed to overcome the learning curve to operate a Kubernetes cluster. If your Kubernetes technical resources are low and the above questions point to a VM setup you should think about going with a vm setup. If you got conflicting answers above, for example if the customer size dedicated that you should operate a Kubernetes cluster you need to invest in your technical staff. If you are on the borderline invest in your Kubernetes technical staff while operating a vm setup and prepare to move in the near future.", "title": "What's my organizations technical expertise level on Kubernetes vs VMs?"}, {"location": "janssen-server/planning/kubernetes/#does-the-deployment-need-to-be-highly-availableha", "text": "We recommend using Kubernetes-based CN deployments for situations where high availability is a critical factor. Though VM cluster can provide high availability, we do not recommend the HA setup with VMs. Primarily because effort required to upgrade multiple servers and configuring them is much more as compared to a cloud native deployment and it is error-prone. We recommend you follow the CN setup for HA as you will get automatic upgrades, patches with a single helm upgrade command. In general the Kubernetes deployment offers an easy deployment strategy with a helm chart and an easy upgrade path but taking the above into account is very important.", "title": "Does the deployment need to be highly available(HA)?"}, {"location": "janssen-server/planning/kubernetes/#the-supported-clouds", "text": "We support several clouds managed Kubernetes solutions but that doesn't mean our setup will not work with other managed Kubernetes solutions. In fact, our Kubernetes setup is expected to work across almost all managed solutions however those not listed below were not tested. AWS GCP Azure DOKS", "title": "The Supported Clouds"}, {"location": "janssen-server/planning/kubernetes/#localhybrid", "text": "", "title": "Local/Hybrid"}, {"location": "janssen-server/planning/kubernetes/#rancher", "text": "Rancher UI can be deployed to several clouds / multi-clouds and also be used to manage local setups.", "title": "Rancher"}, {"location": "janssen-server/planning/kubernetes/#important-tools-and-tech-to-consider", "text": "Helm Terraform Prometheus and Grafana Pipeline tech such as Jenkins, Ansible, Cloud Build ..etc", "title": "Important tools and tech to consider"}, {"location": "janssen-server/planning/load-balancers/", "tags": ["administration", "planning", "load balancer", "nginx", "apache HTTPD", "istio"], "text": "Janssen Auth Server is stateless, so you can spool up as many instances as your load requires. But as there is only one hostname, you need a way to distribute the requests. Typically, this is where a load balancer comes in. The load balancer also terminates the SSL connection, which offloads the cryptographic compute from the application. In cloud-native jargon, load balancing is called HTTP Ingress. In your load balancer configuration, you can use any routing algorithm. There is no need for \"sticky sessions\", or whatever the load balancer you are using calls that. For example, it's ok to use even round robin. Although modern HTTP ingress controllers enable some very flexible routing options to do A/B testing and zero downtime updates. As Janssen Auth Server doesn't really care what load balancer you use, some options you might want to consider are: Apache HTTPD nginx istio f5 Amazon Elastic Load Balancing Google Cloud Load Balancing", "title": "Load Balancers"}, {"location": "janssen-server/planning/machine-to-machine/", "tags": ["administration", "planning"], "text": "OAuth gives us a perfect infrastructure for one machine (i.e. software) to authenticate itself while calling an API of another machine: the Client Credential Grant . The software receiving the token can validate the access token signature, or if it's a reference token, can use OAuth Introspection . For extra security, the software in question can also use mutual TLS to authenticate. The OAuth Authorization Server can also send extra security context, like scopes (which typically communicate the extent of access), or other information about the software vendor or characteristics. Of course this requires the devices in this machine-to-machine scenario to have a tcp stack (some constrained IOT devices only have a UDP stack).", "title": "Machine-to-Machine Authentication"}, {"location": "janssen-server/planning/multi-tenancy/", "tags": ["administration", "planning", "multitenancy"], "text": "Multitenancy is a software architecture where several distinct customers can utilize a single software instance. For a federated identity platform, this presents a number of challenges: Privacy: Customers must only see their own user information and data Trust: Customers trust a distinct set of RPs Authorization: Customers have specific policy requirements UX: Customers brand all user-facing web pages and messages Logs: Customers see only their own log Custom Business Logic: Customers have special rules, for example, to authenticate users, register clients, or issue access tokens. Cryptographic Keys: Customers have their own keys URLs: Customers host the IDP using their own domain name Quality of Service: Customers control response time and concurrency Access: Customers can access systems and data directly One key decision to make with regard to multitenancy is which systems to share. You could share nothing, which lowers deployment complexity but increases operational complexity. Or you could share everything, which is easier to operate, saves money on hardware, but requires a lot more code. Or you could land somewhere between--share some systems, but not others. If you want to address all the challenges of multitenancy, then a \"shared nothing\" approach makes the most sense. And with advances in cloud-native deployment, gitops, and configuration as code, you can approach the cost savings of \"shared everything\" multitenancy today, especially if you leverage serverless, just in time auto-scaling. However, you will need some cloud-native devops gurus to pull this off. If having one top-level domain is acceptable, it is possible to add a tenant_id property to each entity (for example, client and person entities). Auth Server and SCIM interception scripts enable you to filter results by adding this tenant_id to queries behind the scenes. For example, you could also render different login pages by using default_acr_values for clients. It's possible in the future Jansen Project will implement some kind of support to bundle a multitenancy approach that captures some of the properties described above at the code level, but for the time being, it is not a priority.", "title": "Multi-tenancy"}, {"location": "janssen-server/planning/passwordless-auth/", "tags": ["administration", "planning", "passwordless"], "text": "Auth Server is not proscriptive about how an organization authenticates a person. If you want to avoid passwords, that's great. Everyone knows passwords are terrible. Modern authentication flows use a series of web pages to mitigate sufficient risk, enabling them to issue an assertion about the subject's identity. In order to perform authentication, identification is a given. This implies that all authentication flows normally start with the subject asserting some kind of identifier: username, email address, phone number, or any other identifier that uniquely identifies a person. Auth Server is not opinionated about how you do this. You could prompt the user to enter their identifier. Or for example, you could ask the user to scan a QR code, and identify a phone identified with a person. With identification done, Auth Server can present any number of additional web pages to establish that identity. These pages can ask for any \"factors\". For example, if you want to perform two factor authentication in one step, you could use a FIDO 2 credential, which combines possession with either knowledge or biometric. But in practice, you could ask for any one or more combinations of credentials--none of which must include a password. Net-net, \"passwordless\" is really just marketing jargon. Normally it implies some kind of risk assessment to optimize user experience. If you can imagine any such authentication flow, you can implement it in Auth Server.", "title": "Passwordless Authentication"}, {"location": "janssen-server/planning/persistence/", "tags": ["administration", "planning", "persistence", "MySQL", "Aurora", "Postgres", "database"], "text": "The performance of the web tier is derived from the performance of the persistence tier. While memory-caching short lived entities to reduce persistence is an option, there are still long lived objects that need to be written to the disk. Picking the right database has a huge impact on the operational burden of a digital identity infrastructure. All database administration requires some black art--every platform has some secret knobs and levers that are critical to tuning, availability and rapid diagnosis. So beyond the performance requirements that determine the right choice for a database, you also need to consider operational concerns. Janssen's strategy is to provide optionality for persistence. There is no one size fits all solution for databases. The following section will detail some of the pros and cons of the various databases we currently support. MySQL You know it... you love it. That's the biggest advantage. Performance is great out of the box. But if you have high concurrency, you'll have to figure out a plan for replication, and horizontal scaling. MySQL is our default persistence for Production deployments using Kubernetes . Postgres Same as MySQL above, but there are some great commercial distributions of Postgres like EnterpriseDB . Postgres is our default persistence for VM based non-production deployments . Aurora So you want MySQL, but you want Amazon to handle some of the care and feeding? Aurora enables you to consume database as a cloud service. Scalability is excellent and multi-region deployments are possible . The main catch is that write operations are limited to one region, with the ability to failover to another region. But to accomplish this, you need a cloud engineer to implement it.", "title": "Persistence"}, {"location": "janssen-server/planning/platform-goal/", "tags": ["administration", "planning", "platform-goals"], "text": "Mission # Make it easier for organizations to innovate and scale open source, standards-based identity services. Scale # Using Janssen Project software, organizations can build runtime identity services to meet 100% of their requirements for enrollment, authentication, credential management, and authorization. The Janssen Project includes software tools and services for deploying, operating, testing, and developing identity infrastructure at scale. Scale is more than cloud-native design patterns. To truly scale, domains have to consider the people and organizational challenges. To scale domains need to: manage the complexity and cost of integrating multiple technologies, platforms, and vendors that may not be compatible or interoperable ensure the security and compliance of data and transactions across different systems, networks, and jurisdictions, especially when dealing with sensitive or regulated information adapt to the changing and unpredictable demands of customers, markets, and deliver fast and reliable services; domains must develop and share the skills and talent needed to design, implement, and operate scalable identity infrastructure, and foster a culture of innovation and collaboration among teams balance the trade-offs between scaling up (adding more resources within a system) and scaling out (adding more systems across a network), and choosing the optimal architecture and configuration for different workloads and scenarios. At the Janssen Project, we are doing our best to address all these challenges with regard to scaling identity infrastructure. Security # Janssen Project tackles the most challenging security requirements. This means keeping current with OpenID and FIDO self-certifications, creating distributions that enables conformance with FIPS 140-2, and implementing best practices for software development. Janssen Project is unapologetically Java. The reason is simple: Java has the most cryptographic implementations. Java Cryptographic Engines (JCE) are written by many companies and open-source projects. It takes a long time to trust a cryptographic implementation. Not only does Java have the most options for cryptography, but it also has some of the most trusted implementations. And when new algorithms are announced, Java SDKs are usually first. Community # In 2020, Gluu contributed the code to the Linux Foundation Janssen Project. One of the main reasons this was undertaken was to expand the size of the community. Developers don't want to contribute to a project that might change the license at any moment (e.g. Hashicorp, Elastic, MongoDB). There is room for many companies to productize the Janssen Project software. Governments can feel safe using the Janssen Project--it's been recognized as a Digital Public Good . A healthy ecosystem for infrastructure software results in long-term innovation velocity. With the introduction of Agama, we're hoping that developers will have an opportunity to build connectors to third-party systems and services. Gluu is hosting the Agama Lab Explore Catalog to help developers publish their Agama projects, making it easier for the community to find ready-built projects that encourage the re-use of code. Deployment # Developers should have distributions to enable rapid testing for non-production instances. Linux system administrators should have packages for easy installation and update of non-clustered deployments. Cloud-native engineers should have assets for high-end deployments, including high concurrency and high availability.", "title": "Platform Goal"}, {"location": "janssen-server/planning/platform-goal/#mission", "text": "Make it easier for organizations to innovate and scale open source, standards-based identity services.", "title": "Mission"}, {"location": "janssen-server/planning/platform-goal/#scale", "text": "Using Janssen Project software, organizations can build runtime identity services to meet 100% of their requirements for enrollment, authentication, credential management, and authorization. The Janssen Project includes software tools and services for deploying, operating, testing, and developing identity infrastructure at scale. Scale is more than cloud-native design patterns. To truly scale, domains have to consider the people and organizational challenges. To scale domains need to: manage the complexity and cost of integrating multiple technologies, platforms, and vendors that may not be compatible or interoperable ensure the security and compliance of data and transactions across different systems, networks, and jurisdictions, especially when dealing with sensitive or regulated information adapt to the changing and unpredictable demands of customers, markets, and deliver fast and reliable services; domains must develop and share the skills and talent needed to design, implement, and operate scalable identity infrastructure, and foster a culture of innovation and collaboration among teams balance the trade-offs between scaling up (adding more resources within a system) and scaling out (adding more systems across a network), and choosing the optimal architecture and configuration for different workloads and scenarios. At the Janssen Project, we are doing our best to address all these challenges with regard to scaling identity infrastructure.", "title": "Scale"}, {"location": "janssen-server/planning/platform-goal/#security", "text": "Janssen Project tackles the most challenging security requirements. This means keeping current with OpenID and FIDO self-certifications, creating distributions that enables conformance with FIPS 140-2, and implementing best practices for software development. Janssen Project is unapologetically Java. The reason is simple: Java has the most cryptographic implementations. Java Cryptographic Engines (JCE) are written by many companies and open-source projects. It takes a long time to trust a cryptographic implementation. Not only does Java have the most options for cryptography, but it also has some of the most trusted implementations. And when new algorithms are announced, Java SDKs are usually first.", "title": "Security"}, {"location": "janssen-server/planning/platform-goal/#community", "text": "In 2020, Gluu contributed the code to the Linux Foundation Janssen Project. One of the main reasons this was undertaken was to expand the size of the community. Developers don't want to contribute to a project that might change the license at any moment (e.g. Hashicorp, Elastic, MongoDB). There is room for many companies to productize the Janssen Project software. Governments can feel safe using the Janssen Project--it's been recognized as a Digital Public Good . A healthy ecosystem for infrastructure software results in long-term innovation velocity. With the introduction of Agama, we're hoping that developers will have an opportunity to build connectors to third-party systems and services. Gluu is hosting the Agama Lab Explore Catalog to help developers publish their Agama projects, making it easier for the community to find ready-built projects that encourage the re-use of code.", "title": "Community"}, {"location": "janssen-server/planning/platform-goal/#deployment", "text": "Developers should have distributions to enable rapid testing for non-production instances. Linux system administrators should have packages for easy installation and update of non-clustered deployments. Cloud-native engineers should have assets for high-end deployments, including high concurrency and high availability.", "title": "Deployment"}, {"location": "janssen-server/planning/role-based-access-management/", "tags": ["administration", "planning", "RBAC", "Role"], "text": "Using roles to control access to resources makes sense for lots of security use cases. One benefit of RBAC is that it's deterministic-- from an audit perspective, you can tell who had access to what at any point in time. This is harder to achieve when contextual variables play a role in determining access. An OpenID Provider / OAuth Authorization Server like Jans Auth Server certainly has a role to play in the implementation of an RBAC infrastructure, but is not capable of delivering all the functionality your organization will need for a complete solution. For example, you may need a platform to define enterprise roles or to perform role consolidation. This is normally handled by an identity governance tool. Also, Jans Auth Server is not a policy management platform, like * Styra OPA , OSO * Zanzibar , or * Hashicorp Boundary or * Apache Fortress The tools above are just a few open source policy management frameworks. There are more commercial products in this space. Although Jans Auth Server may not be a complete RBAC solution, there are still some RBAC capabilities to consider. When a person authenticates using a web browser, the client can obtain user claims via OpenID Connect. It may make sense to send the role role claim to the client. You may also send the memberOf claim, if your organization uses group membership to manage roles. But what if you need to dynamically compute roles? Or if you don't want to over-share by sending all the roles and groups associated for a person? One strategy is to use the Jans Auth Server Update Token Interception script to render the role claim, either in the OAuth access token, the id_token or the Userinfo JWT.", "title": "Role Based Access Management"}, {"location": "janssen-server/planning/security-best-practices/", "tags": ["administration", "planning", "security", "recommendations"], "text": "Janssen Project distributions are designed to be easy to deploy. Its default security settings may not be strict enough for certain organizations or use cases. This document highlights important security controls and offers best practices for increasing security related to your deployment. Scripts # Make sure only required scripts are enabled. It's extremely important to disable any person authentication or other scripts not in use. Keys # Use RSA keys with a minimum strength of 2048 bits and Elliptic Curve keys with a minimum of 160 bits. Also, check the key rotation policy of your Auth Server. This differs based on your deployment model. A single server can handle key rotation locally, but if you have deployed a cluster, you must manage key rotation centrally. Admin Web Services # Make sure SCIM and the config API are not Internet facing. If you do expose SCIM, you should network restrict access as much as possible. Although SCIM is protected via OAuth or UMA access tokens, because a breach of SCIM would undermine the integrity of authentications, a multi-layer security approach is warranted. There is no use case for an Internet facing Config API--you should tightly control access to this service. Make sure no services are listening on external interfaces except for those that are absolutely required-- tcp/443 for the OpenID and FIDO endpoints. On Linux servers, a list of current listeners can be obtained with netstat -nlpt (for TCP) and netstat -nlpu (for UDP). In particular, make sure the internal databases used by Gluu to store all its configuration are not Internet facing. OpenID # Review the OAuth 2.0 Security Best Current Practice IETF draft. Don't use the implicit flow. In the implicit flow, the client is not authenticated, and a token is returned from the Authorization endpoint. If the response_type in your OpenID Authentication contains token , you are using the implicit flow. Section 2.1.2 of the current OAuth Security Best Practices OAuth working group draft specifically warns against using the implicit flow. If you must use the implicit flow, Review the CORS filter configuration for Jans Auth Server. CORS restricts access to trusted domains to execute browser application requests to Auth Server endpoints. By default, the filter allows any RP to call OpenID endpoints. Review Auth Server properties chosen for sessionIdUnusedLifetime and sessionIdLifetime . Long sessions present higher risks of session hijacking and unauthorized access from shared devices. OAuth Client Security # The table below summarizes the default values for dynamically registered clients. Attribute Default Value applicationType web subjectType public idTokenSignedResponseAlg RS512 userInfoSignedResponseAlg RS512 userInfoEncryptedResponseAlg RSA-OAEP userInfoEncryptedResponseEnc RSA-OAEP accessTokenLifetime 3600 Consider whether support of OpenID Connect Dynamic Client Registration extension is required. If not, disable it by setting dynamicRegistrationEnabled to False . If Dynamic Client Registration is enabled, consider using software statements , and writing a Client Registration interception script to implement extra rules for software statement validation. Check the list of scopes to quickly assess which scopes the clients can potentially add to their registration entry without consent of OP's administrator. Make sure sensitive scopes are dynamicRegistrationScopesParamEnabled set to False. The Auth Server property dynamicRegistrationScopesParamEnabled controls whether default scopes are globally enabled; scopes defined as default will be automatically added to any dynamically registered client entry. For client authentication at the token endpoint, move away from shared secrets-- use either private key authentication or MTLS . A client secret is basically a password for your software application. Utilize asymmetric client authentication. Make sure your OpenID client applications check the state value, and verify that it is the same state posted in the original request. This is necessary to prevent Cross Site Request Forgery (CSRF). Also make sure that clients use a non-static value for state (i.e. a one time non-guessable value). You can also verify the state in the s_hash claim of the id_token in the authentication response. This may sound obvious, but make sure your clients verify the signature of the id_token. The location of the current public keys of the OpenID Provider can be found in the configuration endpoint ( jwks_uri ). It is also recommended that clients implement a unique redirect_uri per OP. This may also sound obvious, but make sure you trust the OpenID Connect client software library that your developers are using to authenticate users. Also make sure OpenID Connect client libraries are updated expeditiously. Suggest to web developers that they read the OpenID Connect Basic Client Implementer's Guide , which provides a more reader-friendly narrative for how to use the OpenID code flow--the main flow for relying parties. Client developers should consider using a Request Object JWT, which prevents hackers from tampering with the request parameters. Request objects can mitigate the Malicious Endpoint Attack and the IDP confusion attack. Mobile developers should read RFC 8252 OAuth 2.0 for Native Apps and follow the recommendations there. It's really important not to store any client secret or private key in the application, because hackers can decompile applications to extract these secrets. That's why RFC 8252 recommends using PKCE to prevent Authorization Code Interception Attack, and use a SHA256 as the code challenge method. Use App Auth if possible for Android , iOS , or JavaScript . If additional client security is needed, consider using the FAPI profile of OpenID Connect, which adds additional signing, encryption and security mitigations. UMA # The UMA protocol enables post-authentication authorization flows. Consider the following system-level properties: umaGrantAccessIfNoPolicies allows access to a resource even if no policies are defined for the related scopes; though it simplifies initial testing, we recommend disabling this feature in production setups umaRestrictResourceToAssociatedClient won't allow any other client except the one that registered the resource initially to acquire a RPT for it; it's recommended to have it enabled for production setups", "title": "Security Best Practices"}, {"location": "janssen-server/planning/security-best-practices/#scripts", "text": "Make sure only required scripts are enabled. It's extremely important to disable any person authentication or other scripts not in use.", "title": "Scripts"}, {"location": "janssen-server/planning/security-best-practices/#keys", "text": "Use RSA keys with a minimum strength of 2048 bits and Elliptic Curve keys with a minimum of 160 bits. Also, check the key rotation policy of your Auth Server. This differs based on your deployment model. A single server can handle key rotation locally, but if you have deployed a cluster, you must manage key rotation centrally.", "title": "Keys"}, {"location": "janssen-server/planning/security-best-practices/#admin-web-services", "text": "Make sure SCIM and the config API are not Internet facing. If you do expose SCIM, you should network restrict access as much as possible. Although SCIM is protected via OAuth or UMA access tokens, because a breach of SCIM would undermine the integrity of authentications, a multi-layer security approach is warranted. There is no use case for an Internet facing Config API--you should tightly control access to this service. Make sure no services are listening on external interfaces except for those that are absolutely required-- tcp/443 for the OpenID and FIDO endpoints. On Linux servers, a list of current listeners can be obtained with netstat -nlpt (for TCP) and netstat -nlpu (for UDP). In particular, make sure the internal databases used by Gluu to store all its configuration are not Internet facing.", "title": "Admin Web Services"}, {"location": "janssen-server/planning/security-best-practices/#openid", "text": "Review the OAuth 2.0 Security Best Current Practice IETF draft. Don't use the implicit flow. In the implicit flow, the client is not authenticated, and a token is returned from the Authorization endpoint. If the response_type in your OpenID Authentication contains token , you are using the implicit flow. Section 2.1.2 of the current OAuth Security Best Practices OAuth working group draft specifically warns against using the implicit flow. If you must use the implicit flow, Review the CORS filter configuration for Jans Auth Server. CORS restricts access to trusted domains to execute browser application requests to Auth Server endpoints. By default, the filter allows any RP to call OpenID endpoints. Review Auth Server properties chosen for sessionIdUnusedLifetime and sessionIdLifetime . Long sessions present higher risks of session hijacking and unauthorized access from shared devices.", "title": "OpenID"}, {"location": "janssen-server/planning/security-best-practices/#oauth-client-security", "text": "The table below summarizes the default values for dynamically registered clients. Attribute Default Value applicationType web subjectType public idTokenSignedResponseAlg RS512 userInfoSignedResponseAlg RS512 userInfoEncryptedResponseAlg RSA-OAEP userInfoEncryptedResponseEnc RSA-OAEP accessTokenLifetime 3600 Consider whether support of OpenID Connect Dynamic Client Registration extension is required. If not, disable it by setting dynamicRegistrationEnabled to False . If Dynamic Client Registration is enabled, consider using software statements , and writing a Client Registration interception script to implement extra rules for software statement validation. Check the list of scopes to quickly assess which scopes the clients can potentially add to their registration entry without consent of OP's administrator. Make sure sensitive scopes are dynamicRegistrationScopesParamEnabled set to False. The Auth Server property dynamicRegistrationScopesParamEnabled controls whether default scopes are globally enabled; scopes defined as default will be automatically added to any dynamically registered client entry. For client authentication at the token endpoint, move away from shared secrets-- use either private key authentication or MTLS . A client secret is basically a password for your software application. Utilize asymmetric client authentication. Make sure your OpenID client applications check the state value, and verify that it is the same state posted in the original request. This is necessary to prevent Cross Site Request Forgery (CSRF). Also make sure that clients use a non-static value for state (i.e. a one time non-guessable value). You can also verify the state in the s_hash claim of the id_token in the authentication response. This may sound obvious, but make sure your clients verify the signature of the id_token. The location of the current public keys of the OpenID Provider can be found in the configuration endpoint ( jwks_uri ). It is also recommended that clients implement a unique redirect_uri per OP. This may also sound obvious, but make sure you trust the OpenID Connect client software library that your developers are using to authenticate users. Also make sure OpenID Connect client libraries are updated expeditiously. Suggest to web developers that they read the OpenID Connect Basic Client Implementer's Guide , which provides a more reader-friendly narrative for how to use the OpenID code flow--the main flow for relying parties. Client developers should consider using a Request Object JWT, which prevents hackers from tampering with the request parameters. Request objects can mitigate the Malicious Endpoint Attack and the IDP confusion attack. Mobile developers should read RFC 8252 OAuth 2.0 for Native Apps and follow the recommendations there. It's really important not to store any client secret or private key in the application, because hackers can decompile applications to extract these secrets. That's why RFC 8252 recommends using PKCE to prevent Authorization Code Interception Attack, and use a SHA256 as the code challenge method. Use App Auth if possible for Android , iOS , or JavaScript . If additional client security is needed, consider using the FAPI profile of OpenID Connect, which adds additional signing, encryption and security mitigations.", "title": "OAuth Client Security"}, {"location": "janssen-server/planning/security-best-practices/#uma", "text": "The UMA protocol enables post-authentication authorization flows. Consider the following system-level properties: umaGrantAccessIfNoPolicies allows access to a resource even if no policies are defined for the related scopes; though it simplifies initial testing, we recommend disabling this feature in production setups umaRestrictResourceToAssociatedClient won't allow any other client except the one that registered the resource initially to acquire a RPT for it; it's recommended to have it enabled for production setups", "title": "UMA"}, {"location": "janssen-server/planning/self-service-password-2fa/", "tags": ["administration", "planning", "2FA", "self-service", "Account Recovery", "Jans casa"], "text": "If your domain offers two-factor authentication, it's a good idea to enable end users to manage their various credentials. Google does a great job in this regard. Check out 2-Step Verification . What's great about this page is that Google lets you manage all your different credentials on one page. You can build a page like Google on your own website. You need to be able to list, add, and remove 2FA credentials for a given user's account. But another good option is the Jans Casa web application.", "title": "Self-Service Password/2FA Portal"}, {"location": "janssen-server/planning/stepped-up-auth/", "tags": ["administration", "planning", "stepped-up authentication"], "text": "The holy grail of security policies since the introduction of RSA OTP tokens, stepped-up authentication is when the subject is presented with an additional authentication requirement, usually in response to perceived risk. As Jans How do you decide when to invoke stepped-up authentication? As Auth Server is not a policy enforcement point, or a policy management system, these two aspects are out of scope. But once you make a runtime decision that you need more evidence of identity, the OpenID Connect Authentication Request has a few features that can help you out. The first is prompt=login . This is a hint from the Relying Party to the OpenID Provider that re-authentication is needed. Not all OpenID Connect providers support this feature (for example, Google does not). However Auth Server does currently support this parameter, although there is a feature request to make it optional. The second is acr_values . In Auth Server, this provides a hint to the Auth Server to invoke a specific Person Authentication interception script. Typically, this would specify your workflow for additional authentication. If you are using Agama, you can also provide a hint for which Agama flow to invoke by adding __. Another more esoteric strategy is to use UMA claims gathering. In this flow, the subject's browser is directed to the claims gathering endpoint (i.e. front channel), at which point the claims gathering script could invoke an OpenID authentication, using the prompt and acr_values parameters mentioned above. If you want to see an example of how a client implements stepped-up authentication, you should checkout this mod_auth_openidc wiki page .", "title": "Stepped-up Authentication"}, {"location": "janssen-server/planning/timeout-management/", "tags": ["administration", "planning", "timeout"], "text": "Warning: business expectations regarding timeouts may drive you crazy. There are several timeout values in Janssen Auth Server. Also, web apps and mobile apps may have their own timeout thresholds. The holy grail of timeouts is when everything times out at the same time--IDP and applications. This is rarely attainable. Normally the application needs to handle gracefully the case when the IDP session expires first. And if the application session expires first, it may need to trigger a logout event at the OpenID Provider. Below is a list of some of the Auth Server configuration properties for timeouts that you should consider: sessionIdCookieLifetime sessionIdLifetime sessionIdUnusedLifetime sessionIdUnauthenticatedUnusedLifetime spontaneousScopeLifetime refreshTokenLifetime idTokenLifetime accessTokenLifetime cleanServiceInterval dynamicRegistrationExpirationTime refreshTokenExtendLifetimeOnRotation CIBA, UMA and Device Flow : have their own specific timeouts.", "title": "Timeout Management"}, {"location": "janssen-server/planning/use-cases/", "tags": ["administration", "planning", "use-cases", "architecture"], "text": "Browser Single Sign-On (B-SS0) # Web browser SSO is one of the main use cases for Janssen. The OpenID Connect interfaces of the Auth Server provide the identity layer that manages authentication and B-SSO. Auth Server tracks web browser sessions via a cookie. An end user may actually have several active sessions, although only one session is active. For example, below is a hypothetical session cookie: session_id: c691e83d-eb1b-41f0-b453-fab905681b5b current_sessions: [\"de510ab6-b06c-4393-86d8-12a7c501aafe\", \"c691e83d-eb1b-41f0-b453-fab905681b5b\"] To switch sessions, an RP can redirect to the Jans Auth Server OpenID Connect Provider authorization endpoint with the parameters prompt=select_account . Native Single Sign-On (N-SS0) # On most mobile platforms, mobile apps signed by the same vendor certs can share information via the system \"keychain\" (Account Manager on Android). OpenID Mobile SSO specifies a new scope, extends the token endpoint, and profiles the OAuth2 Token Exchange spec allowing mobile apps to share identity between apps produced and signed by the same vendor (i.e. signed with the same vendor certificate). Single Logout (SLO) # The bane of identity engineers everywhere, Auth Server does offer some endpoints that enable SLO. Janssen Auth Server implements Back-Channel Logout and Session Management . But the most commonly used strategy is Front-Channel Logout . This works by displaying a web page with numerous iFrames, each with the respective logout URL for each application. The reason SLO is so hard is that logout is inherently an asynchronous use case. When you need a bunch of websites to receive a notification, some of those notifications may fail. Ideally, you'd replay messages that aren't received. But end users want a fast logout response, and don't want to wait for all the applications to confirm they received and acted on the notification. So making logout synchronous is a round-hole / square-peg situation. But with that said, Auth Server supports it. API Access Management # Janssen Auth Server is frequently used to issue access tokens to authenticate software clients that needs to call an API. The OAuth WG has published many useful specifications about how to do this securely, and Janssen implements many of these RFCs and drafts. In OAuth parlance, Jans Auth Server is the Authorization Server; and Jans Client API is a service that helps clients with advanced features like MTLS and private key authentication. As OAuth scopes are frequently used to control the extent of access of clients, many domains are using Jans Auth Server to dynamically render scopes based on the identity of the client, or the security context. The Jans Auth Server also implements OAuth and OpenID client registration API. Finally, Jans Auth Server publishes an SSA endpoint, for OAuth software statement assertions which enables trusted services to request an SSA that specifies what type of clients can register. All of these features mean that Jans Auth Server is an essential tool as part of your API access management infrastructure. Multifactor Authentication # OpenID Connect is a web identity layer. Auth Server displays and processes a series of web pages to authenticate a person, and then shares user claims with the applications that requested them. Out of the box, Auth Server supports many MFA workflows, including FIDO, passkeys, OATH OTP (HOTP, TOTP), SMS (via Twilio or SMPP), and many more. But you're not limited to the MFA that comes out of the box. Using Person Authentication Scripts, you can implement any authentication workflow that you can imagine. You can also use the Janssen Project's Agama programming language to implement multi-step authentication workflows. Mobile Authentication # One of the initial requirements for OpenID was to support mobile apps (because SAML is terrible for mobile apps). OpenID and OAuth have developed several mitigations that make mobile authentication more secure, which are described in RFC 8252 . However, due to the complexity of cookie sharing between the mobile phone browser SDK, and the mobile browser (assuming you are using the system browser), your results may vary if you actually want SSO. Recently, OpenID has published a new specification draft for Native SSO for Mobile Apps , that is on the roadmap . There are some other hacky ways you can implement mobile authentication, for example, using the OAuth password grant--but this is possible only for first-party applications, and is generally discouraged because there is no way to securely store a client secret in the mobile application, which hackers can easily decompile. Open Banking # You'll notice that the Gluu Open Banking Identity Platform is certified for Financial-grade API (FAPI) 1.0 Final--this is Gluu's distribution of the Janssen Auth Server profiled for banking. If you want to implement an OP for open banking, Jans Auth Server is one of the few comprehensive open-source platforms that will enable you to do so. Social Sign-in # This could really be covered under the MFA section. But it's not uncommon that as part of an authentication workflow, Auth Server may redirect you to an external identity provider, which then sends you back to Auth Server with some kind of reference id or assertion. Out of the box, Jans supports the top three social sites: Google, Apple, and Facebook (which account for 80% of social login). But of course, you can implement any social login using an Agama project. Registration # It's not that uncommon that an authentication workflow is used to create an account for a person in an identity provider. In fact, it's so common, that the OpenID working group recently created a spec to standardize a parameter in the authentication request to signal to the OpenID Provider that this is what's happening: prompt=create . As we're just displaying a series of web pages, we can display a registration form, process the form (with some kind of remote identity proofing?), send an email, SMS, Telegram messages, or whatever. Also, frequently social login is tied to registration--the first time you login with an external IDP, Auth Server creates an account on the fly with the user claims sent by the remote IDP. Authorization # Frequently people conflate the identity layer with the authorization layer. RBAC is still an important security paradigm. So it makes sense to people that the place where you store information about a person's roles is where you define policies about what resources a role can access (i.e. policies). Recently, centralized authorization has had an active resurgence. Companies like Styra , Oso , and HashiCorp have introduced innovative centralized authorization software. These systems, acting as a \"policy decision point\", enable you to define policies, and can evaluate these policies at runtime. Note: they rely on \"policy enforcement points\" to call their endpoints, supplying the data which is input to policies. With that said, there are places in Auth Server where you can define or impact authorization (besides user claims). In particular, OAuth scopes are used to convey the extent of access in an access token, that when presented to an API by a software client, enables access control. However, the scope is still input to policy, and may in fact be just one more piece of data considered by a policy decision point. And one more caveat... the \"authorization\" in an OAuth \"authorization server\", was originally meant to convey the authorization of the person who was trying to access something. Whether a person consented to share information, or grant a client the ability to act on their behalf, is another important consideration. So does \"Auth Server\" provide authorization? It depends! Consent Gathering # Through the \"front channel\" (i.e. the browser), Auth Server can interact with a person by displaying web pages. OpenID Connect and OAuth scopes trigger the authorization phase (after authentication). By default, the scopes requested by the client and their respective descriptions are displayed for approval. However, like all pages in Auth Server, these pages can be customized to meet your exact requirements. Auth Server also implements the User Managed Access Protocol (\"UMA\"). This profile of OAuth2 enables consent to be sought from a person even after the initial authentication has taken place. This phase is also called \"claims gathering\", but one of the claims could be whether a person consents to something. Note: Authorizations are stored relative to a person's entity in the database. How a person views and revokes consent is outside the scope of Auth Server. To view a person's consents, you need to use the config API, as this information is not shared via OpenID Connect or SCIM.", "title": "Use Cases"}, {"location": "janssen-server/planning/use-cases/#browser-single-sign-on-b-ss0", "text": "Web browser SSO is one of the main use cases for Janssen. The OpenID Connect interfaces of the Auth Server provide the identity layer that manages authentication and B-SSO. Auth Server tracks web browser sessions via a cookie. An end user may actually have several active sessions, although only one session is active. For example, below is a hypothetical session cookie: session_id: c691e83d-eb1b-41f0-b453-fab905681b5b current_sessions: [\"de510ab6-b06c-4393-86d8-12a7c501aafe\", \"c691e83d-eb1b-41f0-b453-fab905681b5b\"] To switch sessions, an RP can redirect to the Jans Auth Server OpenID Connect Provider authorization endpoint with the parameters prompt=select_account .", "title": "Browser Single Sign-On (B-SS0)"}, {"location": "janssen-server/planning/use-cases/#native-single-sign-on-n-ss0", "text": "On most mobile platforms, mobile apps signed by the same vendor certs can share information via the system \"keychain\" (Account Manager on Android). OpenID Mobile SSO specifies a new scope, extends the token endpoint, and profiles the OAuth2 Token Exchange spec allowing mobile apps to share identity between apps produced and signed by the same vendor (i.e. signed with the same vendor certificate).", "title": "Native Single Sign-On (N-SS0)"}, {"location": "janssen-server/planning/use-cases/#single-logout-slo", "text": "The bane of identity engineers everywhere, Auth Server does offer some endpoints that enable SLO. Janssen Auth Server implements Back-Channel Logout and Session Management . But the most commonly used strategy is Front-Channel Logout . This works by displaying a web page with numerous iFrames, each with the respective logout URL for each application. The reason SLO is so hard is that logout is inherently an asynchronous use case. When you need a bunch of websites to receive a notification, some of those notifications may fail. Ideally, you'd replay messages that aren't received. But end users want a fast logout response, and don't want to wait for all the applications to confirm they received and acted on the notification. So making logout synchronous is a round-hole / square-peg situation. But with that said, Auth Server supports it.", "title": "Single Logout (SLO)"}, {"location": "janssen-server/planning/use-cases/#api-access-management", "text": "Janssen Auth Server is frequently used to issue access tokens to authenticate software clients that needs to call an API. The OAuth WG has published many useful specifications about how to do this securely, and Janssen implements many of these RFCs and drafts. In OAuth parlance, Jans Auth Server is the Authorization Server; and Jans Client API is a service that helps clients with advanced features like MTLS and private key authentication. As OAuth scopes are frequently used to control the extent of access of clients, many domains are using Jans Auth Server to dynamically render scopes based on the identity of the client, or the security context. The Jans Auth Server also implements OAuth and OpenID client registration API. Finally, Jans Auth Server publishes an SSA endpoint, for OAuth software statement assertions which enables trusted services to request an SSA that specifies what type of clients can register. All of these features mean that Jans Auth Server is an essential tool as part of your API access management infrastructure.", "title": "API Access Management"}, {"location": "janssen-server/planning/use-cases/#multifactor-authentication", "text": "OpenID Connect is a web identity layer. Auth Server displays and processes a series of web pages to authenticate a person, and then shares user claims with the applications that requested them. Out of the box, Auth Server supports many MFA workflows, including FIDO, passkeys, OATH OTP (HOTP, TOTP), SMS (via Twilio or SMPP), and many more. But you're not limited to the MFA that comes out of the box. Using Person Authentication Scripts, you can implement any authentication workflow that you can imagine. You can also use the Janssen Project's Agama programming language to implement multi-step authentication workflows.", "title": "Multifactor Authentication"}, {"location": "janssen-server/planning/use-cases/#mobile-authentication", "text": "One of the initial requirements for OpenID was to support mobile apps (because SAML is terrible for mobile apps). OpenID and OAuth have developed several mitigations that make mobile authentication more secure, which are described in RFC 8252 . However, due to the complexity of cookie sharing between the mobile phone browser SDK, and the mobile browser (assuming you are using the system browser), your results may vary if you actually want SSO. Recently, OpenID has published a new specification draft for Native SSO for Mobile Apps , that is on the roadmap . There are some other hacky ways you can implement mobile authentication, for example, using the OAuth password grant--but this is possible only for first-party applications, and is generally discouraged because there is no way to securely store a client secret in the mobile application, which hackers can easily decompile.", "title": "Mobile Authentication"}, {"location": "janssen-server/planning/use-cases/#open-banking", "text": "You'll notice that the Gluu Open Banking Identity Platform is certified for Financial-grade API (FAPI) 1.0 Final--this is Gluu's distribution of the Janssen Auth Server profiled for banking. If you want to implement an OP for open banking, Jans Auth Server is one of the few comprehensive open-source platforms that will enable you to do so.", "title": "Open Banking"}, {"location": "janssen-server/planning/use-cases/#social-sign-in", "text": "This could really be covered under the MFA section. But it's not uncommon that as part of an authentication workflow, Auth Server may redirect you to an external identity provider, which then sends you back to Auth Server with some kind of reference id or assertion. Out of the box, Jans supports the top three social sites: Google, Apple, and Facebook (which account for 80% of social login). But of course, you can implement any social login using an Agama project.", "title": "Social Sign-in"}, {"location": "janssen-server/planning/use-cases/#registration", "text": "It's not that uncommon that an authentication workflow is used to create an account for a person in an identity provider. In fact, it's so common, that the OpenID working group recently created a spec to standardize a parameter in the authentication request to signal to the OpenID Provider that this is what's happening: prompt=create . As we're just displaying a series of web pages, we can display a registration form, process the form (with some kind of remote identity proofing?), send an email, SMS, Telegram messages, or whatever. Also, frequently social login is tied to registration--the first time you login with an external IDP, Auth Server creates an account on the fly with the user claims sent by the remote IDP.", "title": "Registration"}, {"location": "janssen-server/planning/use-cases/#authorization", "text": "Frequently people conflate the identity layer with the authorization layer. RBAC is still an important security paradigm. So it makes sense to people that the place where you store information about a person's roles is where you define policies about what resources a role can access (i.e. policies). Recently, centralized authorization has had an active resurgence. Companies like Styra , Oso , and HashiCorp have introduced innovative centralized authorization software. These systems, acting as a \"policy decision point\", enable you to define policies, and can evaluate these policies at runtime. Note: they rely on \"policy enforcement points\" to call their endpoints, supplying the data which is input to policies. With that said, there are places in Auth Server where you can define or impact authorization (besides user claims). In particular, OAuth scopes are used to convey the extent of access in an access token, that when presented to an API by a software client, enables access control. However, the scope is still input to policy, and may in fact be just one more piece of data considered by a policy decision point. And one more caveat... the \"authorization\" in an OAuth \"authorization server\", was originally meant to convey the authorization of the person who was trying to access something. Whether a person consented to share information, or grant a client the ability to act on their behalf, is another important consideration. So does \"Auth Server\" provide authorization? It depends!", "title": "Authorization"}, {"location": "janssen-server/planning/use-cases/#consent-gathering", "text": "Through the \"front channel\" (i.e. the browser), Auth Server can interact with a person by displaying web pages. OpenID Connect and OAuth scopes trigger the authorization phase (after authentication). By default, the scopes requested by the client and their respective descriptions are displayed for approval. However, like all pages in Auth Server, these pages can be customized to meet your exact requirements. Auth Server also implements the User Managed Access Protocol (\"UMA\"). This profile of OAuth2 enables consent to be sought from a person even after the initial authentication has taken place. This phase is also called \"claims gathering\", but one of the claims could be whether a person consents to something. Note: Authorizations are stored relative to a person's entity in the database. How a person views and revokes consent is outside the scope of Auth Server. To view a person's consents, you need to use the config API, as this information is not shared via OpenID Connect or SCIM.", "title": "Consent Gathering"}, {"location": "janssen-server/planning/vm-cluster/", "tags": ["administration", "planning", "vm", "cluster"], "text": "Note For high availability, we recommend using the Cloud-Native(CN) deployment instead of VM cluster deployments. What if you need four or five nines availability, but cloud-native is not an option? You could cluster Janssen using VMs, but you'll have to do some legwork, because we don't publish tools for this task. This planning guide will cover some of the things you'll need to consider. Hostname : Remember when you run the Linux setup to use the hostname of the cluster, not the hostname of the individual server. This is important because the OpenID Provider metadata needs to use the public hostname (i.e. the URLs you'll find at /.well-known/openid-configuration ) Load Balancing / SSL : As Auth Server and FIDO (the two Internet facing components) are stateless, you can use any load balancer routing algorithm, even round robin. You can also use the load balancer to terminate SSL. Database : The web services Janssen Components share the database, so you'll have to use database replication. You could also use a cloud database that takes care of replication for you. Cache : You can't use IN-MEMORY cache which would have no way to replicate to the other nodes in the network. You could use the Database for caching, although this will impact performance, although it's only an issue for high concurrency use cases. But if you really need a very high concurrency, our recommendation is to use Redis for caching, which has less cache hit misses than Memcached. Key management : Where do you store the private keys? If on the file system, you'll have to make sure that they get securely copied. This is trickier than it sounds because of key rotation. OpenID Connect working group suggests key rotation every two days, to make sure developers who write OpenID applications handle key rotation properly in their code, and don't hardcode the metadata, but retrieve it from the OpenID configuration endpoint. Customizations : You must copy any libraries, xhtml pages, CSS or javascript must be available on all servers.", "title": "VM Cluster"}, {"location": "janssen-server/planning/vm-single-instance/", "tags": ["administration", "planning", "vm", "single instance"], "text": "While an active-active cluster enables you to achieve four or five nines uptime, you may want to consider a single VM instance if simplicity of operation trumps availability. If you do a good job at monitoring, and can restore from backup quickly, it's certainly possible to meet an SLA of 99.9% availability using just one server. Janssen has Linux packages available for SUSE, Red Hat and Ubuntu. One operational consideration is that you should hold the version of Jans Auth Server, to avoid update during the normal package update process. As many applications may rely on a central IDP, you want to plan updates and have a rollback plan if something goes wrong. An automated, unattended update process for the IDP is too risky. An important security tradeoff when you run Janssen on a single VM is that services which you want to control access to are running on a server with an Internet-facing ethernet interface: the Config API, database, and SCIM server. Even though these services are running on localhost , if the Internet facing interface is compromised, network protection could be bypassed. The main advantage of running a single VM is simplicity. Your sys admins won't need any special training. And it will be easy to install, backup, monitor, and configure your deployment. If you have many autonomous domains, each with its own brand and user identity management process, the simplicity of running a single IDP might be the best solution. If three nines are acceptable to your business, the expense of deploying and operating a cluster may not be justified.", "title": "VM Single Instance"}, {"location": "janssen-server/recipes/ACRouter/", "text": "Janssen's authentication server can integrate with any number of authentication mechanisms from different vendors. Factoring the pros and cons of each method, organizations can offer a diverse set of options. A users can register multiple types of credentials and use any preferred credential to perform a login. An ACRouter Script is a PersonAuthenticationType script orchestrates a 2FA flow by delegating specific implementation details of authentication methods to other scripts. This allows the flow to present users with alternatives in case some credential is not working as expected or is lost. Authentication flow # sequenceDiagram autonumber title User selects authentication mechanism User agent->>Jans AS: Invoke /authorize endpoint Jans AS->>User agent: Present \"username\" only screen <br/> OR <br/>username - password screen User agent->>Jans AS: Present username <br/> OR username and password Jans AS ->> Jans AS: verify user Jans AS->>User agent: Show UI for preferred authentication method, <br>and also a link \"Alternate way to sign in\" loop n times - (enter creds or select alternate way to sign in) User agent->>Jans AS: Enter credentials (Or click on \"Alternate way to sign in\") Jans AS->>User agent: Present page for authentication <br/> or <br/> present alternate authentication mechanisms end Jans AS->Jans AS: 8. validate id_token,<br/>create internal Jans session opt if new user Jans AS->Jans AS: 9. Dynamic enrollment or registration end Jans AS->User agent: 10. write Jans session cookie An ACRouter script : # Currently, the Jans Auth server comes with 2 PersonAuthenticationType interception scripts that integrate multiple authentication methods and offer alternative options to users for sign-in. Casa Script The casa script offers a 2 steps authentication flow with login and password prompted in the first step and a user-preferred authentication mechanism in the second step. Passwordless script The passwordless script offers a 2 steps authentication flow with username prompted in the first step and a user-preferred authentication mechanism in the second step. Casa App for enrollment of a variety of credentials: # Casa is a self-service web portal for end-users can be used to 1. Enroll, delete and manage two-factor authentication (2FA) credentials for their account (e.g. FIDO security keys, mobile apps, phone numbers, etc.) 1. Turn 2FA on and off Adding a new authentication method as an \"alternative authentication method\": # Step 1: Write a custom script: # Ensure the following preconditions are met so that the authentication mehtod integrates seamlessly within flow: 1. The orchestrator script looks for authentication method scripts under /opt/jans/python/libs . Write a custom script that focuses only on authentication. The script file name should follow naming convention like orchestratorName-external_acrName e.g. casa-external_fido2 or pwdless-external_fido2 1. For step 1, prepareForStep must only return True 1. For step 1, getExtraParametersForStep must only return None 1. For step 1, the authenticate routine must check if there is already an authenticated user, and if so bypass validating the username and password. This is because a user may have previously attempted authentication with a different method. 1. Keep in mind that getPageForStep won't be called when step=1 in your script. The orchestrator script i.e. casa or passwordless script takes charge of this specific step/method combination 1. Add a hasEnrollments routine with a signature like this def hasEnrollments(self, configurationAttributes, user): hasEnrollments must return True or False , describing whether user has one or more credentials enrolled for the type you are interested in Objects: Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference User User object Reference Step2: Modification to web-pages: # Ensure that custom pages returned by getPageForStep for step 2 (or higher) contain the fragment: <ui:include src=\"/casa/casa.xhtml\" /> This will display a set of links for the user to navigate to alternate 2FA pages. The list will be shown when clicking on a link which should be provided this way: <a href=\"javascript:showAlternative('ELEMENT_ID')\" id=\"alter_link\" class=\"green hover-green f7-cust\">#{msgs['casa.alternative']}</a> Here ELEMENT_ID is the identifier for the HTML node that wraps all visual elements of your page (excluding casa.xhtml ). It is required to preserve alter_link as id for the a tag. Place the modified xhtml page under the path specified in getPageForStep , for e.g. /opt/jans/jetty/jans-auth/custom/pages/casa/fido2.xhtml Step3: Handle enrollment using the Casa app # Step 4: Enable the ACRouter script i.e. passwordless or casa script # Once your script is enabled in the Jans-auth server, you can test it for authentication purposes. Try your script by creating an authentication request passing casa or passwordless as acr value.", "title": "User Journeys"}, {"location": "janssen-server/recipes/ACRouter/#authentication-flow", "text": "sequenceDiagram autonumber title User selects authentication mechanism User agent->>Jans AS: Invoke /authorize endpoint Jans AS->>User agent: Present \"username\" only screen <br/> OR <br/>username - password screen User agent->>Jans AS: Present username <br/> OR username and password Jans AS ->> Jans AS: verify user Jans AS->>User agent: Show UI for preferred authentication method, <br>and also a link \"Alternate way to sign in\" loop n times - (enter creds or select alternate way to sign in) User agent->>Jans AS: Enter credentials (Or click on \"Alternate way to sign in\") Jans AS->>User agent: Present page for authentication <br/> or <br/> present alternate authentication mechanisms end Jans AS->Jans AS: 8. validate id_token,<br/>create internal Jans session opt if new user Jans AS->Jans AS: 9. Dynamic enrollment or registration end Jans AS->User agent: 10. write Jans session cookie", "title": "Authentication flow"}, {"location": "janssen-server/recipes/ACRouter/#an-acrouter-script", "text": "Currently, the Jans Auth server comes with 2 PersonAuthenticationType interception scripts that integrate multiple authentication methods and offer alternative options to users for sign-in. Casa Script The casa script offers a 2 steps authentication flow with login and password prompted in the first step and a user-preferred authentication mechanism in the second step. Passwordless script The passwordless script offers a 2 steps authentication flow with username prompted in the first step and a user-preferred authentication mechanism in the second step.", "title": "An ACRouter script:"}, {"location": "janssen-server/recipes/ACRouter/#casa-app-for-enrollment-of-a-variety-of-credentials", "text": "Casa is a self-service web portal for end-users can be used to 1. Enroll, delete and manage two-factor authentication (2FA) credentials for their account (e.g. FIDO security keys, mobile apps, phone numbers, etc.) 1. Turn 2FA on and off", "title": "Casa App for enrollment of a variety of credentials:"}, {"location": "janssen-server/recipes/ACRouter/#adding-a-new-authentication-method-as-an-alternative-authentication-method", "text": "", "title": "Adding a new authentication method as an \"alternative authentication method\":"}, {"location": "janssen-server/recipes/ACRouter/#step-1-write-a-custom-script", "text": "Ensure the following preconditions are met so that the authentication mehtod integrates seamlessly within flow: 1. The orchestrator script looks for authentication method scripts under /opt/jans/python/libs . Write a custom script that focuses only on authentication. The script file name should follow naming convention like orchestratorName-external_acrName e.g. casa-external_fido2 or pwdless-external_fido2 1. For step 1, prepareForStep must only return True 1. For step 1, getExtraParametersForStep must only return None 1. For step 1, the authenticate routine must check if there is already an authenticated user, and if so bypass validating the username and password. This is because a user may have previously attempted authentication with a different method. 1. Keep in mind that getPageForStep won't be called when step=1 in your script. The orchestrator script i.e. casa or passwordless script takes charge of this specific step/method combination 1. Add a hasEnrollments routine with a signature like this def hasEnrollments(self, configurationAttributes, user): hasEnrollments must return True or False , describing whether user has one or more credentials enrolled for the type you are interested in Objects: Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference User User object Reference", "title": "Step 1: Write a custom script:"}, {"location": "janssen-server/recipes/ACRouter/#step2-modification-to-web-pages", "text": "Ensure that custom pages returned by getPageForStep for step 2 (or higher) contain the fragment: <ui:include src=\"/casa/casa.xhtml\" /> This will display a set of links for the user to navigate to alternate 2FA pages. The list will be shown when clicking on a link which should be provided this way: <a href=\"javascript:showAlternative('ELEMENT_ID')\" id=\"alter_link\" class=\"green hover-green f7-cust\">#{msgs['casa.alternative']}</a> Here ELEMENT_ID is the identifier for the HTML node that wraps all visual elements of your page (excluding casa.xhtml ). It is required to preserve alter_link as id for the a tag. Place the modified xhtml page under the path specified in getPageForStep , for e.g. /opt/jans/jetty/jans-auth/custom/pages/casa/fido2.xhtml", "title": "Step2: Modification to web-pages:"}, {"location": "janssen-server/recipes/ACRouter/#step3-handle-enrollment-using-the-casa-app", "text": "", "title": "Step3: Handle enrollment using the Casa app"}, {"location": "janssen-server/recipes/ACRouter/#step-4-enable-the-acrouter-script-ie-passwordless-or-casa-script", "text": "Once your script is enabled in the Jans-auth server, you can test it for authentication purposes. Try your script by creating an authentication request passing casa or passwordless as acr value.", "title": "Step 4: Enable the ACRouter script i.e. passwordless or casa script"}, {"location": "janssen-server/recipes/benchmark/", "tags": ["administration", "helm", "kubernetes", "benchmarking"], "text": "Overview # The Janssen Server has been optimized with several container strategies that allow scaling microservices and orchestrating them using Kubernetes. In this tutorial we will be running a load test from three different regions on a janssen setup on three different regions. For simplicity, we will be using microk8s however we do recommend users to use the kubernetes cluster providers that they will be using in production. For instance, we run our loadtests across EKS, GKE, AKS and DOKS. With this procedure the following with a 10 million user database is expected: Results # Note The authorization code flow hits a total of 4 steps, 3 authorization steps /token , /authorize , /jans-auth/login and 1 redirect. Flow Authentications per second Authorization code flow 800-1000 Installation # As mentioned in the overview we recommend using the same Kubernetes cluster as planned in production. More guides to install on different clouds can be found here . Persistence # We recommend your persistence in production to be HA, backup supported and point in time recovery supported. Below is a table of the persistence used and resources set for this test. Persistence # of nodes RAM(GiB) vCPU Total RAM (GiB) Total vCPU MySQL 1 52 8 52 8 Set up the cluster # Kubernetes Cluster Load Test Resources # Note Instance type can be selected to best suit the deployment intended. Keep in mind when selecting the instance type to strive for a 10 or up to 10 network bandwidth (Gbps). Below details the exact resources needed for this tutorial. This is in addition to the persistence resources listed above. Resourcing is critical as timeouts in connections can occur, resulting in failed authentications or cutoffs. Regions # of nodes RAM(GiB) vCPU Total RAM (GiB) Total vCPU US-West 1 96 48 96 48 US-East 1 96 48 96 48 EU-Central 1 96 48 96 48 Grand Total 288 GB 144 A Kubernetes cluster can be created with three nodes or more in one region and that's fine as long as the nodes are in multiple zones. We will continue with the above table and using microk8s . Create three ubuntu 22.04 nodes and run on each one the following: sudo snap install microk8s --classic sudo snap alias microk8s.kubectl kubectl 2. Designate one of the nodes as the master. We will choose the us-west node to be our master. On the master node run: Execute : microk8s.enable ingress dashboard observability dns metrics-server hostpath-storage registry All the other microk8s nodes must be resolvable from within the master. If fqdns are not globally resolved (registered) open the /etc/hosts file in the master node and map each hostname of the other nodes. YThe hostname of the other nodes can be obtained by executing the command hostname . # If the hostnames are not globally resolvable on master echo \"192.123.123.123 ubuntu-us-east\" >> /etc/hosts echo \"192.124.124.124 ubuntu-eu-central\" >> /etc/hosts 3. Execute: microk8s add-node Copy the output of the command above with --worker i.e. microk8s join 192.12.12.12:25000/88687d1cc5ecdee0db5014c4df9b82cb/adedf6a730eb --worker and execute it in the other nodes (worker nodes) to join them. Step iii ( this step) needs to be repeated for each worker node. Make sure helm is installed. Prepare your override.yaml . Copy the below into a file named override.yaml. At the time of writing this we are using image tags replace-janssen-version_dev which are the bleeding edge images for release replace-janssen-version . Stable images such as replace-janssen-version-1 should be used. config : image : repository : ghcr.io/janssenproject/jans/configurator tag : replace-janssen-version_dev countryCode : US email : support@gluu.org orgName : Gluu city : Austin configmap : cnSqlDbName : test cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : mycool.cloud.mysql cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# global : auth-server : enabled : true config-api : enabled : true cnPersistenceType : sql cloud : testEnviroment : false fqdn : example.gluu.info isFqdnRegistered : true # In the event the fqdn above is not resolvable from the internet comment the above line and uncomment the below two setting your lbIp to your master ndoe ip. #isFqdnRegistered: false #lbIp: 192.12.12.12 istio : enabled : false ingress : false nginx-ingress : enabled : true fido2 : enabled : false ingress : fido2ConfigEnabled : false scim : enabled : false ingress : scimConfigEnabled : false scimEnabled : false auth-server : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/auth-server tag : replace-janssen-version_dev config-api : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/config-api tag : replace-janssen-version_dev persistence : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/persistence-loader tag : replace-janssen-version_dev nginx-ingress : ingress : path : / hosts : - example.gluu.info tls : - secretName : tls-certificate hosts : - example.gluu.info Run the following: kubectl create ns jans helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml Load-test # Our tests used 10 million users that were loaded. We have created a docker image to load users. That same image is also used to load test Janssen using jmeter tests for the Authorization code flow. More tests will come!. This image will load users and use a unique password for each user. Loading users # Loading users requires a hefty but temporary amount of resources. By default, the resources ask for 10 vCPU and 5 Gis. However, to speed up the process increase the number of CPUs as the job in step two below uses parallel tasks. If left as is 10 million users would load in around 17 hours or so. Create a folder called add_users . mkdir -p add_users && cd add_users Copy the following yaml into the folder under the name load_users.yaml . Open the file and modify the required parameters. Note that the following environments can be used as configmaps data to configure the pod. ENV Description Default TEST_USERS_PREFIX_STRING The user prefix string attached to the test users loaded test_user USER_NUMBER_STARTING_POINT The user number to start from . This is appended to the username i.e test_user0 0 USER_NUMBER_ENDING_POINT The user number to end at. 50000000 LOAD_USERS_TO_RDBMS Enable loading users to RDBMS persistence. true or false == `` false USER_SPLIT_PARALLEL_THREADS The number of parallel threads to break the total number users across. This number heavily effects vCPU usage. 20 RDBMS_TYPE RDBMS type if mysql or pgsql is the persistence to load users in. mysql RDBMS_DB RDBMS Database name if mysql or pgsql is the persistence to load users in. jans RDBMS_USER RDBMS user if mysql or pgsql is the persistence to load users in. jans RDBMS_PASSWORD RDBMS user password if mysql or pgsql is the persistence to load users in. . `` RDBMS_HOST RDBMS host if mysql or pgsql is the persistence to load users in. localhost Tips: To speed the loading process, increase the vCPU requests and limits of the pod. Create a namespace for load-testing. kubectl create ns load Create load_users.yaml kubectl create -f load_users.yaml -n load cd .. Wait until all the users are up before moving forward. Tail the logs by running kubectl logs deployment/load-users -n load . Load testing # Authorization code flow # Resources needed for Authorization code client jmeter test # The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU Authorization code flow jmeter test 20 8 1.3 190 24 Grand Total 190 GiB 24 Setup Client # Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > auth_code_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"Auth Code Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"Auth Code Flow Load Testing Client\" } EOF 3. Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = auth_code_client.json Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_auth_code.yaml under AUTHZ_CLIENT_ID , AUTHZ_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_auth_code.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-authz -n load --replicas=20 Resource Owner Password Credentials (ROPC) flow # Resources needed for ROPC client jmeter test # The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU ROPC flow jmeter test 20 8 1.3 190 24 Grand Total 190 GiB 24 Setup Client # Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > ropc_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"ROPC Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\", \"password\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"ROPC Flow Load Testing Client\" } EOF Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = ropc_client.json Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_ropc.yaml under ROPC_CLIENT_ID , ROPC_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_ropc.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-ropc -n load --replicas=20 DCR flow # Resources needed for DCR client jmeter test # The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU DCR test 20 8 1.3 190 24 Grand Total 190 GiB 24 Setup Client # Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > dcr_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"DCR Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\", \"password\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"DCR Flow Load Testing Client\" } EOF Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = dcr_client.json You will need to load the sectorIdentifier into your persistence.For MySQL that statement would be the following taking into account the FQDN : INSERT INTO jansSectorIdentifier ( doc_id , dn , jansId , jansRedirectURI , objectClass ) VALUES ( 'a55ede29-8f5a-461d-b06e-76caee8d40b5' , 'jansId=a55ede29-8f5a-461d-b06e-76caee8d40b5,ou=sector_identifiers,o=jans' , 'a55ede29-8f5a-461d-b06e-76caee8d40b5' , '{\"v\": [\"https://www.jans.org\", \"http://localhost:80/jans-auth-rp/home.htm\", \"https://localhost:8443/jans-auth-rp/home.htm\", \"https://$FQDN/jans-auth-rp/home.htm\", \"https://$FQDN/jans-auth-client/test/resources/jwks.json\", \"https://client.example.org/callback\", \"https://client.example.org/callback2\", \"https://client.other_company.example.net/callback\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\"]}' , 'jansSectorIdentifier' ); Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_ropc.yaml under DCR_CLIENT_ID , DCR_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_dcr.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-ropc -n load --replicas=20", "title": "Benchmark"}, {"location": "janssen-server/recipes/benchmark/#overview", "text": "The Janssen Server has been optimized with several container strategies that allow scaling microservices and orchestrating them using Kubernetes. In this tutorial we will be running a load test from three different regions on a janssen setup on three different regions. For simplicity, we will be using microk8s however we do recommend users to use the kubernetes cluster providers that they will be using in production. For instance, we run our loadtests across EKS, GKE, AKS and DOKS. With this procedure the following with a 10 million user database is expected:", "title": "Overview"}, {"location": "janssen-server/recipes/benchmark/#results", "text": "Note The authorization code flow hits a total of 4 steps, 3 authorization steps /token , /authorize , /jans-auth/login and 1 redirect. Flow Authentications per second Authorization code flow 800-1000", "title": "Results"}, {"location": "janssen-server/recipes/benchmark/#installation", "text": "As mentioned in the overview we recommend using the same Kubernetes cluster as planned in production. More guides to install on different clouds can be found here .", "title": "Installation"}, {"location": "janssen-server/recipes/benchmark/#persistence", "text": "We recommend your persistence in production to be HA, backup supported and point in time recovery supported. Below is a table of the persistence used and resources set for this test. Persistence # of nodes RAM(GiB) vCPU Total RAM (GiB) Total vCPU MySQL 1 52 8 52 8", "title": "Persistence"}, {"location": "janssen-server/recipes/benchmark/#set-up-the-cluster", "text": "", "title": "Set up the cluster"}, {"location": "janssen-server/recipes/benchmark/#kubernetes-cluster-load-test-resources", "text": "Note Instance type can be selected to best suit the deployment intended. Keep in mind when selecting the instance type to strive for a 10 or up to 10 network bandwidth (Gbps). Below details the exact resources needed for this tutorial. This is in addition to the persistence resources listed above. Resourcing is critical as timeouts in connections can occur, resulting in failed authentications or cutoffs. Regions # of nodes RAM(GiB) vCPU Total RAM (GiB) Total vCPU US-West 1 96 48 96 48 US-East 1 96 48 96 48 EU-Central 1 96 48 96 48 Grand Total 288 GB 144 A Kubernetes cluster can be created with three nodes or more in one region and that's fine as long as the nodes are in multiple zones. We will continue with the above table and using microk8s . Create three ubuntu 22.04 nodes and run on each one the following: sudo snap install microk8s --classic sudo snap alias microk8s.kubectl kubectl 2. Designate one of the nodes as the master. We will choose the us-west node to be our master. On the master node run: Execute : microk8s.enable ingress dashboard observability dns metrics-server hostpath-storage registry All the other microk8s nodes must be resolvable from within the master. If fqdns are not globally resolved (registered) open the /etc/hosts file in the master node and map each hostname of the other nodes. YThe hostname of the other nodes can be obtained by executing the command hostname . # If the hostnames are not globally resolvable on master echo \"192.123.123.123 ubuntu-us-east\" >> /etc/hosts echo \"192.124.124.124 ubuntu-eu-central\" >> /etc/hosts 3. Execute: microk8s add-node Copy the output of the command above with --worker i.e. microk8s join 192.12.12.12:25000/88687d1cc5ecdee0db5014c4df9b82cb/adedf6a730eb --worker and execute it in the other nodes (worker nodes) to join them. Step iii ( this step) needs to be repeated for each worker node. Make sure helm is installed. Prepare your override.yaml . Copy the below into a file named override.yaml. At the time of writing this we are using image tags replace-janssen-version_dev which are the bleeding edge images for release replace-janssen-version . Stable images such as replace-janssen-version-1 should be used. config : image : repository : ghcr.io/janssenproject/jans/configurator tag : replace-janssen-version_dev countryCode : US email : support@gluu.org orgName : Gluu city : Austin configmap : cnSqlDbName : test cnSqlDbPort : 3306 cnSqlDbDialect : mysql cnSqlDbHost : mycool.cloud.mysql cnSqlDbUser : root cnSqlDbTimezone : UTC cnSqldbUserPassword : Test1234# global : auth-server : enabled : true config-api : enabled : true cnPersistenceType : sql cloud : testEnviroment : false fqdn : example.gluu.info isFqdnRegistered : true # In the event the fqdn above is not resolvable from the internet comment the above line and uncomment the below two setting your lbIp to your master ndoe ip. #isFqdnRegistered: false #lbIp: 192.12.12.12 istio : enabled : false ingress : false nginx-ingress : enabled : true fido2 : enabled : false ingress : fido2ConfigEnabled : false scim : enabled : false ingress : scimConfigEnabled : false scimEnabled : false auth-server : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/auth-server tag : replace-janssen-version_dev config-api : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/config-api tag : replace-janssen-version_dev persistence : image : pullPolicy : IfNotPresent repository : ghcr.io/janssenproject/jans/persistence-loader tag : replace-janssen-version_dev nginx-ingress : ingress : path : / hosts : - example.gluu.info tls : - secretName : tls-certificate hosts : - example.gluu.info Run the following: kubectl create ns jans helm repo add janssen https://docs.jans.io/charts helm repo update helm install janssen janssen/janssen -n jans -f override.yaml", "title": "Kubernetes Cluster Load Test Resources"}, {"location": "janssen-server/recipes/benchmark/#load-test", "text": "Our tests used 10 million users that were loaded. We have created a docker image to load users. That same image is also used to load test Janssen using jmeter tests for the Authorization code flow. More tests will come!. This image will load users and use a unique password for each user.", "title": "Load-test"}, {"location": "janssen-server/recipes/benchmark/#loading-users", "text": "Loading users requires a hefty but temporary amount of resources. By default, the resources ask for 10 vCPU and 5 Gis. However, to speed up the process increase the number of CPUs as the job in step two below uses parallel tasks. If left as is 10 million users would load in around 17 hours or so. Create a folder called add_users . mkdir -p add_users && cd add_users Copy the following yaml into the folder under the name load_users.yaml . Open the file and modify the required parameters. Note that the following environments can be used as configmaps data to configure the pod. ENV Description Default TEST_USERS_PREFIX_STRING The user prefix string attached to the test users loaded test_user USER_NUMBER_STARTING_POINT The user number to start from . This is appended to the username i.e test_user0 0 USER_NUMBER_ENDING_POINT The user number to end at. 50000000 LOAD_USERS_TO_RDBMS Enable loading users to RDBMS persistence. true or false == `` false USER_SPLIT_PARALLEL_THREADS The number of parallel threads to break the total number users across. This number heavily effects vCPU usage. 20 RDBMS_TYPE RDBMS type if mysql or pgsql is the persistence to load users in. mysql RDBMS_DB RDBMS Database name if mysql or pgsql is the persistence to load users in. jans RDBMS_USER RDBMS user if mysql or pgsql is the persistence to load users in. jans RDBMS_PASSWORD RDBMS user password if mysql or pgsql is the persistence to load users in. . `` RDBMS_HOST RDBMS host if mysql or pgsql is the persistence to load users in. localhost Tips: To speed the loading process, increase the vCPU requests and limits of the pod. Create a namespace for load-testing. kubectl create ns load Create load_users.yaml kubectl create -f load_users.yaml -n load cd .. Wait until all the users are up before moving forward. Tail the logs by running kubectl logs deployment/load-users -n load .", "title": "Loading users"}, {"location": "janssen-server/recipes/benchmark/#load-testing", "text": "", "title": "Load testing"}, {"location": "janssen-server/recipes/benchmark/#authorization-code-flow", "text": "", "title": "Authorization code flow"}, {"location": "janssen-server/recipes/benchmark/#resources-needed-for-authorization-code-client-jmeter-test", "text": "The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU Authorization code flow jmeter test 20 8 1.3 190 24 Grand Total 190 GiB 24", "title": "Resources needed for Authorization code client jmeter test"}, {"location": "janssen-server/recipes/benchmark/#setup-client", "text": "Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > auth_code_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"Auth Code Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"Auth Code Flow Load Testing Client\" } EOF 3. Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = auth_code_client.json Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_auth_code.yaml under AUTHZ_CLIENT_ID , AUTHZ_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_auth_code.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-authz -n load --replicas=20", "title": "Setup Client"}, {"location": "janssen-server/recipes/benchmark/#resource-owner-password-credentials-ropc-flow", "text": "", "title": "Resource Owner Password Credentials (ROPC) flow"}, {"location": "janssen-server/recipes/benchmark/#resources-needed-for-ropc-client-jmeter-test", "text": "The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU ROPC flow jmeter test 20 8 1.3 190 24 Grand Total 190 GiB 24", "title": "Resources needed for ROPC client jmeter test"}, {"location": "janssen-server/recipes/benchmark/#setup-client_1", "text": "Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > ropc_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"ROPC Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\", \"password\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"ROPC Flow Load Testing Client\" } EOF Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = ropc_client.json Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_ropc.yaml under ROPC_CLIENT_ID , ROPC_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_ropc.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-ropc -n load --replicas=20", "title": "Setup Client"}, {"location": "janssen-server/recipes/benchmark/#dcr-flow", "text": "", "title": "DCR flow"}, {"location": "janssen-server/recipes/benchmark/#resources-needed-for-dcr-client-jmeter-test", "text": "The below resources were calculated when creating the nodes above. NAME # of pods RAM(GiB) vCPU Total RAM(GiB) Total vCPU DCR test 20 8 1.3 190 24 Grand Total 190 GiB 24", "title": "Resources needed for DCR client jmeter test"}, {"location": "janssen-server/recipes/benchmark/#setup-client_2", "text": "Create the client needed to run the test by executing the following. Make sure to change the FQDN : Create a folder called load_test . mkdir -p load_test && cd load_test Create the client json file FQDN = example.gluu.info cat << EOF > dcr_client.json { \"dn\": null, \"inum\": null, \"displayName\": \"DCR Flow Load Test Client\", \"redirectUris\": [ \"https://$FQDN\" ], \"responseTypes\": [ \"id_token\", \"code\" ], \"grantTypes\": [ \"authorization_code\", \"implicit\", \"refresh_token\", \"password\" ], \"tokenEndpointAuthMethod\": \"client_secret_basic\", \"scopes\": [ \"openid\", \"profile\", \"email\", \"user_name\" ], \"trustedClient\": true, \"includeClaimsInIdToken\": false, \"accessTokenAsJwt\": false, \"disabled\": false, \"deletable\": false, \"description\": \"DCR Flow Load Testing Client\" } EOF Copy the following yaml into the folder. Download or build config-cli-tui and run: # Notice the namespace is jans here . Change it if it was changed during installation of janssen previously TUI_CLIENT_ID = $( kubectl get cm cn -o json -n jans | grep '\"tui_client_id\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' ) TUI_CLIENT_SECRET = $( kubectl get secret cn -o json -n jans | grep '\"tui_client_pw\":' | sed -e 's#.*:\\(\\)#\\1#' | tr -d '\"' | tr -d \",\" | tr -d '[:space:]' | base64 -d ) # add -noverify if your fqdn is not registered ./config-cli-tui.pyz --host $FQDN --client-id $TUI_CLIENT_ID --client-secret $TUI_CLIENT_SECRET --no-tui --operation-id = post-oauth-openid-client --data = dcr_client.json You will need to load the sectorIdentifier into your persistence.For MySQL that statement would be the following taking into account the FQDN : INSERT INTO jansSectorIdentifier ( doc_id , dn , jansId , jansRedirectURI , objectClass ) VALUES ( 'a55ede29-8f5a-461d-b06e-76caee8d40b5' , 'jansId=a55ede29-8f5a-461d-b06e-76caee8d40b5,ou=sector_identifiers,o=jans' , 'a55ede29-8f5a-461d-b06e-76caee8d40b5' , '{\"v\": [\"https://www.jans.org\", \"http://localhost:80/jans-auth-rp/home.htm\", \"https://localhost:8443/jans-auth-rp/home.htm\", \"https://$FQDN/jans-auth-rp/home.htm\", \"https://$FQDN/jans-auth-client/test/resources/jwks.json\", \"https://client.example.org/callback\", \"https://client.example.org/callback2\", \"https://client.other_company.example.net/callback\", \"https://client.example.com/cb\", \"https://client.example.com/cb1\", \"https://client.example.com/cb2\"]}' , 'jansSectorIdentifier' ); Save the client id and secret from the response and enter them along with your FQDN in the yaml file load_test_ropc.yaml under DCR_CLIENT_ID , DCR_CLIENT_SECRET and FQDN respectively then execute : kubectl apply -f load_test_dcr.yaml The janssen setup by default installs an HPA which will automatically scale your pods if the metrics server is installed according to traffic. To load it very quickly scale the auth-server manually: bash kubectl scale deploy janssen-auth-server -n jans --replicas=40 Finally, scale the load test. The replica number here should be manually controlled. bash kubectl scale deploy load-testing-ropc -n load --replicas=20", "title": "Setup Client"}, {"location": "janssen-server/recipes/device-flow-config/", "tags": ["administration", "recipes", "device flow"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Authentication via Device Flow"}, {"location": "janssen-server/recipes/device-flow-config/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/recipes/device-flow-config/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/recipes/device-flow-config/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/recipes/inbound-oidc/", "tags": ["administration", "recipe", "openid-connect", "inbound", "authentication"], "text": "Inbound OpenId-Connect Authentication # In this tutorial, we will see how you can integrate any inbound external oauth2 provider authentication in the Janssen server. If you are looking for social login support then check out passport module for that. We will use interception authentication script which is a PersonAuthenticationType script for whole flow. Currently, It supports Authorization Code Flow and client_secret_post token endpoint auth method. Authentication Flow # You can add any external OAuth2 server authentication option and provision authenticated users to your Janssen server A.K.A. Inbound-identity. sequenceDiagram title OIDC Inbound Identity Flow participant browser as Browser participant rp as RP participant jans as Jans Authz Server participant eidp as External Provider autonumber browser->>rp: Request page browser->>jans: Invoke /authorize endpoint jans->>browser: Present \"Login with OAuth2\" button browser->>browser: User click on button browser->>eidp: Redirect login request loop n times - (multistep authentication) eidp->>browser: Present login screen browser->>eidp: Present login credentials end eidp->>eidp: Authenticate user eidp->>jans: Redirect to callback url with success response(code) jans->>jans: Validate code, id_token, userinfo opt if new user jans->>jans: Dynamic enrollment or registration end jans->>jans: Create internal Jans session jans->>rp: Redirect with Success response rp->>rp: Validate response rp->>browser: Page is accessed Prerequisites # The external oauth2 server authentication script External OAuth2 Provider credentials: you can choose any external OP server that follows OAuth2 standards and authentication features. RP application: This is your application that will be used by your users and where you want to add this auth feature. Configure Janssen server # 1. Add Custom Script # Create cs.json with the contents of a CUSTOM script. Edit the cs.json file's contents to reflect the addition of the oidc custom script. Populate the script field with oidc-jans-script.py script. Download oidc-jans-script.py script from here. This script needs to accept one property oidc_creds_file . which is a JSON file with your external oauth2 server details: // oidc_creds_file: /opt/oidc.json { \"op_server\": \"https://your.external.oauth2.server\", \"client_id\": \"xxxxxxxxxxxxxxxx-xxxxx-external-oauth2\", \"client_secret\": \"xxxxxxxxxxxxxx-xxxxx-external-oauth2\", \"authorization_uri\": \"https://your.external.oauth2.server/xx/xxxx\", \"token_uri\": \"https://your.external.oauth2.server/oauth/xx/xxx\", \"userinfo_uri\": \"https://your.external.oauth2.server/xxx/xxx\", \"redirect_uri\": \"https://your.jans.server/jans-auth/postlogin.htm\", \"scope\": \"openid profile email\", \"auto_redirect\": false, \"title\": \"Login with OAuth2\" } Property Description op_server Your external OAuth2 server FQDN client_id Client id of your external OAuth2 server client_secret Client secret of your external OAuth2 server authorization_uri Authorization endpoint of your external OAuth2 server token_uri Token endpoint of your external OAuth2 server userinfo_uri Userinfo endpoint of your external OAuth2 server redirect_uri Sample: https://<your.jans.server>/jans-auth/postlogin.htm , This is redirect URL where your OAuth2 server redirect back with code . Use this same URL to configure redirect urls at your external OAuth2 server. scope OAuth scopes auto_redirect If true, it will automatically redirect to external OAuth2 server otherwise you will get one button on jans login page. title This property is used to set text for a button which is shown on jans login page name field should reflect the use case i.e. oidc script_type field should be PERSON_AUTHENTICATION cs.json example: { \"dn\": null, \"inum\": null, \"name\": \"oidc\", \"aliases\": [], \"description\": \"OIDC Inbound custom script\", \"script\": \"_file /root/oidc-jans-script.py\", \"scriptType\": \"PERSON_AUTHENTICATION\", \"programmingLanguage\": \"JYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": [ { \"value1\": \"oidc_creds_file\", \"value2\": \"/opt/oidc.json\", \"description\": \"External server details\", \"hide\": true } ], \"level\": \"integer\", \"revision\": 0, \"enabled\": true, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } Add the custom script jans cli --operation-id post-config-scripts --data /tmp/cs.json 2. Login Page Setup # OIDC Script needs a login page Download oidc-jans-login.xhtml from here Place it here /opt/jans/jetty/jans-auth/custom/pages/auth/oidc/ . If folders are not there then create them in the same order. Rename it to oidc.xhtml . Restart jans-auth server service jans-auth restart Check here for more details on custom login page. Now oidc script is an available authentication mechanism for your Janssen Server. This means that using OpenID Connect acr_values , applications can now request your external auth server for authentication. !!! Note To make sure oidc script has been enabled successfully, you can check your Janssen Server's OpenID Connect configuration by navigating to the following URL: https://<hostname>/.well-known/openid-configuration . Find acr_values_supported: and you should see oidc . Test with RP Client # RP(Relying party) is an application that will be used by your users when you want to add authentication and protect resources. Once you initiate auth request from your RP Application make sure to add acr_values=oidc in the request. acr_values is your script name as configured above.", "title": "Inbound OIDC"}, {"location": "janssen-server/recipes/inbound-oidc/#inbound-openid-connect-authentication", "text": "In this tutorial, we will see how you can integrate any inbound external oauth2 provider authentication in the Janssen server. If you are looking for social login support then check out passport module for that. We will use interception authentication script which is a PersonAuthenticationType script for whole flow. Currently, It supports Authorization Code Flow and client_secret_post token endpoint auth method.", "title": "Inbound OpenId-Connect Authentication"}, {"location": "janssen-server/recipes/inbound-oidc/#authentication-flow", "text": "You can add any external OAuth2 server authentication option and provision authenticated users to your Janssen server A.K.A. Inbound-identity. sequenceDiagram title OIDC Inbound Identity Flow participant browser as Browser participant rp as RP participant jans as Jans Authz Server participant eidp as External Provider autonumber browser->>rp: Request page browser->>jans: Invoke /authorize endpoint jans->>browser: Present \"Login with OAuth2\" button browser->>browser: User click on button browser->>eidp: Redirect login request loop n times - (multistep authentication) eidp->>browser: Present login screen browser->>eidp: Present login credentials end eidp->>eidp: Authenticate user eidp->>jans: Redirect to callback url with success response(code) jans->>jans: Validate code, id_token, userinfo opt if new user jans->>jans: Dynamic enrollment or registration end jans->>jans: Create internal Jans session jans->>rp: Redirect with Success response rp->>rp: Validate response rp->>browser: Page is accessed", "title": "Authentication Flow"}, {"location": "janssen-server/recipes/inbound-oidc/#prerequisites", "text": "The external oauth2 server authentication script External OAuth2 Provider credentials: you can choose any external OP server that follows OAuth2 standards and authentication features. RP application: This is your application that will be used by your users and where you want to add this auth feature.", "title": "Prerequisites"}, {"location": "janssen-server/recipes/inbound-oidc/#configure-janssen-server", "text": "", "title": "Configure Janssen server"}, {"location": "janssen-server/recipes/inbound-oidc/#1-add-custom-script", "text": "Create cs.json with the contents of a CUSTOM script. Edit the cs.json file's contents to reflect the addition of the oidc custom script. Populate the script field with oidc-jans-script.py script. Download oidc-jans-script.py script from here. This script needs to accept one property oidc_creds_file . which is a JSON file with your external oauth2 server details: // oidc_creds_file: /opt/oidc.json { \"op_server\": \"https://your.external.oauth2.server\", \"client_id\": \"xxxxxxxxxxxxxxxx-xxxxx-external-oauth2\", \"client_secret\": \"xxxxxxxxxxxxxx-xxxxx-external-oauth2\", \"authorization_uri\": \"https://your.external.oauth2.server/xx/xxxx\", \"token_uri\": \"https://your.external.oauth2.server/oauth/xx/xxx\", \"userinfo_uri\": \"https://your.external.oauth2.server/xxx/xxx\", \"redirect_uri\": \"https://your.jans.server/jans-auth/postlogin.htm\", \"scope\": \"openid profile email\", \"auto_redirect\": false, \"title\": \"Login with OAuth2\" } Property Description op_server Your external OAuth2 server FQDN client_id Client id of your external OAuth2 server client_secret Client secret of your external OAuth2 server authorization_uri Authorization endpoint of your external OAuth2 server token_uri Token endpoint of your external OAuth2 server userinfo_uri Userinfo endpoint of your external OAuth2 server redirect_uri Sample: https://<your.jans.server>/jans-auth/postlogin.htm , This is redirect URL where your OAuth2 server redirect back with code . Use this same URL to configure redirect urls at your external OAuth2 server. scope OAuth scopes auto_redirect If true, it will automatically redirect to external OAuth2 server otherwise you will get one button on jans login page. title This property is used to set text for a button which is shown on jans login page name field should reflect the use case i.e. oidc script_type field should be PERSON_AUTHENTICATION cs.json example: { \"dn\": null, \"inum\": null, \"name\": \"oidc\", \"aliases\": [], \"description\": \"OIDC Inbound custom script\", \"script\": \"_file /root/oidc-jans-script.py\", \"scriptType\": \"PERSON_AUTHENTICATION\", \"programmingLanguage\": \"JYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": [ { \"value1\": \"oidc_creds_file\", \"value2\": \"/opt/oidc.json\", \"description\": \"External server details\", \"hide\": true } ], \"level\": \"integer\", \"revision\": 0, \"enabled\": true, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } Add the custom script jans cli --operation-id post-config-scripts --data /tmp/cs.json", "title": "1. Add Custom Script"}, {"location": "janssen-server/recipes/inbound-oidc/#2-login-page-setup", "text": "OIDC Script needs a login page Download oidc-jans-login.xhtml from here Place it here /opt/jans/jetty/jans-auth/custom/pages/auth/oidc/ . If folders are not there then create them in the same order. Rename it to oidc.xhtml . Restart jans-auth server service jans-auth restart Check here for more details on custom login page. Now oidc script is an available authentication mechanism for your Janssen Server. This means that using OpenID Connect acr_values , applications can now request your external auth server for authentication. !!! Note To make sure oidc script has been enabled successfully, you can check your Janssen Server's OpenID Connect configuration by navigating to the following URL: https://<hostname>/.well-known/openid-configuration . Find acr_values_supported: and you should see oidc .", "title": "2. Login Page Setup"}, {"location": "janssen-server/recipes/inbound-oidc/#test-with-rp-client", "text": "RP(Relying party) is an application that will be used by your users when you want to add authentication and protect resources. Once you initiate auth request from your RP Application make sure to add acr_values=oidc in the request. acr_values is your script name as configured above.", "title": "Test with RP Client"}, {"location": "janssen-server/recipes/locking-accounts/", "tags": ["administration", "recipes"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Locking or Disabling Accounts"}, {"location": "janssen-server/recipes/locking-accounts/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/recipes/locking-accounts/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/recipes/locking-accounts/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/recipes/password-expirations/", "tags": ["administration", "recipes"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Password Expirations"}, {"location": "janssen-server/recipes/password-expirations/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/recipes/password-expirations/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/recipes/password-expirations/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/recipes/registration/", "tags": ["administration", "recipes"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Registration"}, {"location": "janssen-server/recipes/registration/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/recipes/registration/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/recipes/registration/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/recipes/social-login/", "tags": ["administration", "Social login", "Google", "Apple", "Facebook"], "text": "Implementing Social logins # You can use a PersonAuthenticationType script to allow users to sign using credentials from popular Social Identity providers or Inbound Identity Providers like Facebook, Google and Apple. After users authenticate, we provision their Social Identity Provider credentials into the Jans-auth server. No additional username, password, credentials are needed for this user. Facebook Google Apple Following is a high-level diagram depicting a typical flow - user authentication on a Social Identity Platform and subsequent user provisioning on Jans-Auth server. You can copy paste this sequence in https://sequencediagram.org/ title Social login Jans AS<-User agent: 1. Invoke /authorize endpoint Jans AS->User agent: 2. Discovery: Present list of remote IDPs (Google, Apple, FB...) User agent->Jans AS: 3. Select IDP (e.g. click on button) Jans AS->Social login Identity Provider: 4. Redirects login request to IDP loop n times - (multistep authentication) Social login Identity Provider->User agent: 5. present login screen User agent->Social login Identity Provider: 6. present credentials end Social login Identity Provider->Jans AS: 7. return id_token, user claims Jans AS->Jans AS: 8. validate id_token,\\ncreate internal Jans session opt if new user Jans AS->Jans AS: 9. Dynamic enrollment or registration end Jans AS->User agent: 10. write Jans session cookie User provisioning # After a user has logged in at an external provider a new record is added in local database - or updated if the user is known. To determine if a user was already added, a string is composed with the provider name and the user ID. For example, if user \"MrBrown123\" has logged in at Twitter, the string would look like passport-twitter:mrbrown123 . A database search is performed for a match in the people branch for an entry where attribute jansExtUid equals passport-twitter:mrbrown123 . If there are no matches, an entry is added using the values received from the external provider (after having applied the corresponding attribute mapping) attaching the computed value for jansExtUid . The user profile can contain single or multivalued attributes. \ud83d\udcdd The prefix passport-<provider-name> is used to keep the code compatible with the Passport.js implementation for Inbound Identity", "title": "Social Login"}, {"location": "janssen-server/recipes/social-login/#implementing-social-logins", "text": "You can use a PersonAuthenticationType script to allow users to sign using credentials from popular Social Identity providers or Inbound Identity Providers like Facebook, Google and Apple. After users authenticate, we provision their Social Identity Provider credentials into the Jans-auth server. No additional username, password, credentials are needed for this user. Facebook Google Apple Following is a high-level diagram depicting a typical flow - user authentication on a Social Identity Platform and subsequent user provisioning on Jans-Auth server. You can copy paste this sequence in https://sequencediagram.org/ title Social login Jans AS<-User agent: 1. Invoke /authorize endpoint Jans AS->User agent: 2. Discovery: Present list of remote IDPs (Google, Apple, FB...) User agent->Jans AS: 3. Select IDP (e.g. click on button) Jans AS->Social login Identity Provider: 4. Redirects login request to IDP loop n times - (multistep authentication) Social login Identity Provider->User agent: 5. present login screen User agent->Social login Identity Provider: 6. present credentials end Social login Identity Provider->Jans AS: 7. return id_token, user claims Jans AS->Jans AS: 8. validate id_token,\\ncreate internal Jans session opt if new user Jans AS->Jans AS: 9. Dynamic enrollment or registration end Jans AS->User agent: 10. write Jans session cookie", "title": "Implementing Social logins"}, {"location": "janssen-server/recipes/social-login/#user-provisioning", "text": "After a user has logged in at an external provider a new record is added in local database - or updated if the user is known. To determine if a user was already added, a string is composed with the provider name and the user ID. For example, if user \"MrBrown123\" has logged in at Twitter, the string would look like passport-twitter:mrbrown123 . A database search is performed for a match in the people branch for an entry where attribute jansExtUid equals passport-twitter:mrbrown123 . If there are no matches, an entry is added using the values received from the external provider (after having applied the corresponding attribute mapping) attaching the computed value for jansExtUid . The user profile can contain single or multivalued attributes. \ud83d\udcdd The prefix passport-<provider-name> is used to keep the code compatible with the Passport.js implementation for Inbound Identity", "title": "User provisioning"}, {"location": "janssen-server/recipes/stepped-up-authn/", "text": "tags: - administration - recipes - stepped-up authentication - Update token - modify access token - scope What is Stepped Up Authentication ? # While navigating through an application, a user is challenged to produce an additional authentication when a certain API (of higher criticality) accessed by the client, does not have the needed scope. Consider the following sequence of events : 1. A user is logged in to an app using very basic authentication mechanism. Say login- password. 2. The user navigates through the app. 3. When the user attempts to access a critical resource, he is presented with another authentication step say otp. 4. The user, after successful authentication, has the needed access token to access the critical resource. sequenceDiagram title Stepped-up Authentication actor Person participant Browser participant Website participant Auth Server participant API autonumber Website->>API: request some endpoint API->>API: Enforce<br> presence of <br> 'otp' scope<br> in access_token API->>Website: 3. 401 Unauthorized<br>WWW-Authenticate: Bearer error=\"insufficient_user_authentication\" Website->>Browser: Enforce additional challenge on the user<br> (Enter OTP) Person->>Browser:Enter OTP Browser->>Auth Server: /authorize endpoint Note right of Auth Server: Stepped-up Authentication Auth Server->>Auth Server:Validate OTP (Person authentication script) Note right of Auth Server: Modify scope of AT Auth Server->>Auth Server: Modify scope of AT to include OTP (Update token script) Auth Server->> Website: Return Access Token with scope containing OTP Implementation details : # This implementation has been broken down to 5 parts highlighted in different colours. The details contain sample code that can be used to be build the flow using Person Authentication Scripts and Update Token Scripts sequenceDiagram title Implementation Stepped-up authn in Janssen's Authentication server actor Person participant Browser participant Website participant Auth Server participant API autonumber rect rgb(255, 223, 211) Website->>Browser: html login form Person->>Browser: Update PII Browser->>Website: POST Website->>Auth Server: login request /authorize?response_type=code id_token Auth Server->> Auth Server: UpdateTokenScript - place user info in id_token <br>e.g. encrypted inum Auth Server ->>Website: return id_token and code end rect rgb(211,211,211) Website->> Website: Extract the user info from id_token and save in website's session (not to be confused with Auth Server session) end rect rgb(212, 238, 227) Website->>API: request some endpoint API->>API: Enforce<br> presence of <br> 'otp' scope<br> in access_token API->>Website: 401 Unauthorized<br>WWW-Authenticate: <br>Bearer error=\"insufficient_user_authentication\" Website->>Browser: redirect to AS end rect rgb(186,225,255) Browser->>Auth Server: authorize?acr_values=otp<br>&client_id=1234<br>&scope=otp + other scopes<br>&response_type=code<br>&client_id=____<br>&redirect_uri=____<br>&state=_____<br>&nonce=____<br>&prompt=login&<br>login_hint=encrypted_inum Auth Server->>Auth Server: Get encrypted user inum,<br>from login_hint, and decrypt<br>return None, if inum not found<br> Auth Server->>Browser: Display OTP Page Person->>Browser: enter OTP Browser->>Auth Server: POST OTP form Auth Server->>Auth Server: validate OTP Auth Server->>Auth Server: add session variable scope_enforce= otp Auth Server->>Browser: redirect to callback Browser->>Website: callback URI Website->>Auth Server: /token + client creds Auth Server->>Auth Server: Update token script is invoked. <br> read session variable scope-enforce <br> update scope of AT to include otp Auth Server->>Website: access_token, id_token,<br>refresh_token end rect rgb(255,255,186) Website->>API: request some endpoint<br>(with new access_token) API->>API: verify the acess_token. It should contain the necessary scope i.e otp end Step A: Ensure id_token has some info to identify the user: # When the user logs in for the very first time and performs basic authentication, the Update Token script can be used to place a custom claim containing some user information like User permissions User personal information Internal user identifier. In this example, we store the encrypted inum of the user as a \"custom claim\" in the id_token. A good practice is to not put the primary key / user identifier in plain text UpdateToken script: def modifyIdToken(self, jsonWebResponse, context): print \"Update token script. Modify idToken: %s\" % jsonWebResponse sessionIdService = CdiUtil.bean(SessionIdService) session = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence userService = CdiUtil.bean(UserService) user_name = session.getSessionAttributes().get(\"auth_user\") foundUser = userService.getUserByAttribute(\"uid\", user_name) userInum = foundUser.getAttribute(\"inum\") encryptedInum = CdiUtil.bean(EncryptionService).encrypt(userInum) print encryptedInum #custom claim in id_token jsonWebResponse.getClaims().setClaim(\"someFancyName\", encryptedInum) return True Step B: Website (RP) extracts the user info from id_token: # The Website (RP / client) should extract the user info from id_token and save it in the website's session. The website's session should not be confused with the Auth Server's session. The Auth Server sessions are state-less and any session related information that the website wishes to consume can only be that which can be extracted from an id_token. Step C: Critical Resource accessed by user. # Website detects critical resource, examines the Access token presented by the client. Redirects to RP for stepped-up authentication Step D: Stepped-up authentication # Website calls /authorize endpoint with login_hint=encrypted_inum, which was previously extracted from id_token in Step B Use login_hint , id_token_hint or request -jwe to identify the user in Person Authentication script used to perform the additional authentication step. Stepped-up Authn Person Authentication script: def prepareForStep(self, configurationAttributes, requestParameters, step): print \"OTP test. Prepare for steps %s\" %step if (step ==1): try: userService = CdiUtil.bean(UserService) encryptedInum = ServerUtil.getFirstValue(requestParameters, \"login_hint\") identity = CdiUtil.bean(Identity) print encryptedInum inum = CdiUtil.bean(EncryptionService).decrypt(encryptedInum) foundUser = userService.getUserByInum(inum ) print foundUser username = foundUser.getUserId() print \"username is %s \" % username identity.setWorkingParameter(\"uusername\", username ) return True except: print \"OTP. Exception: '%s'\" % (sys.exc_info()[1]) return False else: return False 3. Validate user otp 4. \"enforce_scope=otp\", add to session def authenticate(self, configurationAttributes, requestParameters, step): print(\"OTP, authentication for step %s\" %step) authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) userService = CdiUtil.bean(UserService) username = identity.getWorkingParameter(\"username\") print username #Here we set hard coded otp otp = '12345' inputOtp = ServerUtil.getFirstValue(requestParameters, \"loginForm:otpCode\") print(\"Client end otp %s \" %inputOtp) print(\"Server end otp %s\" %otp) if otp == inputOtp: print \"OTP Authenticated\" print CdiUtil.bean(SessionIdService).getSessionId() authenticationService.authenticate('username') # adding to session identity.setWorkingParameter(\"enforce_scope\",\"otp\") return True else: print(\"Wrong otp\") return errorMessage(\"Wrong otp entered\") return False 5: Update AT with relevant scope * Check the session variable \"enforce_scope\" and add the \"scope\" to the Access token. * You can also modify Access token header claims and regular claims using the modifyAccessToken in the Update Token Script. Update Token script: def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence enforce_scope = sessionId.getSessionAttributes().get(\"enforce_scope \") if enforce_scope not None: context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"existingScope1\", \"existingScope2\", \"mynewscope\")) context.getHeader().setClaim(\"custom_header_name\", \"custom_header_value\") context.getClaims().setClaim(\"claim_name\", \"claimValue\") Step E: Access the critical resource with new Access token: # The access token contains needed scope because the scopes were updated in Step D, point 5 Update token script # from io.jans.as.server.service import AuthenticationService from io.jans.as.server.service import UserService from io.jans.as.server.service import SessionIdService from io.jans.as.server.util import ServerUtil from io.jans.service.cdi.util import CdiUtil from io.jans.as.service.common import EncryptionService from io.jans.model.custom.script.type.token import UpdateTokenType class UpdateToken(UpdateTokenType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"Update token script. Initializing ...\" print \"Update token script. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Update token script. Destroying ...\" print \"Update token script. Destroyed successfully\" return True def getApiVersion(self): return 11 def modifyIdToken(self, jsonWebResponse, context): print \"Update token script. Modify idToken: %s\" % jsonWebResponse sessionIdService = CdiUtil.bean(SessionIdService) session = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence userService = CdiUtil.bean(UserService) user_name = session.getSessionAttributes().get(\"auth_user\") foundUser = userService.getUserByAttribute(\"uid\", user_name) userInum = foundUser.getAttribute(\"inum\") print userInum encryptedInum = CdiUtil.bean(EncryptionService).encrypt(userInum) print encryptedInum #custom claim in id_token jsonWebResponse.getClaims().setClaim(\"someFancyName\", encryptedInum) #print \"Update token script. After modify idToken: %s\" % jsonWebResponse #jsonWebResponse.getClaims().setClaim(\"someFancyName\", \"madhu\") return True def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence enforce_scope = sessionId.getSessionAttributes().get(\"enforce_scope\") if enforce_scope is not None: context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"openid\", \"profile\", \"otp\")) return True def modifyRefreshToken(self, refreshToken, context): return True def getRefreshTokenLifetimeInSeconds(self, context): return 0 def getIdTokenLifetimeInSeconds(self, context): return 0 def getAccessTokenLifetimeInSeconds(self, context): return 0 OTP script # from io.jans.as.server.util import ServerUtil from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.as.server.service import UserService from io.jans.as.server.service import SessionIdService from org.jans.as.server.service import CookieService from javax.faces.application import FacesMessage from org.gluu.jsf2.message import FacesMessages from org.gluu.jsf2.service import FacesService from io.jans.util import StringHelper from java.util import Arrays def errorMessage(errorInfo): facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() facesMessages.clear() facesMessages.add(FacesMessage.SEVERITY_ERROR, errorInfo) return False class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"OTP test. Initialization\" self.auth_user = None self.isUserAuthenticated = False self.isValidOtp = False print \"OTP test. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"OTP test. Destroy\" print \"OTP test. Destroyed successfully\" return True def getAuthenticationMethodClaims(self, requestParameters): return None def getApiVersion(self): return 11 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): print(\"OTP test, authentication for step %s\" %step) authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) userService = CdiUtil.bean(UserService) username = identity.getWorkingParameter(\"uusername\") print \"username is %s \" , username if(username is not None): userAuthenticated = authenticationService.authenticate(username) print(\"User present in session\") if(not userAuthenticated): print (\"Not authenticated\") return False #Here we set hard coded otp otp = '12345' inputOtp = ServerUtil.getFirstValue(requestParameters, \"loginForm:otpCode\") print(\"Client end otp %s \" %inputOtp) print(\"Server end otp %s\" %otp) if otp == inputOtp: print \"OTP Authenticated\" print CdiUtil.bean(SessionIdService).getSessionId() authenticationService.authenticate('username') identity.setWorkingParameter(\"enforce_scope\",\"otp\") return True else: print(\"Wrong otp\") return errorMessage(\"Wrong otp entered\") return False def prepareForStep(self, configurationAttributes, requestParameters, step): print \"OTP test. Prepare for steps %s\" %step if (step ==1): try: userService = CdiUtil.bean(UserService) encryptedInum = ServerUtil.getFirstValue(requestParameters, \"login_hint\") identity = CdiUtil.bean(Identity) print encryptedInum inum = CdiUtil.bean(EncryptionService).decrypt(encryptedInum) foundUser = userService.getUserByInum(inum ) print foundUser username = foundUser.getUserId() print \"username is %s \" % username identity.setWorkingParameter(\"uusername\", username ) return True except: print \"OTP. Exception: '%s'\" % (sys.exc_info()[1]) return False else: return False def getExtraParametersForStep(self, configurationAttributes, step): return Arrays.asList(\"uusername\", \"enforce_scope\") def getCountAuthenticationSteps(self, configurationAttributes): return 1 def getPageForStep(self, configurationAttributes, step): print(\"Get page for step %s\" %step) if( step==1 ) : return \"/auth/otp/otplogin.xhtml\" else: return \"\" def getNextStep(self, configurationAttributes, requestParameters, step): return -1 def getLogoutExternalUrl(self, configurationAttributes, requestParameters): print \"Get external logout URL call\" return None def logout(self, configurationAttributes, requestParameters): print\"logout\" return True", "title": "Stepped-up Authentication"}, {"location": "janssen-server/recipes/stepped-up-authn/#what-is-stepped-up-authentication", "text": "While navigating through an application, a user is challenged to produce an additional authentication when a certain API (of higher criticality) accessed by the client, does not have the needed scope. Consider the following sequence of events : 1. A user is logged in to an app using very basic authentication mechanism. Say login- password. 2. The user navigates through the app. 3. When the user attempts to access a critical resource, he is presented with another authentication step say otp. 4. The user, after successful authentication, has the needed access token to access the critical resource. sequenceDiagram title Stepped-up Authentication actor Person participant Browser participant Website participant Auth Server participant API autonumber Website->>API: request some endpoint API->>API: Enforce<br> presence of <br> 'otp' scope<br> in access_token API->>Website: 3. 401 Unauthorized<br>WWW-Authenticate: Bearer error=\"insufficient_user_authentication\" Website->>Browser: Enforce additional challenge on the user<br> (Enter OTP) Person->>Browser:Enter OTP Browser->>Auth Server: /authorize endpoint Note right of Auth Server: Stepped-up Authentication Auth Server->>Auth Server:Validate OTP (Person authentication script) Note right of Auth Server: Modify scope of AT Auth Server->>Auth Server: Modify scope of AT to include OTP (Update token script) Auth Server->> Website: Return Access Token with scope containing OTP", "title": "What is Stepped Up Authentication ?"}, {"location": "janssen-server/recipes/stepped-up-authn/#implementation-details", "text": "This implementation has been broken down to 5 parts highlighted in different colours. The details contain sample code that can be used to be build the flow using Person Authentication Scripts and Update Token Scripts sequenceDiagram title Implementation Stepped-up authn in Janssen's Authentication server actor Person participant Browser participant Website participant Auth Server participant API autonumber rect rgb(255, 223, 211) Website->>Browser: html login form Person->>Browser: Update PII Browser->>Website: POST Website->>Auth Server: login request /authorize?response_type=code id_token Auth Server->> Auth Server: UpdateTokenScript - place user info in id_token <br>e.g. encrypted inum Auth Server ->>Website: return id_token and code end rect rgb(211,211,211) Website->> Website: Extract the user info from id_token and save in website's session (not to be confused with Auth Server session) end rect rgb(212, 238, 227) Website->>API: request some endpoint API->>API: Enforce<br> presence of <br> 'otp' scope<br> in access_token API->>Website: 401 Unauthorized<br>WWW-Authenticate: <br>Bearer error=\"insufficient_user_authentication\" Website->>Browser: redirect to AS end rect rgb(186,225,255) Browser->>Auth Server: authorize?acr_values=otp<br>&client_id=1234<br>&scope=otp + other scopes<br>&response_type=code<br>&client_id=____<br>&redirect_uri=____<br>&state=_____<br>&nonce=____<br>&prompt=login&<br>login_hint=encrypted_inum Auth Server->>Auth Server: Get encrypted user inum,<br>from login_hint, and decrypt<br>return None, if inum not found<br> Auth Server->>Browser: Display OTP Page Person->>Browser: enter OTP Browser->>Auth Server: POST OTP form Auth Server->>Auth Server: validate OTP Auth Server->>Auth Server: add session variable scope_enforce= otp Auth Server->>Browser: redirect to callback Browser->>Website: callback URI Website->>Auth Server: /token + client creds Auth Server->>Auth Server: Update token script is invoked. <br> read session variable scope-enforce <br> update scope of AT to include otp Auth Server->>Website: access_token, id_token,<br>refresh_token end rect rgb(255,255,186) Website->>API: request some endpoint<br>(with new access_token) API->>API: verify the acess_token. It should contain the necessary scope i.e otp end", "title": "Implementation details :"}, {"location": "janssen-server/recipes/stepped-up-authn/#step-a-ensure-id_token-has-some-info-to-identify-the-user", "text": "When the user logs in for the very first time and performs basic authentication, the Update Token script can be used to place a custom claim containing some user information like User permissions User personal information Internal user identifier. In this example, we store the encrypted inum of the user as a \"custom claim\" in the id_token. A good practice is to not put the primary key / user identifier in plain text UpdateToken script: def modifyIdToken(self, jsonWebResponse, context): print \"Update token script. Modify idToken: %s\" % jsonWebResponse sessionIdService = CdiUtil.bean(SessionIdService) session = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence userService = CdiUtil.bean(UserService) user_name = session.getSessionAttributes().get(\"auth_user\") foundUser = userService.getUserByAttribute(\"uid\", user_name) userInum = foundUser.getAttribute(\"inum\") encryptedInum = CdiUtil.bean(EncryptionService).encrypt(userInum) print encryptedInum #custom claim in id_token jsonWebResponse.getClaims().setClaim(\"someFancyName\", encryptedInum) return True", "title": "Step A: Ensure id_token has some info to identify the user:"}, {"location": "janssen-server/recipes/stepped-up-authn/#step-b-website-rp-extracts-the-user-info-from-id_token", "text": "The Website (RP / client) should extract the user info from id_token and save it in the website's session. The website's session should not be confused with the Auth Server's session. The Auth Server sessions are state-less and any session related information that the website wishes to consume can only be that which can be extracted from an id_token.", "title": "Step B: Website (RP) extracts the user info from id_token:"}, {"location": "janssen-server/recipes/stepped-up-authn/#step-c-critical-resource-accessed-by-user", "text": "Website detects critical resource, examines the Access token presented by the client. Redirects to RP for stepped-up authentication", "title": "Step C: Critical Resource accessed by user."}, {"location": "janssen-server/recipes/stepped-up-authn/#step-d-stepped-up-authentication", "text": "Website calls /authorize endpoint with login_hint=encrypted_inum, which was previously extracted from id_token in Step B Use login_hint , id_token_hint or request -jwe to identify the user in Person Authentication script used to perform the additional authentication step. Stepped-up Authn Person Authentication script: def prepareForStep(self, configurationAttributes, requestParameters, step): print \"OTP test. Prepare for steps %s\" %step if (step ==1): try: userService = CdiUtil.bean(UserService) encryptedInum = ServerUtil.getFirstValue(requestParameters, \"login_hint\") identity = CdiUtil.bean(Identity) print encryptedInum inum = CdiUtil.bean(EncryptionService).decrypt(encryptedInum) foundUser = userService.getUserByInum(inum ) print foundUser username = foundUser.getUserId() print \"username is %s \" % username identity.setWorkingParameter(\"uusername\", username ) return True except: print \"OTP. Exception: '%s'\" % (sys.exc_info()[1]) return False else: return False 3. Validate user otp 4. \"enforce_scope=otp\", add to session def authenticate(self, configurationAttributes, requestParameters, step): print(\"OTP, authentication for step %s\" %step) authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) userService = CdiUtil.bean(UserService) username = identity.getWorkingParameter(\"username\") print username #Here we set hard coded otp otp = '12345' inputOtp = ServerUtil.getFirstValue(requestParameters, \"loginForm:otpCode\") print(\"Client end otp %s \" %inputOtp) print(\"Server end otp %s\" %otp) if otp == inputOtp: print \"OTP Authenticated\" print CdiUtil.bean(SessionIdService).getSessionId() authenticationService.authenticate('username') # adding to session identity.setWorkingParameter(\"enforce_scope\",\"otp\") return True else: print(\"Wrong otp\") return errorMessage(\"Wrong otp entered\") return False 5: Update AT with relevant scope * Check the session variable \"enforce_scope\" and add the \"scope\" to the Access token. * You can also modify Access token header claims and regular claims using the modifyAccessToken in the Update Token Script. Update Token script: def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence enforce_scope = sessionId.getSessionAttributes().get(\"enforce_scope \") if enforce_scope not None: context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"existingScope1\", \"existingScope2\", \"mynewscope\")) context.getHeader().setClaim(\"custom_header_name\", \"custom_header_value\") context.getClaims().setClaim(\"claim_name\", \"claimValue\")", "title": "Step D: Stepped-up authentication"}, {"location": "janssen-server/recipes/stepped-up-authn/#step-e-access-the-critical-resource-with-new-access-token", "text": "The access token contains needed scope because the scopes were updated in Step D, point 5", "title": "Step E: Access the critical resource with new Access token:"}, {"location": "janssen-server/recipes/stepped-up-authn/#update-token-script", "text": "from io.jans.as.server.service import AuthenticationService from io.jans.as.server.service import UserService from io.jans.as.server.service import SessionIdService from io.jans.as.server.util import ServerUtil from io.jans.service.cdi.util import CdiUtil from io.jans.as.service.common import EncryptionService from io.jans.model.custom.script.type.token import UpdateTokenType class UpdateToken(UpdateTokenType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"Update token script. Initializing ...\" print \"Update token script. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Update token script. Destroying ...\" print \"Update token script. Destroyed successfully\" return True def getApiVersion(self): return 11 def modifyIdToken(self, jsonWebResponse, context): print \"Update token script. Modify idToken: %s\" % jsonWebResponse sessionIdService = CdiUtil.bean(SessionIdService) session = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence userService = CdiUtil.bean(UserService) user_name = session.getSessionAttributes().get(\"auth_user\") foundUser = userService.getUserByAttribute(\"uid\", user_name) userInum = foundUser.getAttribute(\"inum\") print userInum encryptedInum = CdiUtil.bean(EncryptionService).encrypt(userInum) print encryptedInum #custom claim in id_token jsonWebResponse.getClaims().setClaim(\"someFancyName\", encryptedInum) #print \"Update token script. After modify idToken: %s\" % jsonWebResponse #jsonWebResponse.getClaims().setClaim(\"someFancyName\", \"madhu\") return True def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence enforce_scope = sessionId.getSessionAttributes().get(\"enforce_scope\") if enforce_scope is not None: context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"openid\", \"profile\", \"otp\")) return True def modifyRefreshToken(self, refreshToken, context): return True def getRefreshTokenLifetimeInSeconds(self, context): return 0 def getIdTokenLifetimeInSeconds(self, context): return 0 def getAccessTokenLifetimeInSeconds(self, context): return 0", "title": "Update token script"}, {"location": "janssen-server/recipes/stepped-up-authn/#otp-script", "text": "from io.jans.as.server.util import ServerUtil from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.as.server.service import UserService from io.jans.as.server.service import SessionIdService from org.jans.as.server.service import CookieService from javax.faces.application import FacesMessage from org.gluu.jsf2.message import FacesMessages from org.gluu.jsf2.service import FacesService from io.jans.util import StringHelper from java.util import Arrays def errorMessage(errorInfo): facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() facesMessages.clear() facesMessages.add(FacesMessage.SEVERITY_ERROR, errorInfo) return False class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print \"OTP test. Initialization\" self.auth_user = None self.isUserAuthenticated = False self.isValidOtp = False print \"OTP test. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"OTP test. Destroy\" print \"OTP test. Destroyed successfully\" return True def getAuthenticationMethodClaims(self, requestParameters): return None def getApiVersion(self): return 11 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): print(\"OTP test, authentication for step %s\" %step) authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) userService = CdiUtil.bean(UserService) username = identity.getWorkingParameter(\"uusername\") print \"username is %s \" , username if(username is not None): userAuthenticated = authenticationService.authenticate(username) print(\"User present in session\") if(not userAuthenticated): print (\"Not authenticated\") return False #Here we set hard coded otp otp = '12345' inputOtp = ServerUtil.getFirstValue(requestParameters, \"loginForm:otpCode\") print(\"Client end otp %s \" %inputOtp) print(\"Server end otp %s\" %otp) if otp == inputOtp: print \"OTP Authenticated\" print CdiUtil.bean(SessionIdService).getSessionId() authenticationService.authenticate('username') identity.setWorkingParameter(\"enforce_scope\",\"otp\") return True else: print(\"Wrong otp\") return errorMessage(\"Wrong otp entered\") return False def prepareForStep(self, configurationAttributes, requestParameters, step): print \"OTP test. Prepare for steps %s\" %step if (step ==1): try: userService = CdiUtil.bean(UserService) encryptedInum = ServerUtil.getFirstValue(requestParameters, \"login_hint\") identity = CdiUtil.bean(Identity) print encryptedInum inum = CdiUtil.bean(EncryptionService).decrypt(encryptedInum) foundUser = userService.getUserByInum(inum ) print foundUser username = foundUser.getUserId() print \"username is %s \" % username identity.setWorkingParameter(\"uusername\", username ) return True except: print \"OTP. Exception: '%s'\" % (sys.exc_info()[1]) return False else: return False def getExtraParametersForStep(self, configurationAttributes, step): return Arrays.asList(\"uusername\", \"enforce_scope\") def getCountAuthenticationSteps(self, configurationAttributes): return 1 def getPageForStep(self, configurationAttributes, step): print(\"Get page for step %s\" %step) if( step==1 ) : return \"/auth/otp/otplogin.xhtml\" else: return \"\" def getNextStep(self, configurationAttributes, requestParameters, step): return -1 def getLogoutExternalUrl(self, configurationAttributes, requestParameters): print \"Get external logout URL call\" return None def logout(self, configurationAttributes, requestParameters): print\"logout\" return True", "title": "OTP script"}, {"location": "janssen-server/recipes/user-password-validation/", "tags": ["administration", "recipes", "password"], "text": "Password validation # User password validation can be set to check the password strength, like the password must have at least one uppercase, or lowercase, number, and the length of the password. By default, the password attribute validation is not enabled. Enable user password validation through Command Line Tool (CLI) # Obtain the unique ID, that is inum for userPassword attribute. jans cli --operation-id get-attributes --endpoint-args pattern:userPassword Obatin the PatchRequest schema jans cli --schema PatchRequest > /tmp/patch.json Update /tmp/patch.json with user password validation details Enter a valid regex expression to check the strength of the password. Enter Minimum length , the minimum length of a value associated with this attribute. Enter Maximum length , the maximum length of a value associated with this attribute. Following is the example of having userPassword with minimum 8 characters, maximum 20 characters and should be alphanumeric with special characters. [{ \"op\" : \"add\" , \"path\" : \"/attributeValidation\" , \"value\" : { \"minLength\" : 5 , \"maxLength\" :15, \"regexp\" : \"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()\u2013[{}]:;',?/*~ $ ^+=<>]).{8,20} $ \" } }] Execute patch operation for userPassword attribute. jans cli --operation-id patch-attributes-by-inum \\ --url-suffix = \"inum:AAEE\" --data /tmp/patch.json Create a new user using post-user operation. An error notification will be displayed if the password does not match the validation criteria. Enable user password validation through Jans Text UI (TUI) # When using Janssen Text-based UI(TUI) to configure userPassword attribute validation , navigate via Auth Server -> Attributes ->search for userPassword attribute->open the attribute details->enable Enable Custom Validation field-> Enter a value for Regular expression , Minimum Length & Maximum Length fields->Save Create a new user using Users TUI menu. An error notification will be displayed if the password does not match the validation criteria. Enable user password validation through Jans Config API # Obtain the access token curl -k -u \"<put_client_id_here>:<put_config_api_client_secret_here>\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/attributes.write\" Obtain the unique ID, that is inum for userPassword attribute. curl -k -i -H \"Accept: application/json\" -H \"Content-Type: application/json\" \\ -H \"Authorization:Bearer <put_access_token_here>\" -X GET https://<your.jans.server>/jans-config-api/api/v1/attributes?pattern = userPassword Apply Patch for userPassword , use inum as path parameter Enter a valid regex expression to check the strength of the password. Enter Minimum length , the minimum length of a value associated with this attribute. Enter Maximum length , the maximum length of a value associated with this attribute. Following is the example of having userPassword with minimum 8 characters, maximum 20 characters, and should be alphanumeric with special characters. curl -k --location --request PATCH 'https://<your.jans.server>/jans-config-api/api/v1/attributes/<put_userPassword_inum_here>' \\ --header 'Content-Type: application/json-patch+json' --header 'Authorization: Bearer <put_access_token_here>' \\ --data-raw '[{ \"op\": \"add\", \"path\": \"/attributeValidation\", \"value\": { \"minLength\": 8, \"maxLength\":20, \"regexp\": \"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()\u2013[{}]:;' \\' ',?/*~$^+=<>]).{8,20}$\" } }]' Create a new user using /jans-config-api/mgt/configuser endpoint. An error notification will be displayed if the password does not match the validation criteria.", "title": "Password Validation"}, {"location": "janssen-server/recipes/user-password-validation/#password-validation", "text": "User password validation can be set to check the password strength, like the password must have at least one uppercase, or lowercase, number, and the length of the password. By default, the password attribute validation is not enabled.", "title": "Password validation"}, {"location": "janssen-server/recipes/user-password-validation/#enable-user-password-validation-through-command-line-tool-cli", "text": "Obtain the unique ID, that is inum for userPassword attribute. jans cli --operation-id get-attributes --endpoint-args pattern:userPassword Obatin the PatchRequest schema jans cli --schema PatchRequest > /tmp/patch.json Update /tmp/patch.json with user password validation details Enter a valid regex expression to check the strength of the password. Enter Minimum length , the minimum length of a value associated with this attribute. Enter Maximum length , the maximum length of a value associated with this attribute. Following is the example of having userPassword with minimum 8 characters, maximum 20 characters and should be alphanumeric with special characters. [{ \"op\" : \"add\" , \"path\" : \"/attributeValidation\" , \"value\" : { \"minLength\" : 5 , \"maxLength\" :15, \"regexp\" : \"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()\u2013[{}]:;',?/*~ $ ^+=<>]).{8,20} $ \" } }] Execute patch operation for userPassword attribute. jans cli --operation-id patch-attributes-by-inum \\ --url-suffix = \"inum:AAEE\" --data /tmp/patch.json Create a new user using post-user operation. An error notification will be displayed if the password does not match the validation criteria.", "title": "Enable user password validation through Command Line Tool (CLI)"}, {"location": "janssen-server/recipes/user-password-validation/#enable-user-password-validation-through-jans-text-ui-tui", "text": "When using Janssen Text-based UI(TUI) to configure userPassword attribute validation , navigate via Auth Server -> Attributes ->search for userPassword attribute->open the attribute details->enable Enable Custom Validation field-> Enter a value for Regular expression , Minimum Length & Maximum Length fields->Save Create a new user using Users TUI menu. An error notification will be displayed if the password does not match the validation criteria.", "title": "Enable user password validation through Jans Text UI (TUI)"}, {"location": "janssen-server/recipes/user-password-validation/#enable-user-password-validation-through-jans-config-api", "text": "Obtain the access token curl -k -u \"<put_client_id_here>:<put_config_api_client_secret_here>\" https://<your.jans.server>/jans-auth/restv1/token \\ -d \"grant_type=client_credentials&scope=https://jans.io/oauth/config/attributes.write\" Obtain the unique ID, that is inum for userPassword attribute. curl -k -i -H \"Accept: application/json\" -H \"Content-Type: application/json\" \\ -H \"Authorization:Bearer <put_access_token_here>\" -X GET https://<your.jans.server>/jans-config-api/api/v1/attributes?pattern = userPassword Apply Patch for userPassword , use inum as path parameter Enter a valid regex expression to check the strength of the password. Enter Minimum length , the minimum length of a value associated with this attribute. Enter Maximum length , the maximum length of a value associated with this attribute. Following is the example of having userPassword with minimum 8 characters, maximum 20 characters, and should be alphanumeric with special characters. curl -k --location --request PATCH 'https://<your.jans.server>/jans-config-api/api/v1/attributes/<put_userPassword_inum_here>' \\ --header 'Content-Type: application/json-patch+json' --header 'Authorization: Bearer <put_access_token_here>' \\ --data-raw '[{ \"op\": \"add\", \"path\": \"/attributeValidation\", \"value\": { \"minLength\": 8, \"maxLength\":20, \"regexp\": \"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()\u2013[{}]:;' \\' ',?/*~$^+=<>]).{8,20}$\" } }]' Create a new user using /jans-config-api/mgt/configuser endpoint. An error notification will be displayed if the password does not match the validation criteria.", "title": "Enable user password validation through Jans Config API"}, {"location": "janssen-server/reference/learning-reference/", "tags": ["administration", "external content", "blogs", "videos", "tutorials"], "text": "Community Content References # This is a list of helpful learning resources outside the official documentation about the Janssen Project. Most of the content is created by the community at large, along with the core team. Though this list is not a complete list of all the content created by the community on various platforms, please help us keep it updated by raising a PR. Articles and Blogs # An intro to Janssen IDP Terraform Provider - Part1 An intro to Janssen IDP Terraform Provider - Part2 Jans-tent to test Single-Sign-On with your Authorization Server Janssen + Mod Auth openidc module to Test OpenID Connect Single Sign-on (SSO) and Single Single Logout (SLO) Enhancing Secure Mobile Authentication with OAuth, Dynamic Client Registration, and DPoP Videos # Password Authentication Using Agama Email Code verification flow Using Agama Time Based OTP authentication Using Agama Connecting To External OpenId Providers Using Agama", "title": "Learning Reference"}, {"location": "janssen-server/reference/learning-reference/#community-content-references", "text": "This is a list of helpful learning resources outside the official documentation about the Janssen Project. Most of the content is created by the community at large, along with the core team. Though this list is not a complete list of all the content created by the community on various platforms, please help us keep it updated by raising a PR.", "title": "Community Content References"}, {"location": "janssen-server/reference/learning-reference/#articles-and-blogs", "text": "An intro to Janssen IDP Terraform Provider - Part1 An intro to Janssen IDP Terraform Provider - Part2 Jans-tent to test Single-Sign-On with your Authorization Server Janssen + Mod Auth openidc module to Test OpenID Connect Single Sign-on (SSO) and Single Single Logout (SLO) Enhancing Secure Mobile Authentication with OAuth, Dynamic Client Registration, and DPoP", "title": "Articles and Blogs"}, {"location": "janssen-server/reference/learning-reference/#videos", "text": "Password Authentication Using Agama Email Code verification flow Using Agama Time Based OTP authentication Using Agama Connecting To External OpenId Providers Using Agama", "title": "Videos"}, {"location": "janssen-server/reference/openapi/", "tags": ["administration", "reference", "REST API", "javadocs"], "text": "API Reference # Janssen Server components publish REST API using OpenAPI specification and Java API using javadoc. REST API # Follow the links below to access respective documentation. Service REST API Jans Auth Server Swagger Jans Config API Swagger Jans Core NA Jans FIDO 2 Swagger Jans SCIM API Swagger Jans KC SAML API Swagger Jans Lock Server Swagger Javadocs # Javadocs for all the modules can be accessed from left side navigation bar under respective module name in Reference Guide > Javadocs / OpenAPI .", "title": "API Reference"}, {"location": "janssen-server/reference/openapi/#api-reference", "text": "Janssen Server components publish REST API using OpenAPI specification and Java API using javadoc.", "title": "API Reference"}, {"location": "janssen-server/reference/openapi/#rest-api", "text": "Follow the links below to access respective documentation. Service REST API Jans Auth Server Swagger Jans Config API Swagger Jans Core NA Jans FIDO 2 Swagger Jans SCIM API Swagger Jans KC SAML API Swagger Jans Lock Server Swagger", "title": "REST API"}, {"location": "janssen-server/reference/openapi/#javadocs", "text": "Javadocs for all the modules can be accessed from left side navigation bar under respective module name in Reference Guide > Javadocs / OpenAPI .", "title": "Javadocs"}, {"location": "janssen-server/reference/database/mysql-config/", "tags": ["administration", "reference", "database", "remote database"], "text": "MySQL ORM persistence layer # The recommended MySQL version is 8.x or newer. Before running installation the administrator can pre-install DB and provide credentials to access it or he can select option to install MySQL on same server during setup. During installation setup generates default /etc/jans/conf/jans-sql.properties and creates jansdb schema with tables and initial data set. Configuration properties # List of specific for MySQL default setting from jans-sql.properties : db.schema.name=jansdb connection.uri=jdbc:mysql://localhost:3306/jansdb?enabledTLSProtocols=TLSv1.2 connection.driver-property.serverTimezone=UTC+0000 # Prefix connection.driver-property.key=value will be coverterd to key=value JDBC driver properties #connection.driver-property.driverProperty=driverPropertyValue #connection.driver-property.useServerPrepStmts=false connection.driver-property.cachePrepStmts=false connection.driver-property.cacheResultSetMetadata=true connection.driver-property.metadataCacheSize=500 #connection.driver-property.prepStmtCacheSize=500 #connection.driver-property.prepStmtCacheSqlLimit=1024 auth.userName=jans auth.userPassword=CC0NHhtXW78= # Password hash method password.encryption.method=SSHA-256 # Connection pool size connection.pool.max-total=40 connection.pool.max-idle=15 connection.pool.min-idle=5 # Max time needed to create connection pool in milliseconds connection.pool.create-max-wait-time-millis=20000 # Max wait 20 seconds connection.pool.max-wait-time-millis=20000 # Allow to evict connection in pool after 30 minutes connection.pool.min-evictable-idle-time-millis=1800000 # Sets whether objects created for the pool will be validated before being returned from it #connection.pool.test-on-create=true # Sets whether objects borrowed from the pool will be validated when they are returned to the pool #connection.pool.test-on-return=true The rest of properties are static for all other supported DB: binaryAttributes=objectGUID certificateAttributes=userCertificate doc_id building rules # In order to support transparency for end applications and allow data migration from one DB to another ORM requires DN attribute in each entry. This attribute it also uses to build doc_id . Here is example of this DN -> doc_id conversion: doc_id is primary key. In order to build unique document identifier ORM uses another unique attribute DN . doc_id is last RDN value. Generic tables structure # Each table in jansdb MySQL schema follow next rules: one table for every objectClass has 2 mandatory column DN and doc_id Index for primary key Data mapping rules # ORM uses VARCHAR / DATETIME(3) / INT / BINARY / SMALLINT / BLOB / JSON data types. SMALLINT represents boolean attribute type. JSON it uses to store multi-valued attribute values. The generic format of such values is: {\"v\": [\"value_1\", \"value_2\", ...]} ORM add v key on top level due to MySQL limitations of indexing JSON array if they are on to level. If it's specified in schema that application can do search in multi-valued attribute setup add next indexes for each column: KEY `jansExtUid_json_1` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v') as char(128) array))), KEY `jansExtUid_json_2` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[0]') as char(128) charset utf8mb4))), KEY `jansExtUid_json_3` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[1]') as char(128) charset utf8mb4))), KEY `jansExtUid_json_4` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[2]') as char(128) charset utf8mb4))), By default it creates indexes for first 3 values. Administrator should add more indexes to confrom maximum count of values. In future versions if top level JSON array indexing will work well we can review format to use simple JSON array. For user password field ORM on persist/update operations automatically create hash. On authentication ORM compares hashes. To store attributes defined in java beans with @JsonObject annotation ORM uses TEXT column type. Java example # This example shows how to use ORM. It opens connection to MySQL DB and add user entry to it: public static void main(String[] args) { // Create Sql entry manager SqlEntryManager couchbaseEntryManager = createSqlEntryManager(); // Create and fill user bean SimpleUser newUser = new SimpleUser(); newUser.setDn(String.format(\"inum=%s,ou=people,o=jans\", System.currentTimeMillis())); newUser.setUserId(\"sample_user_\" + System.currentTimeMillis()); newUser.setUserPassword(\"test\"); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansAddress\", Arrays.asList(\"London\", \"Texas\", \"New York\"))); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); // Call ORM API to store entry couchbaseEntryManager.persist(newUser); couchbaseEntryManager.destroy(); } public static SqlEntryManager createSqlEntryManager() { SqlEntryManagerFactory couchbaseEntryManagerFactory = new SqlEntryManagerFactory(); couchbaseEntryManagerFactory.create(); Properties connectionProperties = getSampleConnectionProperties(); SqlEntryManager couchbaseEntryManager = couchbaseEntryManagerFactory.createEntryManager(connectionProperties); return couchbaseEntryManager; } private static Properties getSampleConnectionProperties() { Properties connectionProperties = new Properties(); connectionProperties.put(\"sql#db.schema.name\", \"jansdb\"); connectionProperties.put(\"sql#connection.uri\", \"jdbc:mysql://localhost:3306/jansdb?profileSQL=true\"); connectionProperties.put(\"sql#connection.driver-property.serverTimezone\", \"GMT+2\"); connectionProperties.put(\"sql#connection.pool.max-total\", \"300\"); connectionProperties.put(\"sql#connection.pool.max-idle\", \"300\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"secret\"); // Password hash method connectionProperties.put(\"sql#password.encryption.method\", \"SSHA-256\"); // Max time needed to create connection pool in milliseconds connectionProperties.put(\"sql#connection.pool.create-max-wait-time-millis\", \"20000\"); // Max wait 20 seconds connectionProperties.put(\"sql#connection.pool.max-wait-time-millis\", \"20000\"); // Allow to evict connection in pool after 30 minutes connectionProperties.put(\"sql#connection.pool.min-evictable-idle-time-millis\", \"1800000\"); connectionProperties.put(\"sql#binaryAttributes\", \"objectGUID\"); connectionProperties.put(\"sql#certificateAttributes\", \"userCertificate\"); return connectionProperties; } More MySQL ORM examples is in this sample module.", "title": "MySQL Configuration"}, {"location": "janssen-server/reference/database/mysql-config/#mysql-orm-persistence-layer", "text": "The recommended MySQL version is 8.x or newer. Before running installation the administrator can pre-install DB and provide credentials to access it or he can select option to install MySQL on same server during setup. During installation setup generates default /etc/jans/conf/jans-sql.properties and creates jansdb schema with tables and initial data set.", "title": "MySQL ORM persistence layer"}, {"location": "janssen-server/reference/database/mysql-config/#configuration-properties", "text": "List of specific for MySQL default setting from jans-sql.properties : db.schema.name=jansdb connection.uri=jdbc:mysql://localhost:3306/jansdb?enabledTLSProtocols=TLSv1.2 connection.driver-property.serverTimezone=UTC+0000 # Prefix connection.driver-property.key=value will be coverterd to key=value JDBC driver properties #connection.driver-property.driverProperty=driverPropertyValue #connection.driver-property.useServerPrepStmts=false connection.driver-property.cachePrepStmts=false connection.driver-property.cacheResultSetMetadata=true connection.driver-property.metadataCacheSize=500 #connection.driver-property.prepStmtCacheSize=500 #connection.driver-property.prepStmtCacheSqlLimit=1024 auth.userName=jans auth.userPassword=CC0NHhtXW78= # Password hash method password.encryption.method=SSHA-256 # Connection pool size connection.pool.max-total=40 connection.pool.max-idle=15 connection.pool.min-idle=5 # Max time needed to create connection pool in milliseconds connection.pool.create-max-wait-time-millis=20000 # Max wait 20 seconds connection.pool.max-wait-time-millis=20000 # Allow to evict connection in pool after 30 minutes connection.pool.min-evictable-idle-time-millis=1800000 # Sets whether objects created for the pool will be validated before being returned from it #connection.pool.test-on-create=true # Sets whether objects borrowed from the pool will be validated when they are returned to the pool #connection.pool.test-on-return=true The rest of properties are static for all other supported DB: binaryAttributes=objectGUID certificateAttributes=userCertificate", "title": "Configuration properties"}, {"location": "janssen-server/reference/database/mysql-config/#doc_id-building-rules", "text": "In order to support transparency for end applications and allow data migration from one DB to another ORM requires DN attribute in each entry. This attribute it also uses to build doc_id . Here is example of this DN -> doc_id conversion: doc_id is primary key. In order to build unique document identifier ORM uses another unique attribute DN . doc_id is last RDN value.", "title": "doc_id building rules"}, {"location": "janssen-server/reference/database/mysql-config/#generic-tables-structure", "text": "Each table in jansdb MySQL schema follow next rules: one table for every objectClass has 2 mandatory column DN and doc_id Index for primary key", "title": "Generic tables structure"}, {"location": "janssen-server/reference/database/mysql-config/#data-mapping-rules", "text": "ORM uses VARCHAR / DATETIME(3) / INT / BINARY / SMALLINT / BLOB / JSON data types. SMALLINT represents boolean attribute type. JSON it uses to store multi-valued attribute values. The generic format of such values is: {\"v\": [\"value_1\", \"value_2\", ...]} ORM add v key on top level due to MySQL limitations of indexing JSON array if they are on to level. If it's specified in schema that application can do search in multi-valued attribute setup add next indexes for each column: KEY `jansExtUid_json_1` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v') as char(128) array))), KEY `jansExtUid_json_2` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[0]') as char(128) charset utf8mb4))), KEY `jansExtUid_json_3` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[1]') as char(128) charset utf8mb4))), KEY `jansExtUid_json_4` ((cast(json_extract(`jansExtUid`,_utf8mb4'$.v[2]') as char(128) charset utf8mb4))), By default it creates indexes for first 3 values. Administrator should add more indexes to confrom maximum count of values. In future versions if top level JSON array indexing will work well we can review format to use simple JSON array. For user password field ORM on persist/update operations automatically create hash. On authentication ORM compares hashes. To store attributes defined in java beans with @JsonObject annotation ORM uses TEXT column type.", "title": "Data mapping rules"}, {"location": "janssen-server/reference/database/mysql-config/#java-example", "text": "This example shows how to use ORM. It opens connection to MySQL DB and add user entry to it: public static void main(String[] args) { // Create Sql entry manager SqlEntryManager couchbaseEntryManager = createSqlEntryManager(); // Create and fill user bean SimpleUser newUser = new SimpleUser(); newUser.setDn(String.format(\"inum=%s,ou=people,o=jans\", System.currentTimeMillis())); newUser.setUserId(\"sample_user_\" + System.currentTimeMillis()); newUser.setUserPassword(\"test\"); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansAddress\", Arrays.asList(\"London\", \"Texas\", \"New York\"))); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); // Call ORM API to store entry couchbaseEntryManager.persist(newUser); couchbaseEntryManager.destroy(); } public static SqlEntryManager createSqlEntryManager() { SqlEntryManagerFactory couchbaseEntryManagerFactory = new SqlEntryManagerFactory(); couchbaseEntryManagerFactory.create(); Properties connectionProperties = getSampleConnectionProperties(); SqlEntryManager couchbaseEntryManager = couchbaseEntryManagerFactory.createEntryManager(connectionProperties); return couchbaseEntryManager; } private static Properties getSampleConnectionProperties() { Properties connectionProperties = new Properties(); connectionProperties.put(\"sql#db.schema.name\", \"jansdb\"); connectionProperties.put(\"sql#connection.uri\", \"jdbc:mysql://localhost:3306/jansdb?profileSQL=true\"); connectionProperties.put(\"sql#connection.driver-property.serverTimezone\", \"GMT+2\"); connectionProperties.put(\"sql#connection.pool.max-total\", \"300\"); connectionProperties.put(\"sql#connection.pool.max-idle\", \"300\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"secret\"); // Password hash method connectionProperties.put(\"sql#password.encryption.method\", \"SSHA-256\"); // Max time needed to create connection pool in milliseconds connectionProperties.put(\"sql#connection.pool.create-max-wait-time-millis\", \"20000\"); // Max wait 20 seconds connectionProperties.put(\"sql#connection.pool.max-wait-time-millis\", \"20000\"); // Allow to evict connection in pool after 30 minutes connectionProperties.put(\"sql#connection.pool.min-evictable-idle-time-millis\", \"1800000\"); connectionProperties.put(\"sql#binaryAttributes\", \"objectGUID\"); connectionProperties.put(\"sql#certificateAttributes\", \"userCertificate\"); return connectionProperties; } More MySQL ORM examples is in this sample module.", "title": "Java example"}, {"location": "janssen-server/reference/database/mysql-ops/", "tags": ["administration", "reference", "database", "additional claims to database", "jansPerson"], "text": "Below operations require to log into mysql workspace first with command: mysql Change password for user jans : # ALTER USER 'jans'@'localhost' IDENTIFIED BY 'TopSecret'; GRANT ALL PRIVILEGES ON jansdb.* TO 'jans'@'localhost'; Create new user claims to jansPerson : # You can add additional attributes to jansPerson table and use them. Here DB stores all the user attribute information in one entry. Additional attributes will not affect the server functionality. Ensure you restart services after DB schema modification Modify column size of jansPerson : # Say we want to increase the size of mail field to 144. Do the following: * a. Modify column size - ALTER TABLE `jansdb`.`jansPerson` CHANGE COLUMN `mail` `mail` VARCHAR(144) NULL DEFAULT NULL ; * b. Drop indexes and re-create - ALTER TABLE jansdb.jansPerson DROP INDEX `jansPerson_CustomIdx2`; ALTER TABLE jansdb.jansPerson ADD INDEX `jansPerson_CustomIdx2` ((lower(`mail`))); * c. Ensure you restart services after DB schema modification Add user in Jans admin group # Search for inum of JansGrp use jansdb; select * from jansGrp\\G; Add specific user in this group Get DN of user use jansdb; select * from jansPerson where uid='testUser'\\G ; Copy DN of this user. i.e. inum=83d43a5d-3311-4c93-ae26-df80c320557a,ou=people,o=jans Perform operation: use jansdb; update jansGrp set member = '{\"v\": [\"inum=e4fe2c89-f588-41a2-aac5-2f1afa63bed1,ou=people,o=jans\", \"inum=83d43a5d-3311-4c93-ae26-df80c320557a,ou=people,o=jans\"]}'; Update user information # In this example we are doing to update one user's email address. Search for existing email address: use jansdb; select * from jansPerson where uid='testUser'\\G; Modify it: use jansdb; update jansPerson set mail='newEmail@gluu.org' where uid='testUser'; Search user : # use jansdb; select * from jansPerson where uid='admin'\\G; Add custom attribute # There are three steps here: Create attribute in MySQL database: ALTER TABLE jansdb.jansPerson ADD COLUMN cmdAttr VARCHAR(64) NULL; Restart the ConfgiApi service . If you are using kubernetes please restart the deployment . Create attribute using the terraform provider, curl commands, or TUI: Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "MySQL Operation"}, {"location": "janssen-server/reference/database/mysql-ops/#change-password-for-user-jans", "text": "ALTER USER 'jans'@'localhost' IDENTIFIED BY 'TopSecret'; GRANT ALL PRIVILEGES ON jansdb.* TO 'jans'@'localhost';", "title": "Change password for user jans :"}, {"location": "janssen-server/reference/database/mysql-ops/#create-new-user-claims-to-jansperson", "text": "You can add additional attributes to jansPerson table and use them. Here DB stores all the user attribute information in one entry. Additional attributes will not affect the server functionality. Ensure you restart services after DB schema modification", "title": "Create new user claims to jansPerson:"}, {"location": "janssen-server/reference/database/mysql-ops/#modify-column-size-of-jansperson", "text": "Say we want to increase the size of mail field to 144. Do the following: * a. Modify column size - ALTER TABLE `jansdb`.`jansPerson` CHANGE COLUMN `mail` `mail` VARCHAR(144) NULL DEFAULT NULL ; * b. Drop indexes and re-create - ALTER TABLE jansdb.jansPerson DROP INDEX `jansPerson_CustomIdx2`; ALTER TABLE jansdb.jansPerson ADD INDEX `jansPerson_CustomIdx2` ((lower(`mail`))); * c. Ensure you restart services after DB schema modification", "title": "Modify column size of jansPerson :"}, {"location": "janssen-server/reference/database/mysql-ops/#add-user-in-jans-admin-group", "text": "Search for inum of JansGrp use jansdb; select * from jansGrp\\G; Add specific user in this group Get DN of user use jansdb; select * from jansPerson where uid='testUser'\\G ; Copy DN of this user. i.e. inum=83d43a5d-3311-4c93-ae26-df80c320557a,ou=people,o=jans Perform operation: use jansdb; update jansGrp set member = '{\"v\": [\"inum=e4fe2c89-f588-41a2-aac5-2f1afa63bed1,ou=people,o=jans\", \"inum=83d43a5d-3311-4c93-ae26-df80c320557a,ou=people,o=jans\"]}';", "title": "Add user in Jans admin group"}, {"location": "janssen-server/reference/database/mysql-ops/#update-user-information", "text": "In this example we are doing to update one user's email address. Search for existing email address: use jansdb; select * from jansPerson where uid='testUser'\\G; Modify it: use jansdb; update jansPerson set mail='newEmail@gluu.org' where uid='testUser';", "title": "Update user information"}, {"location": "janssen-server/reference/database/mysql-ops/#search-user", "text": "use jansdb; select * from jansPerson where uid='admin'\\G;", "title": "Search user :"}, {"location": "janssen-server/reference/database/mysql-ops/#add-custom-attribute", "text": "There are three steps here: Create attribute in MySQL database: ALTER TABLE jansdb.jansPerson ADD COLUMN cmdAttr VARCHAR(64) NULL; Restart the ConfgiApi service . If you are using kubernetes please restart the deployment . Create attribute using the terraform provider, curl commands, or TUI: Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "Add custom attribute"}, {"location": "janssen-server/reference/database/mysql-schema/", "tags": ["administration", "database", "MySQL", "Indexes"], "text": "MySQL Schema # Tables # Table names adsPrjDeployment agmFlow agmFlowRun jansAppConf jansAttr jansCache jansCibaReq jansClnt jansClntAuthz jansCustomScr jansDeviceRegistration jansDocument jansFido2AuthnEntry jansFido2RegistrationEntry jansGrant jansGrp jansInumMap jansMetric jansOrganization jansPairwiseIdentifier jansPar jansPassResetReq jansPerson jansPushApp jansPushDevice jansRp jansScope jansScr jansSectorIdentifier jansSessId jansSsa jansStatEntry jansToken jansU2fReq jansUmaPCT jansUmaRPT jansUmaResource jansUmaResourcePermission adsPrjDeployment # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansStartDate datetime(3) YES None Start date jansActive smallint YES None jansEndDate datetime(3) YES None End date adsPrjAssets longtext YES None Assets of an ADS project adsPrjDeplDetails text YES None Misc details associated to an ADS project agmFlow # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None agFlowQname varchar(64) YES None Full name of an agama flow agFlowMeta text YES None Metadata of an agama flow jansScr text YES None Attr that contains script (python, java script) jansEnabled smallint YES None Status of the entry, used by many objectclasses jansScrError text YES None Attr that contains first error which application get during it execution agFlowTrans text YES None Transpiled code of an agama flow jansRevision int YES None Revision jansCustomMessage varchar(128) YES None exclude custom welcome message agmFlowRun # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier agFlowSt text YES None Details of a running agama flow instance agFlowEncCont mediumtext YES None Continuation associated to a running agama flow instance jansCustomMessage varchar(128) YES None exclude custom welcome message exp datetime(3) YES None jans Exp jansAppConf # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None ou varchar(64) YES None description varchar(768) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansHostname varchar(64) YES None The hostname of the Jans Server instance jansLastUpd datetime(3) YES None Monitors last time the server was able to connect to the monitoring system. jansManager varchar(64) YES None Used to specify if a person has the manager role jansOrgProfileMgt smallint YES None enable or disable profile management feature in exclude jansScimEnabled smallint YES None exclude SCIM feature - enabled or disabled jansEmail json YES None jansSmtpConf json YES None SMTP configuration jansSslExpiry varchar(64) YES None SAML Trust Relationship configuration jansStatus varchar(16) YES None Status of the entry, used by many objectclasses jansUrl varchar(64) YES None Jans instance URL inum varchar(64) YES None XRI i-number o varchar(64) YES None jansAuthMode varchar(64) YES None jansDbAuth json YES None Custom IDP authentication configuration jansLogViewerConfig varchar(64) YES None Log viewer configuration jansLogConfigLocation varchar(64) YES None Path to external log4j2.xml jansCacheConf text YES None Cache configuration jansDocStoreConf text YES None jansDocStoreConf jansSoftVer varchar(64) YES None userPassword varchar(256) YES None jansConfDyn text YES None jans Dyn Conf jansConfErrors text YES None jans Errors Conf jansConfStatic text YES None jans Static Conf jansConfWebKeys text YES None jans Web Keys Conf jansWebKeysSettings varchar(64) YES None jans Web Keys Conf jansConfApp text YES None jans App Conf jansRevision int YES None Revision jansAttr # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries jansAttrEditTyp json YES None Specify in exclude who can update an attribute, admin or user jansAttrName varchar(64) YES MUL None Specify an identifier for an attribute. May be multi-value where an attribute has two names, like givenName and first-name. jansAttrOrigin varchar(64) YES MUL None Specify the person objectclass associated with the attribute, used for display purposes in exclude. jansAttrSystemEditTyp varchar(64) YES None TODO - still required? jansAttrTyp varchar(64) YES None Data type of attribute. Values can be string, photo, numeric, date jansClaimName varchar(64) YES None Used by jans in conjunction with jansttributeName to map claims to attributes in datastore. jansAttrUsgTyp varchar(64) YES None TODO - Usg? Value can be OpenID jansAttrViewTyp json YES None Specify in exclude who can view an attribute, admin or user jansSAML1URI varchar(64) YES None SAML 1 uri of attribute jansSAML2URI varchar(64) YES None SAML 2 uri of attribute jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number jansMultivaluedAttr smallint YES None jansHideOnDiscovery smallint YES None jansNameIdTyp varchar(64) YES None NameId Typ jansScimCustomAttr smallint YES None jansSourceAttr varchar(64) YES None Source Attr for this Attr seeAlso varchar(64) YES None urn varchar(128) YES None jansRegExp varchar(64) YES None Regular expression used to validate attribute data jansTooltip varchar(64) YES None Custom tooltip to be shown on the UI jansValidation tinytext YES None This data has information about attribute Validation jansCache # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None uuid varchar(64) YES None Unique identifier iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del dat text YES None OX data jansCibaReq # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authReqId varchar(64) YES None Authn request id clnId varchar(64) YES None jans Clnt id usrId varchar(64) YES None jans user id creationDate datetime(3) YES None Creation Date used for password reset requests exp datetime(3) YES None jans Exp jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses jansClnt # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None o varchar(64) YES None jansGrp varchar(64) YES None Group displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries displayNameLocalized json YES None jans Display Name Localized description varchar(768) YES MUL None inum varchar(64) YES MUL None XRI i-number jansAppTyp varchar(64) YES None jans App Typ jansClntIdIssuedAt datetime(3) YES None jans Clnt Issued At jansClntSecret varchar(64) YES None jans Clnt Secret jansClntSecretExpAt datetime(3) YES MUL None Date client expires exp datetime(3) YES None jans Exp del smallint YES MUL None del jansClntURI tinytext YES None jans Clnt URI jansClntURILocalized json YES None jans Clnt URI localized jansContact json YES None jans Contact jansDefAcrValues json YES None jans Def Acr Values jansDefMaxAge int YES None jans Def Max Age jansGrantTyp json YES None jans Grant Typ jansIdTknEncRespAlg varchar(64) YES None jans ID Tkn Enc Resp Alg jansIdTknEncRespEnc varchar(64) YES None jans ID Tkn Enc Resp Enc jansIdTknSignedRespAlg varchar(64) YES None jans ID Tkn Signed Resp Alg jansInitiateLoginURI tinytext YES None jans Initiate Login URI jansJwksURI tinytext YES None jans JWKs URI jansJwks text YES None jans JWKs jansLogoURI tinytext YES None jans Logo URI jansLogoURILocalized json YES None jans Logo URI localized jansPolicyURI tinytext YES None jans Policy URI jansPolicyURILocalized json YES None jans Policy URI localized jansPostLogoutRedirectURI json YES None jans Post Logout Redirect URI jansRedirectURI json YES None jans Redirect URI jansRegistrationAccessTkn varchar(64) YES MUL None jans Registration Access Tkn jansReqObjSigAlg varchar(64) YES None jans Req Obj Sig Alg jansReqObjEncAlg varchar(64) YES None jans Req Obj Enc Alg jansReqObjEncEnc varchar(64) YES None jans Req Obj Enc Enc jansReqURI json YES None jans Req URI jansRespTyp json YES None jans Resp Typ jansScope json YES None jans Attr Scope jansClaim json YES None jans Attr Claim jansSectorIdentifierURI tinytext YES None jans Sector Identifier URI jansSignedRespAlg varchar(64) YES None jans Signed Resp Alg jansSubjectTyp varchar(64) YES None jans Subject Typ jansTknEndpointAuthMethod varchar(64) YES None jans Tkn Endpoint Auth Method jansTknEndpointAuthSigAlg varchar(64) YES None jans Tkn Endpoint Auth Sig Alg jansTosURI tinytext YES None jans TOS URI jansTosURILocalized json YES None jans Tos URI localized jansTrustedClnt smallint YES None jans Trusted Clnt jansUsrInfEncRespAlg varchar(64) YES None jans Usr Inf Enc Resp Alg jansUsrInfEncRespEnc varchar(64) YES None jans Usr Inf Enc Resp Enc jansExtraConf varchar(64) YES None jans additional configuration jansClaimRedirectURI json YES None Claim Redirect URI jansLastAccessTime datetime(3) YES None Last access time jansLastLogonTime datetime(3) YES None Last logon time jansPersistClntAuthzs smallint YES None jans Persist Clnt Authzs jansInclClaimsInIdTkn smallint YES None jans Incl Claims In Id Tkn jansRefreshTknLife int YES None Life of refresh token jansDisabled smallint YES None Status of client jansLogoutURI json YES None jans Policy URI jansLogoutSessRequired smallint YES None jans Policy URI jansdId varchar(64) YES None jansd Id jansAuthorizedOrigins json YES None jans Authorized Origins tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash jansAccessTknAsJwt smallint YES None jansauth - indicator whether to return access token as JWT jansAccessTknSigAlg varchar(64) YES None jansauth - access token signing algorithm jansAccessTknLife int YES None Life of access token jansSoftId varchar(64) YES None Soft Identifier jansSoftVer varchar(64) YES None jansSoftStatement text YES None Soft Statement jansRptAsJwt smallint YES None jansRptAsJwt jansAttrs text YES None Attrs jansBackchannelTknDeliveryMode varchar(64) YES None jans Backchannel Tkn Delivery Mode jansBackchannelClntNotificationEndpoint varchar(64) YES None jans Backchannel Clnt Notification Endpoint jansBackchannelAuthnReqSigAlg varchar(64) YES None jans Backchannel Authn Req Sig Alg jansBackchannelUsrCodeParameter smallint YES None jans Backchannel Usr Code Parameter jansClntAuthz # Field Type Null Key Default Comment doc_id varchar(100) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansClntId json YES None jans Clnt id jansUsrId varchar(64) YES MUL None jans user id exp datetime(3) YES None jans Exp del smallint YES MUL None del jansScope json YES None jans Attr Scope jansCustomScr # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES MUL None XRI i-number displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None jansScr text YES None Attr that contains script (python, java script) jansScrTyp varchar(64) YES MUL None Attr that contains script type (e.g. python, java script) jansProgLng varchar(64) YES None programming language jansModuleProperty json YES None Module property jansConfProperty json YES None Conf property jansLevel int YES None Level jansRevision int YES None Revision jansEnabled smallint YES None Status of the entry, used by many objectclasses jansScrError text YES None Attr that contains first error which application get during it execution jansAlias json YES None jansAlias jansDeviceRegistration # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None jansDeviceKeyHandle varchar(128) YES MUL None jansDeviceKeyHandle jansDeviceHashCode int YES MUL None jansDeviceHashCode jansApp varchar(96) YES MUL None jansApp jansDeviceRegistrationConf text YES None jansDeviceRegistrationConf jansDeviceNotificationConf varchar(64) YES None Extended push notification configuration jansNickName varchar(64) YES None jansNickName jansDeviceData tinytext YES None jansDeviceData jansCounter int YES None jansCounter jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses del smallint YES MUL None del exp datetime(3) YES None jans Exp personInum varchar(64) YES MUL None Inum of a person creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansLastAccessTime datetime(3) YES None Last access time jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None jansDocument # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number ou varchar(64) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None document varchar(64) YES None Save Document in DB creationDate datetime(3) YES None Creation Date used for password reset requests jansModuleProperty json YES None Module property jansLevel int YES None Level jansRevision int YES None Revision jansEnabled smallint YES None Status of the entry, used by many objectclasses jansAlias json YES None jansAlias jansFido2AuthnEntry # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansApp varchar(96) YES MUL None jansApp jansSessStateId varchar(64) YES None jansSessStateId jansCodeChallenge varchar(64) YES MUL None OX PKCE code challenge jansCodeChallengeHash int YES MUL None OX code challenge hash personInum varchar(64) YES MUL None Inum of a person jansAuthData text YES None jansAuthData jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses exp datetime(3) YES None jans Exp del smallint YES MUL None del jansFido2RegistrationEntry # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier creationDate datetime(3) YES MUL None Creation Date used for password reset requests displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansApp varchar(96) YES MUL None jansApp jansSessStateId varchar(64) YES None jansSessStateId jansCodeChallenge varchar(64) YES MUL None OX PKCE code challenge jansCodeChallengeHash int YES MUL None OX code challenge hash jansPublicKeyId varchar(96) YES MUL None jansPublicKeyId jansPublicKeyIdHash int YES MUL None jansPublicKeyIdHash personInum varchar(64) YES MUL None Inum of a person jansRegistrationData text YES None jansRegistrationData jansDeviceData tinytext YES None jansDeviceData jansDeviceNotificationConf varchar(64) YES None Extended push notification configuration jansCounter int YES None jansCounter jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses exp datetime(3) YES None jans Exp del smallint YES MUL None del jansGrant # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None grtId varchar(64) YES None jans grant id iat datetime(3) YES None jans Creation jansGrp # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number member json YES None o varchar(64) YES None owner varchar(64) YES None seeAlso varchar(64) YES None jansMetaCreated varchar(64) YES None jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None jansInumMap # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number jansPrimaryKeyAttrName varchar(64) YES None Primary Key Attribute Name jansPrimaryKeyValue varchar(64) YES None Primary Key Value jansSecondaryKeyAttrName varchar(64) YES None Secondary Key Attribute Name jansSecondaryKeyValue varchar(64) YES None Secondary Key Value jansTertiaryKeyAttrName varchar(64) YES None Tertiary Key Attribute Name jansTertiaryKeyValue varchar(64) YES None Tertiary Key Value jansMetric # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None uniqueIdentifier varchar(64) YES None jansStartDate datetime(3) YES MUL None Start date jansEndDate datetime(3) YES MUL None End date jansAppTyp varchar(64) YES MUL None jans App Typ jansMetricTyp varchar(64) YES MUL None Metric type creationDate datetime(3) YES None Creation Date used for password reset requests del smallint YES MUL None del exp datetime(3) YES None jans Exp jansData text YES None OX data jansHost varchar(64) YES None jans host jansOrganization # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None description varchar(768) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansCustomMessage varchar(128) YES None exclude custom welcome message jansFaviconImage varchar(64) YES None TODO - Stores URL of favicon jansLogoImage varchar(64) YES None Logo used by exclude for default look and feel. jansManager varchar(64) YES None Used to specify if a person has the manager role jansManagerGrp tinytext YES None Used in organizatoin entry to specifies the dn of the group that has admin priviledges in exclude. jansOrgShortName varchar(64) YES None Short description, as few letters as possible, no spaces. jansThemeColor varchar(64) YES None exclude login page configuration inum varchar(64) YES None XRI i-number l varchar(64) YES None mail varchar(96) YES None memberOf json YES None o varchar(64) YES None jansCreationTimestamp datetime(3) YES None Registration time jansRegistrationConf varchar(64) YES None Registration Conf postalCode varchar(16) YES None st varchar(64) YES None street tinytext YES None telephoneNumber varchar(20) YES None title varchar(64) YES None uid varchar(64) YES MUL None jansLogoPath varchar(64) YES None jansLogoPath jansStatus varchar(16) YES None Status of the entry, used by many objectclasses jansFaviconPath varchar(64) YES None jansFaviconPath jansPairwiseIdentifier # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansSectorIdentifier varchar(64) YES None jans Sector Identifier jansClntId json YES None jans Clnt id jansUsrId varchar(64) YES None jans user id jansPar # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES MUL None Identifier jansAttrs text YES None Attrs exp datetime(3) YES None jans Exp del smallint YES MUL None del jansPassResetReq # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansGuid varchar(64) YES None A random string to mark temporary tokens personInum varchar(64) YES None Inum of a person jansPerson # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansAssociatedClnt json YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. c varchar(2) YES None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries givenName varchar(128) YES MUL None jansManagedOrganizations varchar(64) YES None Used to track with which organizations a person is associated jansOptOuts json YES None White pages attributes restricted by person in exclude profile management jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number mail varchar(96) YES MUL None memberOf json YES None o varchar(64) YES None jansPersistentJWT json YES None jans Persistent JWT jansCreationTimestamp datetime(3) YES None Registration time jansExtUid json YES None jansOTPCache json YES None Stores a used OTP to prevent a hacker from using it again. Complementary to jansExtUid attribute jansLastLogonTime datetime(3) YES None Last logon time jansActive smallint YES None jansAddress json YES None jansEmail json YES None jansEntitlements json YES None jansExtId varchar(128) YES None jansImsValue json YES None jansMetaCreated varchar(64) YES None jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None jansNameFormatted tinytext YES None jansPhoneValue json YES None jansPhotos json YES None jansProfileURL varchar(256) YES None jansRole json YES None jansTitle varchar(64) YES None jansUsrTyp varchar(64) YES None jansHonorificPrefix varchar(64) YES None jansHonorificSuffix varchar(64) YES None jans509Certificate json YES None jansPassExpDate datetime(3) YES None Pass Exp date, represented as an ISO 8601 (YYYY-MM-DD) format persistentId varchar(64) YES None PersistentId middleName varchar(64) YES None Middle name(s) nickname varchar(64) YES None Casual name of the End-Usr jansPrefUsrName varchar(64) YES None Shorthand Name profile varchar(64) YES None Profile page URL of the person picture tinytext YES None Profile picture URL of the person website varchar(64) YES None Web page or blog URL of the person emailVerified smallint YES None True if the e-mail address of the person has been verified; otherwise false gender varchar(32) YES None Gender of the person either female or male birthdate datetime(3) YES None Birthday of the person, represented as an ISO 8601:2004 [ISO8601-2004] YYYY-MM-DD format zoneinfo varchar(64) YES None Time zone database representing the End-Usrs time zone. For example, Europe/Paris or America/Los_Angeles locale varchar(64) YES None Locale of the person, represented as a BCP47 [RFC5646] language tag phoneNumberVerified smallint YES None True if the phone number of the person has been verified, otherwise false address tinytext YES None OpenID Connect formatted JSON object representing the address of the person updatedAt datetime(3) YES None Time the information of the person was last updated. Seconds from 1970-01-01T0:0:0Z preferredLanguage varchar(64) YES None preferred written or spoken language for a person role json YES None Role secretAnswer tinytext YES None Secret Answer secretQuestion tinytext YES None Secret Question seeAlso varchar(64) YES None sn varchar(128) YES MUL None cn varchar(128) YES None transientId varchar(64) YES None TransientId uid varchar(64) YES MUL None userPassword varchar(256) YES None st varchar(64) YES None street tinytext YES None l varchar(64) YES None jansCountInvalidLogin varchar(64) YES None Invalid login attempts count jansEnrollmentCode varchar(64) YES None jansEnrollmentCode jansIMAPData varchar(64) YES None This data has information about your imap connection jansPPID json YES None Persistent Pairwise ID for OpenID Connect jansGuid varchar(64) YES None A random string to mark temporary tokens jansPreferredMethod varchar(64) YES None Casa - Preferred method to use for user authentication userCertificate blob YES None jansOTPDevices varchar(512) YES None Casa - Json representation of OTP devices. Complementary to jansExtUid attribute jansMobileDevices varchar(512) YES None Casa - Json representation of mobile devices. Complementary to mobile attribute jansTrustedDevices text YES None Casa - Devices with which strong authentication may be skipped jansStrongAuthPolicy varchar(64) YES None Casa - 2FA Enforcement Policy for User jansUnlinkedExternalUids varchar(64) YES None Casa - List of unlinked social accounts (ie disabled jansExtUids) jansBackchannelDeviceRegistrationTkn varchar(64) YES None jans Backchannel Device Registration Tkn jansBackchannelUsrCode varchar(64) YES None jans Backchannel Usr Code telephoneNumber varchar(20) YES None mobile json YES None carLicense varchar(64) YES None vehicle license or registration plate facsimileTelephoneNumber varchar(20) YES None departmentNumber varchar(64) YES None identifies a department within an organization employeeType varchar(64) YES None type of employment for a person manager tinytext YES None postOfficeBox varchar(64) YES None employeeNumber varchar(64) YES None numerically identifies an employee within an organization preferredDeliveryMethod varchar(50) YES None roomNumber varchar(64) YES None secretary tinytext YES None homePostalAddress tinytext YES None postalCode varchar(16) YES None description varchar(768) YES None title varchar(64) YES None jansAdminUIRole json YES None jansAdminUIRole jansPushApp # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansId varchar(128) YES None Identifier jansName varchar(64) YES None Name jansPushAppConf varchar(64) YES None jansPush application configuration jansPushDevice # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansUsrId varchar(64) YES None jans user id jansId varchar(128) YES None Identifier jansPushApp tinytext YES None jansPush application DN jansPushDeviceConf varchar(64) YES None jansPush device configuration jansTyp varchar(64) YES None jans type jansRp # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier dat text YES None OX data jansScope # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansDefScope smallint YES None Track the default scope for an custom OAuth2 Scope. description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries inum varchar(64) YES None XRI i-number jansScopeTyp varchar(64) YES None OX Attr Scope type creatorId varchar(64) YES None Creator Id creatorTyp varchar(64) YES None Creator type creatorAttrs varchar(64) YES None Creator Attrs creationDate datetime(3) YES None Creation Date used for password reset requests jansClaim json YES None jans Attr Claim jansScrDn json YES None Script object DN jansGrpClaims smallint YES None jans Grp Attr Claims (true or false) jansId varchar(128) YES MUL None Identifier jansIconUrl varchar(64) YES None jans icon url jansUmaPolicyScrDn tinytext YES None OX policy script Dn jansAttrs text YES None Attrs exp datetime(3) YES None jans Exp del smallint YES MUL None del jansScr # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number jansScr text YES None Attr that contains script (python, java script) jansScrTyp varchar(64) YES None Attr that contains script type (e.g. python, java script) jansSectorIdentifier # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier description varchar(768) YES None jansRedirectURI json YES None jans Redirect URI jansClntId json YES None jans Clnt id jansSessId # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier sid varchar(64) YES MUL None Sess Identifier creationDate datetime(3) YES None Creation Date used for password reset requests exp datetime(3) YES None jans Exp del smallint YES MUL None del jansLastAccessTime datetime(3) YES None Last access time jansUsrDN varchar(128) YES MUL None jans Usr DN authnTime datetime(3) YES None jans Authn Time jansState varchar(64) YES None jansState jansSessState text YES None jans Sess State jansPermissionGranted smallint YES None jans Permission Granted jansAsJwt smallint YES None Boolean field to indicate whether object is used as JWT jansJwt text YES None JWT representation of the object or otherwise jwt associated with the object jansPermissionGrantedMap text YES None jans Permission Granted Map jansInvolvedClnts text YES None Involved clients deviceSecret varchar(64) YES MUL None deviceSecret jansSessAttr text YES None jansSessAttr jansSsa # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number o varchar(64) YES None jansAttrs text YES None Attrs description varchar(768) YES None exp datetime(3) YES None jans Exp del smallint YES None del jansState varchar(64) YES None jansState creatorId varchar(64) YES None Creator Id creatorTyp varchar(64) YES None Creator type creationDate datetime(3) YES None Creation Date used for password reset requests jansStatEntry # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES MUL None Identifier dat text YES None OX data jansData text YES None OX data attr text YES None Attrs jansToken # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authnTime datetime(3) YES None jans Authn Time authzCode varchar(64) YES MUL None jans authorization code iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del grtId varchar(64) YES MUL None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknCde varchar(80) YES MUL None jans Tkn Code tknTyp varchar(32) YES None jans Tkn Typ usrId varchar(64) YES None jans user id jansUsrDN varchar(128) YES None jans Usr DN clnId varchar(64) YES None jans Clnt id acr varchar(48) YES None uuid varchar(64) YES None Unique identifier chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims ssnId varchar(64) YES MUL None jans Sess DN attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash dpop varchar(64) YES None DPoP Proof jansU2fReq # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansReqId varchar(64) YES None jansReqId jansReq text YES None jansReq jansSessStateId varchar(64) YES None jansSessStateId del smallint YES MUL None del exp datetime(3) YES None jans Exp personInum varchar(64) YES None Inum of a person creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansUmaPCT # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None clnId varchar(64) YES None jans Clnt id iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del tknCde varchar(80) YES MUL None jans Tkn Code ssnId varchar(64) YES None jans Sess DN jansClaimValues varchar(64) YES None Claim Values dpop varchar(64) YES None DPoP Proof authnTime datetime(3) YES None jans Authn Time authzCode varchar(64) YES None jans authorization code grtId varchar(64) YES None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknTyp varchar(32) YES None jans Tkn Typ usrId varchar(64) YES None jans user id jansUsrDN varchar(128) YES None jans Usr DN acr varchar(48) YES None uuid varchar(64) YES None Unique identifier chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash jansUmaRPT # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authnTime datetime(3) YES None jans Authn Time clnId varchar(64) YES None jans Clnt id iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES None del tknCde varchar(80) YES None jans Tkn Code usrId varchar(64) YES None jans user id ssnId varchar(64) YES None jans Sess DN jansUmaPermission json YES None jans uma permission uuid varchar(64) YES None Unique identifier dpop varchar(64) YES None DPoP Proof authzCode varchar(64) YES None jans authorization code grtId varchar(64) YES None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknTyp varchar(32) YES None jans Tkn Typ jansUsrDN varchar(128) YES None jans Usr DN acr varchar(48) YES None chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash jansUmaResource # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries inum varchar(64) YES None XRI i-number owner varchar(64) YES None jansAssociatedClnt json YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. jansUmaScope varchar(768) YES MUL None URI reference of scope descriptor jansFaviconImage varchar(64) YES None TODO - Stores URL of favicon jansGrp varchar(64) YES None Group jansId varchar(128) YES MUL None Identifier jansResource tinytext YES None Host path jansRevision int YES None Revision jansTyp varchar(64) YES None jans type jansScopeExpression text YES None Scope expression iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del description varchar(768) YES None jansUmaResourcePermission # Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None exp datetime(3) YES None jans Exp del smallint YES None del jansUmaScope varchar(768) YES None URI reference of scope descriptor jansConfCode varchar(64) YES None jans configuration code jansResourceSetId varchar(64) YES None jans resource set id jansAttrs text YES None Attrs jansTicket varchar(64) YES MUL None jans ticket jansStatus varchar(16) YES None Status of the entry, used by many objectclasses", "title": "MySQL Schema"}, {"location": "janssen-server/reference/database/mysql-schema/#mysql-schema", "text": "", "title": "MySQL Schema"}, {"location": "janssen-server/reference/database/mysql-schema/#tables", "text": "Table names adsPrjDeployment agmFlow agmFlowRun jansAppConf jansAttr jansCache jansCibaReq jansClnt jansClntAuthz jansCustomScr jansDeviceRegistration jansDocument jansFido2AuthnEntry jansFido2RegistrationEntry jansGrant jansGrp jansInumMap jansMetric jansOrganization jansPairwiseIdentifier jansPar jansPassResetReq jansPerson jansPushApp jansPushDevice jansRp jansScope jansScr jansSectorIdentifier jansSessId jansSsa jansStatEntry jansToken jansU2fReq jansUmaPCT jansUmaRPT jansUmaResource jansUmaResourcePermission", "title": "Tables"}, {"location": "janssen-server/reference/database/mysql-schema/#adsprjdeployment", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansStartDate datetime(3) YES None Start date jansActive smallint YES None jansEndDate datetime(3) YES None End date adsPrjAssets longtext YES None Assets of an ADS project adsPrjDeplDetails text YES None Misc details associated to an ADS project", "title": "adsPrjDeployment"}, {"location": "janssen-server/reference/database/mysql-schema/#agmflow", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None agFlowQname varchar(64) YES None Full name of an agama flow agFlowMeta text YES None Metadata of an agama flow jansScr text YES None Attr that contains script (python, java script) jansEnabled smallint YES None Status of the entry, used by many objectclasses jansScrError text YES None Attr that contains first error which application get during it execution agFlowTrans text YES None Transpiled code of an agama flow jansRevision int YES None Revision jansCustomMessage varchar(128) YES None exclude custom welcome message", "title": "agmFlow"}, {"location": "janssen-server/reference/database/mysql-schema/#agmflowrun", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier agFlowSt text YES None Details of a running agama flow instance agFlowEncCont mediumtext YES None Continuation associated to a running agama flow instance jansCustomMessage varchar(128) YES None exclude custom welcome message exp datetime(3) YES None jans Exp", "title": "agmFlowRun"}, {"location": "janssen-server/reference/database/mysql-schema/#jansappconf", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None ou varchar(64) YES None description varchar(768) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansHostname varchar(64) YES None The hostname of the Jans Server instance jansLastUpd datetime(3) YES None Monitors last time the server was able to connect to the monitoring system. jansManager varchar(64) YES None Used to specify if a person has the manager role jansOrgProfileMgt smallint YES None enable or disable profile management feature in exclude jansScimEnabled smallint YES None exclude SCIM feature - enabled or disabled jansEmail json YES None jansSmtpConf json YES None SMTP configuration jansSslExpiry varchar(64) YES None SAML Trust Relationship configuration jansStatus varchar(16) YES None Status of the entry, used by many objectclasses jansUrl varchar(64) YES None Jans instance URL inum varchar(64) YES None XRI i-number o varchar(64) YES None jansAuthMode varchar(64) YES None jansDbAuth json YES None Custom IDP authentication configuration jansLogViewerConfig varchar(64) YES None Log viewer configuration jansLogConfigLocation varchar(64) YES None Path to external log4j2.xml jansCacheConf text YES None Cache configuration jansDocStoreConf text YES None jansDocStoreConf jansSoftVer varchar(64) YES None userPassword varchar(256) YES None jansConfDyn text YES None jans Dyn Conf jansConfErrors text YES None jans Errors Conf jansConfStatic text YES None jans Static Conf jansConfWebKeys text YES None jans Web Keys Conf jansWebKeysSettings varchar(64) YES None jans Web Keys Conf jansConfApp text YES None jans App Conf jansRevision int YES None Revision", "title": "jansAppConf"}, {"location": "janssen-server/reference/database/mysql-schema/#jansattr", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries jansAttrEditTyp json YES None Specify in exclude who can update an attribute, admin or user jansAttrName varchar(64) YES MUL None Specify an identifier for an attribute. May be multi-value where an attribute has two names, like givenName and first-name. jansAttrOrigin varchar(64) YES MUL None Specify the person objectclass associated with the attribute, used for display purposes in exclude. jansAttrSystemEditTyp varchar(64) YES None TODO - still required? jansAttrTyp varchar(64) YES None Data type of attribute. Values can be string, photo, numeric, date jansClaimName varchar(64) YES None Used by jans in conjunction with jansttributeName to map claims to attributes in datastore. jansAttrUsgTyp varchar(64) YES None TODO - Usg? Value can be OpenID jansAttrViewTyp json YES None Specify in exclude who can view an attribute, admin or user jansSAML1URI varchar(64) YES None SAML 1 uri of attribute jansSAML2URI varchar(64) YES None SAML 2 uri of attribute jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number jansMultivaluedAttr smallint YES None jansHideOnDiscovery smallint YES None jansNameIdTyp varchar(64) YES None NameId Typ jansScimCustomAttr smallint YES None jansSourceAttr varchar(64) YES None Source Attr for this Attr seeAlso varchar(64) YES None urn varchar(128) YES None jansRegExp varchar(64) YES None Regular expression used to validate attribute data jansTooltip varchar(64) YES None Custom tooltip to be shown on the UI jansValidation tinytext YES None This data has information about attribute Validation", "title": "jansAttr"}, {"location": "janssen-server/reference/database/mysql-schema/#janscache", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None uuid varchar(64) YES None Unique identifier iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del dat text YES None OX data", "title": "jansCache"}, {"location": "janssen-server/reference/database/mysql-schema/#janscibareq", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authReqId varchar(64) YES None Authn request id clnId varchar(64) YES None jans Clnt id usrId varchar(64) YES None jans user id creationDate datetime(3) YES None Creation Date used for password reset requests exp datetime(3) YES None jans Exp jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses", "title": "jansCibaReq"}, {"location": "janssen-server/reference/database/mysql-schema/#jansclnt", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None o varchar(64) YES None jansGrp varchar(64) YES None Group displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries displayNameLocalized json YES None jans Display Name Localized description varchar(768) YES MUL None inum varchar(64) YES MUL None XRI i-number jansAppTyp varchar(64) YES None jans App Typ jansClntIdIssuedAt datetime(3) YES None jans Clnt Issued At jansClntSecret varchar(64) YES None jans Clnt Secret jansClntSecretExpAt datetime(3) YES MUL None Date client expires exp datetime(3) YES None jans Exp del smallint YES MUL None del jansClntURI tinytext YES None jans Clnt URI jansClntURILocalized json YES None jans Clnt URI localized jansContact json YES None jans Contact jansDefAcrValues json YES None jans Def Acr Values jansDefMaxAge int YES None jans Def Max Age jansGrantTyp json YES None jans Grant Typ jansIdTknEncRespAlg varchar(64) YES None jans ID Tkn Enc Resp Alg jansIdTknEncRespEnc varchar(64) YES None jans ID Tkn Enc Resp Enc jansIdTknSignedRespAlg varchar(64) YES None jans ID Tkn Signed Resp Alg jansInitiateLoginURI tinytext YES None jans Initiate Login URI jansJwksURI tinytext YES None jans JWKs URI jansJwks text YES None jans JWKs jansLogoURI tinytext YES None jans Logo URI jansLogoURILocalized json YES None jans Logo URI localized jansPolicyURI tinytext YES None jans Policy URI jansPolicyURILocalized json YES None jans Policy URI localized jansPostLogoutRedirectURI json YES None jans Post Logout Redirect URI jansRedirectURI json YES None jans Redirect URI jansRegistrationAccessTkn varchar(64) YES MUL None jans Registration Access Tkn jansReqObjSigAlg varchar(64) YES None jans Req Obj Sig Alg jansReqObjEncAlg varchar(64) YES None jans Req Obj Enc Alg jansReqObjEncEnc varchar(64) YES None jans Req Obj Enc Enc jansReqURI json YES None jans Req URI jansRespTyp json YES None jans Resp Typ jansScope json YES None jans Attr Scope jansClaim json YES None jans Attr Claim jansSectorIdentifierURI tinytext YES None jans Sector Identifier URI jansSignedRespAlg varchar(64) YES None jans Signed Resp Alg jansSubjectTyp varchar(64) YES None jans Subject Typ jansTknEndpointAuthMethod varchar(64) YES None jans Tkn Endpoint Auth Method jansTknEndpointAuthSigAlg varchar(64) YES None jans Tkn Endpoint Auth Sig Alg jansTosURI tinytext YES None jans TOS URI jansTosURILocalized json YES None jans Tos URI localized jansTrustedClnt smallint YES None jans Trusted Clnt jansUsrInfEncRespAlg varchar(64) YES None jans Usr Inf Enc Resp Alg jansUsrInfEncRespEnc varchar(64) YES None jans Usr Inf Enc Resp Enc jansExtraConf varchar(64) YES None jans additional configuration jansClaimRedirectURI json YES None Claim Redirect URI jansLastAccessTime datetime(3) YES None Last access time jansLastLogonTime datetime(3) YES None Last logon time jansPersistClntAuthzs smallint YES None jans Persist Clnt Authzs jansInclClaimsInIdTkn smallint YES None jans Incl Claims In Id Tkn jansRefreshTknLife int YES None Life of refresh token jansDisabled smallint YES None Status of client jansLogoutURI json YES None jans Policy URI jansLogoutSessRequired smallint YES None jans Policy URI jansdId varchar(64) YES None jansd Id jansAuthorizedOrigins json YES None jans Authorized Origins tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash jansAccessTknAsJwt smallint YES None jansauth - indicator whether to return access token as JWT jansAccessTknSigAlg varchar(64) YES None jansauth - access token signing algorithm jansAccessTknLife int YES None Life of access token jansSoftId varchar(64) YES None Soft Identifier jansSoftVer varchar(64) YES None jansSoftStatement text YES None Soft Statement jansRptAsJwt smallint YES None jansRptAsJwt jansAttrs text YES None Attrs jansBackchannelTknDeliveryMode varchar(64) YES None jans Backchannel Tkn Delivery Mode jansBackchannelClntNotificationEndpoint varchar(64) YES None jans Backchannel Clnt Notification Endpoint jansBackchannelAuthnReqSigAlg varchar(64) YES None jans Backchannel Authn Req Sig Alg jansBackchannelUsrCodeParameter smallint YES None jans Backchannel Usr Code Parameter", "title": "jansClnt"}, {"location": "janssen-server/reference/database/mysql-schema/#jansclntauthz", "text": "Field Type Null Key Default Comment doc_id varchar(100) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansClntId json YES None jans Clnt id jansUsrId varchar(64) YES MUL None jans user id exp datetime(3) YES None jans Exp del smallint YES MUL None del jansScope json YES None jans Attr Scope", "title": "jansClntAuthz"}, {"location": "janssen-server/reference/database/mysql-schema/#janscustomscr", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES MUL None XRI i-number displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None jansScr text YES None Attr that contains script (python, java script) jansScrTyp varchar(64) YES MUL None Attr that contains script type (e.g. python, java script) jansProgLng varchar(64) YES None programming language jansModuleProperty json YES None Module property jansConfProperty json YES None Conf property jansLevel int YES None Level jansRevision int YES None Revision jansEnabled smallint YES None Status of the entry, used by many objectclasses jansScrError text YES None Attr that contains first error which application get during it execution jansAlias json YES None jansAlias", "title": "jansCustomScr"}, {"location": "janssen-server/reference/database/mysql-schema/#jansdeviceregistration", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None jansDeviceKeyHandle varchar(128) YES MUL None jansDeviceKeyHandle jansDeviceHashCode int YES MUL None jansDeviceHashCode jansApp varchar(96) YES MUL None jansApp jansDeviceRegistrationConf text YES None jansDeviceRegistrationConf jansDeviceNotificationConf varchar(64) YES None Extended push notification configuration jansNickName varchar(64) YES None jansNickName jansDeviceData tinytext YES None jansDeviceData jansCounter int YES None jansCounter jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses del smallint YES MUL None del exp datetime(3) YES None jans Exp personInum varchar(64) YES MUL None Inum of a person creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansLastAccessTime datetime(3) YES None Last access time jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None", "title": "jansDeviceRegistration"}, {"location": "janssen-server/reference/database/mysql-schema/#jansdocument", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number ou varchar(64) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries description varchar(768) YES None document varchar(64) YES None Save Document in DB creationDate datetime(3) YES None Creation Date used for password reset requests jansModuleProperty json YES None Module property jansLevel int YES None Level jansRevision int YES None Revision jansEnabled smallint YES None Status of the entry, used by many objectclasses jansAlias json YES None jansAlias", "title": "jansDocument"}, {"location": "janssen-server/reference/database/mysql-schema/#jansfido2authnentry", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansApp varchar(96) YES MUL None jansApp jansSessStateId varchar(64) YES None jansSessStateId jansCodeChallenge varchar(64) YES MUL None OX PKCE code challenge jansCodeChallengeHash int YES MUL None OX code challenge hash personInum varchar(64) YES MUL None Inum of a person jansAuthData text YES None jansAuthData jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses exp datetime(3) YES None jans Exp del smallint YES MUL None del", "title": "jansFido2AuthnEntry"}, {"location": "janssen-server/reference/database/mysql-schema/#jansfido2registrationentry", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier creationDate datetime(3) YES MUL None Creation Date used for password reset requests displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansApp varchar(96) YES MUL None jansApp jansSessStateId varchar(64) YES None jansSessStateId jansCodeChallenge varchar(64) YES MUL None OX PKCE code challenge jansCodeChallengeHash int YES MUL None OX code challenge hash jansPublicKeyId varchar(96) YES MUL None jansPublicKeyId jansPublicKeyIdHash int YES MUL None jansPublicKeyIdHash personInum varchar(64) YES MUL None Inum of a person jansRegistrationData text YES None jansRegistrationData jansDeviceData tinytext YES None jansDeviceData jansDeviceNotificationConf varchar(64) YES None Extended push notification configuration jansCounter int YES None jansCounter jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses exp datetime(3) YES None jans Exp del smallint YES MUL None del", "title": "jansFido2RegistrationEntry"}, {"location": "janssen-server/reference/database/mysql-schema/#jansgrant", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None grtId varchar(64) YES None jans grant id iat datetime(3) YES None jans Creation", "title": "jansGrant"}, {"location": "janssen-server/reference/database/mysql-schema/#jansgrp", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number member json YES None o varchar(64) YES None owner varchar(64) YES None seeAlso varchar(64) YES None jansMetaCreated varchar(64) YES None jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None", "title": "jansGrp"}, {"location": "janssen-server/reference/database/mysql-schema/#jansinummap", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansStatus varchar(16) YES MUL None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number jansPrimaryKeyAttrName varchar(64) YES None Primary Key Attribute Name jansPrimaryKeyValue varchar(64) YES None Primary Key Value jansSecondaryKeyAttrName varchar(64) YES None Secondary Key Attribute Name jansSecondaryKeyValue varchar(64) YES None Secondary Key Value jansTertiaryKeyAttrName varchar(64) YES None Tertiary Key Attribute Name jansTertiaryKeyValue varchar(64) YES None Tertiary Key Value", "title": "jansInumMap"}, {"location": "janssen-server/reference/database/mysql-schema/#jansmetric", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None uniqueIdentifier varchar(64) YES None jansStartDate datetime(3) YES MUL None Start date jansEndDate datetime(3) YES MUL None End date jansAppTyp varchar(64) YES MUL None jans App Typ jansMetricTyp varchar(64) YES MUL None Metric type creationDate datetime(3) YES None Creation Date used for password reset requests del smallint YES MUL None del exp datetime(3) YES None jans Exp jansData text YES None OX data jansHost varchar(64) YES None jans host", "title": "jansMetric"}, {"location": "janssen-server/reference/database/mysql-schema/#jansorganization", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None c varchar(2) YES None description varchar(768) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansCustomMessage varchar(128) YES None exclude custom welcome message jansFaviconImage varchar(64) YES None TODO - Stores URL of favicon jansLogoImage varchar(64) YES None Logo used by exclude for default look and feel. jansManager varchar(64) YES None Used to specify if a person has the manager role jansManagerGrp tinytext YES None Used in organizatoin entry to specifies the dn of the group that has admin priviledges in exclude. jansOrgShortName varchar(64) YES None Short description, as few letters as possible, no spaces. jansThemeColor varchar(64) YES None exclude login page configuration inum varchar(64) YES None XRI i-number l varchar(64) YES None mail varchar(96) YES None memberOf json YES None o varchar(64) YES None jansCreationTimestamp datetime(3) YES None Registration time jansRegistrationConf varchar(64) YES None Registration Conf postalCode varchar(16) YES None st varchar(64) YES None street tinytext YES None telephoneNumber varchar(20) YES None title varchar(64) YES None uid varchar(64) YES MUL None jansLogoPath varchar(64) YES None jansLogoPath jansStatus varchar(16) YES None Status of the entry, used by many objectclasses jansFaviconPath varchar(64) YES None jansFaviconPath", "title": "jansOrganization"}, {"location": "janssen-server/reference/database/mysql-schema/#janspairwiseidentifier", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansSectorIdentifier varchar(64) YES None jans Sector Identifier jansClntId json YES None jans Clnt id jansUsrId varchar(64) YES None jans user id", "title": "jansPairwiseIdentifier"}, {"location": "janssen-server/reference/database/mysql-schema/#janspar", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES MUL None Identifier jansAttrs text YES None Attrs exp datetime(3) YES None jans Exp del smallint YES MUL None del", "title": "jansPar"}, {"location": "janssen-server/reference/database/mysql-schema/#janspassresetreq", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None creationDate datetime(3) YES MUL None Creation Date used for password reset requests jansGuid varchar(64) YES None A random string to mark temporary tokens personInum varchar(64) YES None Inum of a person", "title": "jansPassResetReq"}, {"location": "janssen-server/reference/database/mysql-schema/#jansperson", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansAssociatedClnt json YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. c varchar(2) YES None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries givenName varchar(128) YES MUL None jansManagedOrganizations varchar(64) YES None Used to track with which organizations a person is associated jansOptOuts json YES None White pages attributes restricted by person in exclude profile management jansStatus varchar(16) YES None Status of the entry, used by many objectclasses inum varchar(64) YES MUL None XRI i-number mail varchar(96) YES MUL None memberOf json YES None o varchar(64) YES None jansPersistentJWT json YES None jans Persistent JWT jansCreationTimestamp datetime(3) YES None Registration time jansExtUid json YES None jansOTPCache json YES None Stores a used OTP to prevent a hacker from using it again. Complementary to jansExtUid attribute jansLastLogonTime datetime(3) YES None Last logon time jansActive smallint YES None jansAddress json YES None jansEmail json YES None jansEntitlements json YES None jansExtId varchar(128) YES None jansImsValue json YES None jansMetaCreated varchar(64) YES None jansMetaLastMod varchar(64) YES None jansMetaLocation tinytext YES None jansMetaVer varchar(64) YES None jansNameFormatted tinytext YES None jansPhoneValue json YES None jansPhotos json YES None jansProfileURL varchar(256) YES None jansRole json YES None jansTitle varchar(64) YES None jansUsrTyp varchar(64) YES None jansHonorificPrefix varchar(64) YES None jansHonorificSuffix varchar(64) YES None jans509Certificate json YES None jansPassExpDate datetime(3) YES None Pass Exp date, represented as an ISO 8601 (YYYY-MM-DD) format persistentId varchar(64) YES None PersistentId middleName varchar(64) YES None Middle name(s) nickname varchar(64) YES None Casual name of the End-Usr jansPrefUsrName varchar(64) YES None Shorthand Name profile varchar(64) YES None Profile page URL of the person picture tinytext YES None Profile picture URL of the person website varchar(64) YES None Web page or blog URL of the person emailVerified smallint YES None True if the e-mail address of the person has been verified; otherwise false gender varchar(32) YES None Gender of the person either female or male birthdate datetime(3) YES None Birthday of the person, represented as an ISO 8601:2004 [ISO8601-2004] YYYY-MM-DD format zoneinfo varchar(64) YES None Time zone database representing the End-Usrs time zone. For example, Europe/Paris or America/Los_Angeles locale varchar(64) YES None Locale of the person, represented as a BCP47 [RFC5646] language tag phoneNumberVerified smallint YES None True if the phone number of the person has been verified, otherwise false address tinytext YES None OpenID Connect formatted JSON object representing the address of the person updatedAt datetime(3) YES None Time the information of the person was last updated. Seconds from 1970-01-01T0:0:0Z preferredLanguage varchar(64) YES None preferred written or spoken language for a person role json YES None Role secretAnswer tinytext YES None Secret Answer secretQuestion tinytext YES None Secret Question seeAlso varchar(64) YES None sn varchar(128) YES MUL None cn varchar(128) YES None transientId varchar(64) YES None TransientId uid varchar(64) YES MUL None userPassword varchar(256) YES None st varchar(64) YES None street tinytext YES None l varchar(64) YES None jansCountInvalidLogin varchar(64) YES None Invalid login attempts count jansEnrollmentCode varchar(64) YES None jansEnrollmentCode jansIMAPData varchar(64) YES None This data has information about your imap connection jansPPID json YES None Persistent Pairwise ID for OpenID Connect jansGuid varchar(64) YES None A random string to mark temporary tokens jansPreferredMethod varchar(64) YES None Casa - Preferred method to use for user authentication userCertificate blob YES None jansOTPDevices varchar(512) YES None Casa - Json representation of OTP devices. Complementary to jansExtUid attribute jansMobileDevices varchar(512) YES None Casa - Json representation of mobile devices. Complementary to mobile attribute jansTrustedDevices text YES None Casa - Devices with which strong authentication may be skipped jansStrongAuthPolicy varchar(64) YES None Casa - 2FA Enforcement Policy for User jansUnlinkedExternalUids varchar(64) YES None Casa - List of unlinked social accounts (ie disabled jansExtUids) jansBackchannelDeviceRegistrationTkn varchar(64) YES None jans Backchannel Device Registration Tkn jansBackchannelUsrCode varchar(64) YES None jans Backchannel Usr Code telephoneNumber varchar(20) YES None mobile json YES None carLicense varchar(64) YES None vehicle license or registration plate facsimileTelephoneNumber varchar(20) YES None departmentNumber varchar(64) YES None identifies a department within an organization employeeType varchar(64) YES None type of employment for a person manager tinytext YES None postOfficeBox varchar(64) YES None employeeNumber varchar(64) YES None numerically identifies an employee within an organization preferredDeliveryMethod varchar(50) YES None roomNumber varchar(64) YES None secretary tinytext YES None homePostalAddress tinytext YES None postalCode varchar(16) YES None description varchar(768) YES None title varchar(64) YES None jansAdminUIRole json YES None jansAdminUIRole", "title": "jansPerson"}, {"location": "janssen-server/reference/database/mysql-schema/#janspushapp", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None displayName varchar(128) YES None preferred name of a person to be used when displaying entries jansId varchar(128) YES None Identifier jansName varchar(64) YES None Name jansPushAppConf varchar(64) YES None jansPush application configuration", "title": "jansPushApp"}, {"location": "janssen-server/reference/database/mysql-schema/#janspushdevice", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansUsrId varchar(64) YES None jans user id jansId varchar(128) YES None Identifier jansPushApp tinytext YES None jansPush application DN jansPushDeviceConf varchar(64) YES None jansPush device configuration jansTyp varchar(64) YES None jans type", "title": "jansPushDevice"}, {"location": "janssen-server/reference/database/mysql-schema/#jansrp", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier dat text YES None OX data", "title": "jansRp"}, {"location": "janssen-server/reference/database/mysql-schema/#jansscope", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansDefScope smallint YES None Track the default scope for an custom OAuth2 Scope. description varchar(768) YES MUL None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries inum varchar(64) YES None XRI i-number jansScopeTyp varchar(64) YES None OX Attr Scope type creatorId varchar(64) YES None Creator Id creatorTyp varchar(64) YES None Creator type creatorAttrs varchar(64) YES None Creator Attrs creationDate datetime(3) YES None Creation Date used for password reset requests jansClaim json YES None jans Attr Claim jansScrDn json YES None Script object DN jansGrpClaims smallint YES None jans Grp Attr Claims (true or false) jansId varchar(128) YES MUL None Identifier jansIconUrl varchar(64) YES None jans icon url jansUmaPolicyScrDn tinytext YES None OX policy script Dn jansAttrs text YES None Attrs exp datetime(3) YES None jans Exp del smallint YES MUL None del", "title": "jansScope"}, {"location": "janssen-server/reference/database/mysql-schema/#jansscr", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number jansScr text YES None Attr that contains script (python, java script) jansScrTyp varchar(64) YES None Attr that contains script type (e.g. python, java script)", "title": "jansScr"}, {"location": "janssen-server/reference/database/mysql-schema/#janssectoridentifier", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier description varchar(768) YES None jansRedirectURI json YES None jans Redirect URI jansClntId json YES None jans Clnt id", "title": "jansSectorIdentifier"}, {"location": "janssen-server/reference/database/mysql-schema/#janssessid", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier sid varchar(64) YES MUL None Sess Identifier creationDate datetime(3) YES None Creation Date used for password reset requests exp datetime(3) YES None jans Exp del smallint YES MUL None del jansLastAccessTime datetime(3) YES None Last access time jansUsrDN varchar(128) YES MUL None jans Usr DN authnTime datetime(3) YES None jans Authn Time jansState varchar(64) YES None jansState jansSessState text YES None jans Sess State jansPermissionGranted smallint YES None jans Permission Granted jansAsJwt smallint YES None Boolean field to indicate whether object is used as JWT jansJwt text YES None JWT representation of the object or otherwise jwt associated with the object jansPermissionGrantedMap text YES None jans Permission Granted Map jansInvolvedClnts text YES None Involved clients deviceSecret varchar(64) YES MUL None deviceSecret jansSessAttr text YES None jansSessAttr", "title": "jansSessId"}, {"location": "janssen-server/reference/database/mysql-schema/#jansssa", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None inum varchar(64) YES None XRI i-number o varchar(64) YES None jansAttrs text YES None Attrs description varchar(768) YES None exp datetime(3) YES None jans Exp del smallint YES None del jansState varchar(64) YES None jansState creatorId varchar(64) YES None Creator Id creatorTyp varchar(64) YES None Creator type creationDate datetime(3) YES None Creation Date used for password reset requests", "title": "jansSsa"}, {"location": "janssen-server/reference/database/mysql-schema/#jansstatentry", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES MUL None Identifier dat text YES None OX data jansData text YES None OX data attr text YES None Attrs", "title": "jansStatEntry"}, {"location": "janssen-server/reference/database/mysql-schema/#janstoken", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authnTime datetime(3) YES None jans Authn Time authzCode varchar(64) YES MUL None jans authorization code iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del grtId varchar(64) YES MUL None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknCde varchar(80) YES MUL None jans Tkn Code tknTyp varchar(32) YES None jans Tkn Typ usrId varchar(64) YES None jans user id jansUsrDN varchar(128) YES None jans Usr DN clnId varchar(64) YES None jans Clnt id acr varchar(48) YES None uuid varchar(64) YES None Unique identifier chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims ssnId varchar(64) YES MUL None jans Sess DN attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash dpop varchar(64) YES None DPoP Proof", "title": "jansToken"}, {"location": "janssen-server/reference/database/mysql-schema/#jansu2freq", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None jansId varchar(128) YES None Identifier jansReqId varchar(64) YES None jansReqId jansReq text YES None jansReq jansSessStateId varchar(64) YES None jansSessStateId del smallint YES MUL None del exp datetime(3) YES None jans Exp personInum varchar(64) YES None Inum of a person creationDate datetime(3) YES MUL None Creation Date used for password reset requests", "title": "jansU2fReq"}, {"location": "janssen-server/reference/database/mysql-schema/#jansumapct", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None clnId varchar(64) YES None jans Clnt id iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del tknCde varchar(80) YES MUL None jans Tkn Code ssnId varchar(64) YES None jans Sess DN jansClaimValues varchar(64) YES None Claim Values dpop varchar(64) YES None DPoP Proof authnTime datetime(3) YES None jans Authn Time authzCode varchar(64) YES None jans authorization code grtId varchar(64) YES None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknTyp varchar(32) YES None jans Tkn Typ usrId varchar(64) YES None jans user id jansUsrDN varchar(128) YES None jans Usr DN acr varchar(48) YES None uuid varchar(64) YES None Unique identifier chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash", "title": "jansUmaPCT"}, {"location": "janssen-server/reference/database/mysql-schema/#jansumarpt", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None authnTime datetime(3) YES None jans Authn Time clnId varchar(64) YES None jans Clnt id iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES None del tknCde varchar(80) YES None jans Tkn Code usrId varchar(64) YES None jans user id ssnId varchar(64) YES None jans Sess DN jansUmaPermission json YES None jans uma permission uuid varchar(64) YES None Unique identifier dpop varchar(64) YES None DPoP Proof authzCode varchar(64) YES None jans authorization code grtId varchar(64) YES None jans grant id grtTyp varchar(64) YES None jans Grant Typ jwtReq text YES None jans JWT Req nnc text YES None jans nonce scp text YES None jans Attr Scope tknTyp varchar(32) YES None jans Tkn Typ jansUsrDN varchar(128) YES None jans Usr DN acr varchar(48) YES None chlng varchar(64) YES None OX PKCE code challenge chlngMth varchar(64) YES None OX PKCE code challenge method clms varchar(64) YES None jans Claims attr text YES None Attrs tknBndCnf tinytext YES None jansauth - Tkn Binding Id Hash", "title": "jansUmaRPT"}, {"location": "janssen-server/reference/database/mysql-schema/#jansumaresource", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None displayName varchar(128) YES MUL None preferred name of a person to be used when displaying entries inum varchar(64) YES None XRI i-number owner varchar(64) YES None jansAssociatedClnt json YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. jansUmaScope varchar(768) YES MUL None URI reference of scope descriptor jansFaviconImage varchar(64) YES None TODO - Stores URL of favicon jansGrp varchar(64) YES None Group jansId varchar(128) YES MUL None Identifier jansResource tinytext YES None Host path jansRevision int YES None Revision jansTyp varchar(64) YES None jans type jansScopeExpression text YES None Scope expression iat datetime(3) YES None jans Creation exp datetime(3) YES None jans Exp del smallint YES MUL None del description varchar(768) YES None", "title": "jansUmaResource"}, {"location": "janssen-server/reference/database/mysql-schema/#jansumaresourcepermission", "text": "Field Type Null Key Default Comment doc_id varchar(64) NO PRI None objectClass varchar(48) YES None dn varchar(128) YES None exp datetime(3) YES None jans Exp del smallint YES None del jansUmaScope varchar(768) YES None URI reference of scope descriptor jansConfCode varchar(64) YES None jans configuration code jansResourceSetId varchar(64) YES None jans resource set id jansAttrs text YES None Attrs jansTicket varchar(64) YES MUL None jans ticket jansStatus varchar(16) YES None Status of the entry, used by many objectclasses", "title": "jansUmaResourcePermission"}, {"location": "janssen-server/reference/database/pgsql-config/", "tags": ["administration", "reference", "database", "remote database"], "text": "PostgreSQL ORM persistence layer # The recommended PostgreSQL versions are 14.x, 15.x or newer. Before running installation the administrator can pre-install DB and provide credentials to access it or he can select option to install PostgreSQL on same server during setup. During installation setup generates default /etc/jans/conf/jans-sql.properties and creates jansdb schema with tables and initial data set. Configuration properties # List of specific for PostgreSQL default setting from jans-sql.properties : db.schema.name=public connection.uri=jdbc:postgresql://localhost:5432/jansdb # Prefix connection.driver-property.key=value will be coverterd to key=value JDBC driver properties #connection.driver-property.driverProperty=driverPropertyValue auth.userName=jans auth.userPassword=CC0NHhtXW78= # Password hash method password.encryption.method=SSHA-256 # Connection pool size connection.pool.max-total=40 connection.pool.max-idle=15 connection.pool.min-idle=5 # Max time needed to create connection pool in milliseconds connection.pool.create-max-wait-time-millis=20000 # Max wait 20 seconds connection.pool.max-wait-time-millis=20000 # Allow to evict connection in pool after 30 minutes connection.pool.min-evictable-idle-time-millis=1800000 # Sets whether objects created for the pool will be validated before being returned from it #connection.pool.test-on-create=true # Sets whether objects borrowed from the pool will be validated when they are returned to the pool #connection.pool.test-on-return=true The rest of properties are static for all other supported DB: binaryAttributes=objectGUID certificateAttributes=userCertificate doc_id building rules # In order to support transparency for end applications and allow data migration from one DB to another ORM requires DN attribute in each entry. This attribute it also uses to build doc_id . Here is example of this DN -> doc_id conversion: doc_id is primary key. In order to build unique document identifier ORM uses another unique attribute DN . doc_id is last RDN value. Generic tables structure # Each table in jansdb PostgreSQL database follow next rules: one table for every objectClass has 2 mandatory column DN and doc_id Index for primary key Data mapping rules # ORM uses CHARACTER VARYING / TIMESTAMP / INT64 / BYTEA / BOOLEAN / TEXT / JSONB data types. JSONB it uses to store multi-valued attribute values. The generic format of such values is: [\"value_1\", \"value_2\", ...] If in schema specified in schema that application can do search in multi-valued attribute setup add next indexes for each column: CREATE INDEX IF NOT EXISTS \"jansPerson_jsonb_path_query_array_idx\" ON public.\"jansPerson\" USING gin (jsonb_path_query_array(\"jansExtUid\", '$[*]'::jsonpath)) TABLESPACE pg_default; For user password field ORM on persist/update operations automatically create hash. On authentication ORM compares hashes. To store attributes defined in java beans with @JsonObject annotation ORM uses TEXT column type. Java example # This example shows how to use ORM. It opens connection to PostgreSQL DB and add user entry to it: public static void main(String[] args) { // Create Sql entry manager SqlEntryManager couchbaseEntryManager = createSqlEntryManager(); // Create and fill user bean SimpleUser newUser = new SimpleUser(); newUser.setDn(String.format(\"inum=%s,ou=people,o=jans\", System.currentTimeMillis())); newUser.setUserId(\"sample_user_\" + System.currentTimeMillis()); newUser.setUserPassword(\"test\"); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansAddress\", Arrays.asList(\"London\", \"Texas\", \"New York\"))); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); // Call ORM API to store entry couchbaseEntryManager.persist(newUser); couchbaseEntryManager.destroy(); } public static SqlEntryManager createSqlEntryManager() { SqlEntryManagerFactory couchbaseEntryManagerFactory = new SqlEntryManagerFactory(); couchbaseEntryManagerFactory.create(); Properties connectionProperties = getSampleConnectionProperties(); SqlEntryManager couchbaseEntryManager = couchbaseEntryManagerFactory.createEntryManager(connectionProperties); return couchbaseEntryManager; } private static Properties getSampleConnectionProperties() { Properties connectionProperties = new Properties(); connectionProperties.put(\"sql#db.schema.name\", \"public\"); connectionProperties.put(\"sql#connection.uri\", \"jdbc:postgresql://localhost:5432/jansdb\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"secret\"); connectionProperties.put(\"sql#connection.pool.max-total\", \"300\"); connectionProperties.put(\"sql#connection.pool.max-idle\", \"300\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"Secret1!\"); // Password hash method connectionProperties.put(\"sql#password.encryption.method\", \"SSHA-256\"); // Max time needed to create connection pool in milliseconds connectionProperties.put(\"sql#connection.pool.create-max-wait-time-millis\", \"20000\"); // Max wait 20 seconds connectionProperties.put(\"sql#connection.pool.max-wait-time-millis\", \"20000\"); // Allow to evict connection in pool after 30 minutes connectionProperties.put(\"sql#connection.pool.min-evictable-idle-time-millis\", \"1800000\"); connectionProperties.put(\"sql#binaryAttributes\", \"objectGUID\"); connectionProperties.put(\"sql#certificateAttributes\", \"userCertificate\"); return connectionProperties; } More MySQL ORM examples is in this sample module.", "title": "PostgreSQL Configuration"}, {"location": "janssen-server/reference/database/pgsql-config/#postgresql-orm-persistence-layer", "text": "The recommended PostgreSQL versions are 14.x, 15.x or newer. Before running installation the administrator can pre-install DB and provide credentials to access it or he can select option to install PostgreSQL on same server during setup. During installation setup generates default /etc/jans/conf/jans-sql.properties and creates jansdb schema with tables and initial data set.", "title": "PostgreSQL ORM persistence layer"}, {"location": "janssen-server/reference/database/pgsql-config/#configuration-properties", "text": "List of specific for PostgreSQL default setting from jans-sql.properties : db.schema.name=public connection.uri=jdbc:postgresql://localhost:5432/jansdb # Prefix connection.driver-property.key=value will be coverterd to key=value JDBC driver properties #connection.driver-property.driverProperty=driverPropertyValue auth.userName=jans auth.userPassword=CC0NHhtXW78= # Password hash method password.encryption.method=SSHA-256 # Connection pool size connection.pool.max-total=40 connection.pool.max-idle=15 connection.pool.min-idle=5 # Max time needed to create connection pool in milliseconds connection.pool.create-max-wait-time-millis=20000 # Max wait 20 seconds connection.pool.max-wait-time-millis=20000 # Allow to evict connection in pool after 30 minutes connection.pool.min-evictable-idle-time-millis=1800000 # Sets whether objects created for the pool will be validated before being returned from it #connection.pool.test-on-create=true # Sets whether objects borrowed from the pool will be validated when they are returned to the pool #connection.pool.test-on-return=true The rest of properties are static for all other supported DB: binaryAttributes=objectGUID certificateAttributes=userCertificate", "title": "Configuration properties"}, {"location": "janssen-server/reference/database/pgsql-config/#doc_id-building-rules", "text": "In order to support transparency for end applications and allow data migration from one DB to another ORM requires DN attribute in each entry. This attribute it also uses to build doc_id . Here is example of this DN -> doc_id conversion: doc_id is primary key. In order to build unique document identifier ORM uses another unique attribute DN . doc_id is last RDN value.", "title": "doc_id building rules"}, {"location": "janssen-server/reference/database/pgsql-config/#generic-tables-structure", "text": "Each table in jansdb PostgreSQL database follow next rules: one table for every objectClass has 2 mandatory column DN and doc_id Index for primary key", "title": "Generic tables structure"}, {"location": "janssen-server/reference/database/pgsql-config/#data-mapping-rules", "text": "ORM uses CHARACTER VARYING / TIMESTAMP / INT64 / BYTEA / BOOLEAN / TEXT / JSONB data types. JSONB it uses to store multi-valued attribute values. The generic format of such values is: [\"value_1\", \"value_2\", ...] If in schema specified in schema that application can do search in multi-valued attribute setup add next indexes for each column: CREATE INDEX IF NOT EXISTS \"jansPerson_jsonb_path_query_array_idx\" ON public.\"jansPerson\" USING gin (jsonb_path_query_array(\"jansExtUid\", '$[*]'::jsonpath)) TABLESPACE pg_default; For user password field ORM on persist/update operations automatically create hash. On authentication ORM compares hashes. To store attributes defined in java beans with @JsonObject annotation ORM uses TEXT column type.", "title": "Data mapping rules"}, {"location": "janssen-server/reference/database/pgsql-config/#java-example", "text": "This example shows how to use ORM. It opens connection to PostgreSQL DB and add user entry to it: public static void main(String[] args) { // Create Sql entry manager SqlEntryManager couchbaseEntryManager = createSqlEntryManager(); // Create and fill user bean SimpleUser newUser = new SimpleUser(); newUser.setDn(String.format(\"inum=%s,ou=people,o=jans\", System.currentTimeMillis())); newUser.setUserId(\"sample_user_\" + System.currentTimeMillis()); newUser.setUserPassword(\"test\"); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansAddress\", Arrays.asList(\"London\", \"Texas\", \"New York\"))); newUser.getCustomAttributes().add(new CustomObjectAttribute(\"jansGuid\", \"test_value\")); // Call ORM API to store entry couchbaseEntryManager.persist(newUser); couchbaseEntryManager.destroy(); } public static SqlEntryManager createSqlEntryManager() { SqlEntryManagerFactory couchbaseEntryManagerFactory = new SqlEntryManagerFactory(); couchbaseEntryManagerFactory.create(); Properties connectionProperties = getSampleConnectionProperties(); SqlEntryManager couchbaseEntryManager = couchbaseEntryManagerFactory.createEntryManager(connectionProperties); return couchbaseEntryManager; } private static Properties getSampleConnectionProperties() { Properties connectionProperties = new Properties(); connectionProperties.put(\"sql#db.schema.name\", \"public\"); connectionProperties.put(\"sql#connection.uri\", \"jdbc:postgresql://localhost:5432/jansdb\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"secret\"); connectionProperties.put(\"sql#connection.pool.max-total\", \"300\"); connectionProperties.put(\"sql#connection.pool.max-idle\", \"300\"); connectionProperties.put(\"sql#auth.userName\", \"jans\"); connectionProperties.put(\"sql#auth.userPassword\", \"Secret1!\"); // Password hash method connectionProperties.put(\"sql#password.encryption.method\", \"SSHA-256\"); // Max time needed to create connection pool in milliseconds connectionProperties.put(\"sql#connection.pool.create-max-wait-time-millis\", \"20000\"); // Max wait 20 seconds connectionProperties.put(\"sql#connection.pool.max-wait-time-millis\", \"20000\"); // Allow to evict connection in pool after 30 minutes connectionProperties.put(\"sql#connection.pool.min-evictable-idle-time-millis\", \"1800000\"); connectionProperties.put(\"sql#binaryAttributes\", \"objectGUID\"); connectionProperties.put(\"sql#certificateAttributes\", \"userCertificate\"); return connectionProperties; } More MySQL ORM examples is in this sample module.", "title": "Java example"}, {"location": "janssen-server/reference/database/pgsql-ops/", "tags": ["administration", "reference", "database"], "text": "PostgreSQL Operations # PostgreSQL is a versatile and reliable database management system that empowers developers and organizations to build robust and efficient applications. Establish Connection to Jans PostgreSQL Server # Connect to PostgreSql workspace: sudo -u postgres psql Show all Database list : \\list or \\l You will see jansdb in the list of database. Let's make a connection with jansdb : \\c jansdb Search user # Change database: \\c jansdb Search for user testUser : SELECT * FROM \"jansPerson\" WHERE uid = 'testuser'; If you want pretty output, enable display mode with \\x Re-run search query. Change password for user jans # Changing user 'jans' password to \"secret\": ALTER USER jans WITH PASSWORD 'secret'; Add user in Jans Group # Get DN of target user. i.e. we are searching for DN of user 'testUser' with: SELECT * FROM \"jansPerson\" WHERE uid = 'testuser'; Get DN of Jans Admin Group. i.e. SELECT * FROM \"jansGrp\"; Add ( actually append ) new user in member of this group: UPDATE \"jansGrp\" SET member = '[\"inum=d33a2ce9-e9de-4f74-8a7d-2519f73635b7,ou=people,o=jans\", \"inum=618d7792-caca-4915-8b92-9955bf94affb,ou=people,o=jans\"]'; List users with specific filter # To search for users with a filter using PostgreSQL's command-line tool psql, you can use the SELECT statement with the WHERE clause to apply filters to the query. Here's the query to find specific user: SELECT * FROM \"jansPerson\" WHERE uid= '<uid>'; Modify column size of Jans postgresql # The psql command-line tool, you can use the \\d+ command to display detailed information about a table, including its columns. Lets see the details of jansPerson table: \\d+ \"jansPerson\"; To modify the size of a column in a PostgreSQL table, you will need to use the ALTER TABLE statement along with the ALTER COLUMN clause. Here's how you can modify the size of a column: ALTER TABLE \"jansPerson\" ALTER COLUMN mail TYPE VARCHAR(100); Add custom attribute # To add a custom attribute to an existing PostgreSQL table, you can use the ALTER TABLE statement with the ADD COLUMN clause. Here's how you can add a custom attribute in jansPerson table: ALTER TABLE \"jansPerson\" ADD COLUMN membership_level VARCHAR(50); You can also specify additional constraints, defaults, or other attributes for the new column as needed. Here's an example with a default value: ALTER TABLE \"jansPerson\" ADD COLUMN membership_level VARCHAR DEFAULT 'Basic'; Output column data into txt # If you want to output the data from a PostgreSQL table's column into a text file, you can use the COPY command. This command allows you to copy the contents of a table or query result into an external file. Here's how you can do it: COPY (SELECT * FROM \"jansPerson\") TO '/tmp/output.txt'; After executing the command, the data from the specified column will be copied into the specified text file. Back-up and re-store # PostgreSQL is a popular open-source relational database management system used for web applications, business intelligence, and other data-intensive applications. A critical aspect of managing a PostgreSQL database is ensuring data protection by having a backup and restore strategy in place. Back-up # To dump the PostgreSQL database, you can use the pg_dump command-line utility. To back-up your database pg_dump -h localhost -U \"<user>\" \"<dbName>\" -Fc > /tmp/back-up.sql Re-store # To restore the backup file you need to use pg_restore . pg_restore -h localhost -U \"<user>\" -d <db_name> <back-up.sql> Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "PostgreSQL Operation"}, {"location": "janssen-server/reference/database/pgsql-ops/#postgresql-operations", "text": "PostgreSQL is a versatile and reliable database management system that empowers developers and organizations to build robust and efficient applications.", "title": "PostgreSQL Operations"}, {"location": "janssen-server/reference/database/pgsql-ops/#establish-connection-to-jans-postgresql-server", "text": "Connect to PostgreSql workspace: sudo -u postgres psql Show all Database list : \\list or \\l You will see jansdb in the list of database. Let's make a connection with jansdb : \\c jansdb", "title": "Establish Connection to Jans PostgreSQL Server"}, {"location": "janssen-server/reference/database/pgsql-ops/#search-user", "text": "Change database: \\c jansdb Search for user testUser : SELECT * FROM \"jansPerson\" WHERE uid = 'testuser'; If you want pretty output, enable display mode with \\x Re-run search query.", "title": "Search user"}, {"location": "janssen-server/reference/database/pgsql-ops/#change-password-for-user-jans", "text": "Changing user 'jans' password to \"secret\": ALTER USER jans WITH PASSWORD 'secret';", "title": "Change password for user jans"}, {"location": "janssen-server/reference/database/pgsql-ops/#add-user-in-jans-group", "text": "Get DN of target user. i.e. we are searching for DN of user 'testUser' with: SELECT * FROM \"jansPerson\" WHERE uid = 'testuser'; Get DN of Jans Admin Group. i.e. SELECT * FROM \"jansGrp\"; Add ( actually append ) new user in member of this group: UPDATE \"jansGrp\" SET member = '[\"inum=d33a2ce9-e9de-4f74-8a7d-2519f73635b7,ou=people,o=jans\", \"inum=618d7792-caca-4915-8b92-9955bf94affb,ou=people,o=jans\"]';", "title": "Add user in Jans Group"}, {"location": "janssen-server/reference/database/pgsql-ops/#list-users-with-specific-filter", "text": "To search for users with a filter using PostgreSQL's command-line tool psql, you can use the SELECT statement with the WHERE clause to apply filters to the query. Here's the query to find specific user: SELECT * FROM \"jansPerson\" WHERE uid= '<uid>';", "title": "List users with specific filter"}, {"location": "janssen-server/reference/database/pgsql-ops/#modify-column-size-of-jans-postgresql", "text": "The psql command-line tool, you can use the \\d+ command to display detailed information about a table, including its columns. Lets see the details of jansPerson table: \\d+ \"jansPerson\"; To modify the size of a column in a PostgreSQL table, you will need to use the ALTER TABLE statement along with the ALTER COLUMN clause. Here's how you can modify the size of a column: ALTER TABLE \"jansPerson\" ALTER COLUMN mail TYPE VARCHAR(100);", "title": "Modify column size of Jans postgresql"}, {"location": "janssen-server/reference/database/pgsql-ops/#add-custom-attribute", "text": "To add a custom attribute to an existing PostgreSQL table, you can use the ALTER TABLE statement with the ADD COLUMN clause. Here's how you can add a custom attribute in jansPerson table: ALTER TABLE \"jansPerson\" ADD COLUMN membership_level VARCHAR(50); You can also specify additional constraints, defaults, or other attributes for the new column as needed. Here's an example with a default value: ALTER TABLE \"jansPerson\" ADD COLUMN membership_level VARCHAR DEFAULT 'Basic';", "title": "Add custom attribute"}, {"location": "janssen-server/reference/database/pgsql-ops/#output-column-data-into-txt", "text": "If you want to output the data from a PostgreSQL table's column into a text file, you can use the COPY command. This command allows you to copy the contents of a table or query result into an external file. Here's how you can do it: COPY (SELECT * FROM \"jansPerson\") TO '/tmp/output.txt'; After executing the command, the data from the specified column will be copied into the specified text file.", "title": "Output column data into txt"}, {"location": "janssen-server/reference/database/pgsql-ops/#back-up-and-re-store", "text": "PostgreSQL is a popular open-source relational database management system used for web applications, business intelligence, and other data-intensive applications. A critical aspect of managing a PostgreSQL database is ensuring data protection by having a backup and restore strategy in place.", "title": "Back-up and re-store"}, {"location": "janssen-server/reference/database/pgsql-ops/#back-up", "text": "To dump the PostgreSQL database, you can use the pg_dump command-line utility. To back-up your database pg_dump -h localhost -U \"<user>\" \"<dbName>\" -Fc > /tmp/back-up.sql", "title": "Back-up"}, {"location": "janssen-server/reference/database/pgsql-ops/#re-store", "text": "To restore the backup file you need to use pg_restore . pg_restore -h localhost -U \"<user>\" -d <db_name> <back-up.sql>", "title": "Re-store"}, {"location": "janssen-server/reference/database/pgsql-ops/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/", "tags": ["administration", "database", "PostgreSQL", "Indexes"], "text": "PostgreSQL Indexes # jansPairwiseIdentifier # tablename indexname indexdef jansPairwiseIdentifier jansPairwiseIdentifier_pkey CREATE UNIQUE INDEX \"jansPairwiseIdentifier_pkey\" ON public.\"jansPairwiseIdentifier\" USING btree (doc_id) jansPerson # tablename indexname indexdef jansPerson jansPerson_pkey CREATE UNIQUE INDEX \"jansPerson_pkey\" ON public.\"jansPerson\" USING btree (doc_id) jansPerson jansPerson_givenName_idx CREATE INDEX \"jansPerson_givenName_idx\" ON public.\"jansPerson\" USING btree (\"givenName\") jansPerson jansPerson_mail_idx CREATE INDEX \"jansPerson_mail_idx\" ON public.\"jansPerson\" USING btree (mail) jansPerson jansPerson_sn_idx CREATE INDEX \"jansPerson_sn_idx\" ON public.\"jansPerson\" USING btree (sn) jansPerson jansPerson_lower_idx CREATE INDEX \"jansPerson_lower_idx\" ON public.\"jansPerson\" USING btree (lower((uid)::text)) jansPerson jansPerson_displayName_idx CREATE INDEX \"jansPerson_displayName_idx\" ON public.\"jansPerson\" USING btree (\"displayName\") jansPerson jansPerson_inum_idx CREATE INDEX \"jansPerson_inum_idx\" ON public.\"jansPerson\" USING btree (inum) jansPerson jansPerson_jsonb_path_query_array_idx CREATE INDEX \"jansPerson_jsonb_path_query_array_idx\" ON public.\"jansPerson\" USING gin (jsonb_path_query_array(\"jansExtUid\", '$[*]'::jsonpath)) jansPerson jansPerson_uid_idx CREATE INDEX \"jansPerson_uid_idx\" ON public.\"jansPerson\" USING btree (uid) jansPerson jansPerson_lower_idx1 CREATE INDEX \"jansPerson_lower_idx1\" ON public.\"jansPerson\" USING btree (lower((mail)::text)) jansOrganization # tablename indexname indexdef jansOrganization jansOrganization_pkey CREATE UNIQUE INDEX \"jansOrganization_pkey\" ON public.\"jansOrganization\" USING btree (doc_id) jansOrganization jansOrganization_uid_idx CREATE INDEX \"jansOrganization_uid_idx\" ON public.\"jansOrganization\" USING btree (uid) jansSsa # tablename indexname indexdef jansSsa jansSsa_pkey CREATE UNIQUE INDEX \"jansSsa_pkey\" ON public.\"jansSsa\" USING btree (doc_id) jansAppConf # tablename indexname indexdef jansAppConf jansAppConf_pkey CREATE UNIQUE INDEX \"jansAppConf_pkey\" ON public.\"jansAppConf\" USING btree (doc_id) jansClnt # tablename indexname indexdef jansClnt jansClnt_pkey CREATE UNIQUE INDEX \"jansClnt_pkey\" ON public.\"jansClnt\" USING btree (doc_id) jansClnt jansClnt_description_idx CREATE INDEX \"jansClnt_description_idx\" ON public.\"jansClnt\" USING btree (description) jansClnt jansClnt_jansClntSecretExpAt_idx CREATE INDEX \"jansClnt_jansClntSecretExpAt_idx\" ON public.\"jansClnt\" USING btree (\"jansClntSecretExpAt\") jansClnt jansClnt_del_exp_idx CREATE INDEX \"jansClnt_del_exp_idx\" ON public.\"jansClnt\" USING btree (del, exp) jansClnt jansClnt_displayName_idx CREATE INDEX \"jansClnt_displayName_idx\" ON public.\"jansClnt\" USING btree (\"displayName\") jansClnt jansClnt_inum_idx CREATE INDEX \"jansClnt_inum_idx\" ON public.\"jansClnt\" USING btree (inum) jansClnt jansClnt_jansRegistrationAccessTkn_idx CREATE INDEX \"jansClnt_jansRegistrationAccessTkn_idx\" ON public.\"jansClnt\" USING btree (\"jansRegistrationAccessTkn\") jansScope # tablename indexname indexdef jansScope jansScope_pkey CREATE UNIQUE INDEX \"jansScope_pkey\" ON public.\"jansScope\" USING btree (doc_id) jansScope jansScope_displayName_idx CREATE INDEX \"jansScope_displayName_idx\" ON public.\"jansScope\" USING btree (\"displayName\") jansScope jansScope_del_exp_idx CREATE INDEX \"jansScope_del_exp_idx\" ON public.\"jansScope\" USING btree (del, exp) jansScope jansScope_description_idx CREATE INDEX \"jansScope_description_idx\" ON public.\"jansScope\" USING btree (description) jansScope jansScope_jansId_idx CREATE INDEX \"jansScope_jansId_idx\" ON public.\"jansScope\" USING btree (\"jansId\") jansUmaResource # tablename indexname indexdef jansUmaResource jansUmaResource_pkey CREATE UNIQUE INDEX \"jansUmaResource_pkey\" ON public.\"jansUmaResource\" USING btree (doc_id) jansUmaResource jansUmaResource_jansUmaScope_idx CREATE INDEX \"jansUmaResource_jansUmaScope_idx\" ON public.\"jansUmaResource\" USING btree (\"jansUmaScope\") jansUmaResource jansUmaResource_del_exp_idx CREATE INDEX \"jansUmaResource_del_exp_idx\" ON public.\"jansUmaResource\" USING btree (del, exp) jansUmaResource jansUmaResource_displayName_idx CREATE INDEX \"jansUmaResource_displayName_idx\" ON public.\"jansUmaResource\" USING btree (\"displayName\") jansUmaResource jansUmaResource_jansId_idx CREATE INDEX \"jansUmaResource_jansId_idx\" ON public.\"jansUmaResource\" USING btree (\"jansId\") jansUmaResourcePermission # tablename indexname indexdef jansUmaResourcePermission jansUmaResourcePermission_pkey CREATE UNIQUE INDEX \"jansUmaResourcePermission_pkey\" ON public.\"jansUmaResourcePermission\" USING btree (doc_id) jansUmaResourcePermission jansUmaResourcePermission_jansTicket_idx CREATE INDEX \"jansUmaResourcePermission_jansTicket_idx\" ON public.\"jansUmaResourcePermission\" USING btree (\"jansTicket\") jansGrant # tablename indexname indexdef jansGrant jansGrant_pkey CREATE UNIQUE INDEX \"jansGrant_pkey\" ON public.\"jansGrant\" USING btree (doc_id) jansToken # tablename indexname indexdef jansToken jansToken_pkey CREATE UNIQUE INDEX \"jansToken_pkey\" ON public.\"jansToken\" USING btree (doc_id) jansToken jansToken_authzCode_idx CREATE INDEX \"jansToken_authzCode_idx\" ON public.\"jansToken\" USING btree (\"authzCode\") jansToken jansToken_grtId_idx CREATE INDEX \"jansToken_grtId_idx\" ON public.\"jansToken\" USING btree (\"grtId\") jansToken jansToken_ssnId_idx CREATE INDEX \"jansToken_ssnId_idx\" ON public.\"jansToken\" USING btree (\"ssnId\") jansToken jansToken_tknCde_idx CREATE INDEX \"jansToken_tknCde_idx\" ON public.\"jansToken\" USING btree (\"tknCde\") jansToken jansToken_del_exp_idx CREATE INDEX \"jansToken_del_exp_idx\" ON public.\"jansToken\" USING btree (del, exp) jansGrp # tablename indexname indexdef jansGrp jansGrp_pkey CREATE UNIQUE INDEX \"jansGrp_pkey\" ON public.\"jansGrp\" USING btree (doc_id) jansGrp jansGrp_description_idx CREATE INDEX \"jansGrp_description_idx\" ON public.\"jansGrp\" USING btree (description) jansGrp jansGrp_inum_idx CREATE INDEX \"jansGrp_inum_idx\" ON public.\"jansGrp\" USING btree (inum) jansGrp jansGrp_displayName_idx CREATE INDEX \"jansGrp_displayName_idx\" ON public.\"jansGrp\" USING btree (\"displayName\") jansAttr # tablename indexname indexdef jansAttr jansAttr_pkey CREATE UNIQUE INDEX \"jansAttr_pkey\" ON public.\"jansAttr\" USING btree (doc_id) jansAttr jansAttr_description_idx CREATE INDEX \"jansAttr_description_idx\" ON public.\"jansAttr\" USING btree (description) jansAttr jansAttr_jansAttrName_idx CREATE INDEX \"jansAttr_jansAttrName_idx\" ON public.\"jansAttr\" USING btree (\"jansAttrName\") jansAttr jansAttr_inum_idx CREATE INDEX \"jansAttr_inum_idx\" ON public.\"jansAttr\" USING btree (inum) jansAttr jansAttr_displayName_idx CREATE INDEX \"jansAttr_displayName_idx\" ON public.\"jansAttr\" USING btree (\"displayName\") jansAttr jansAttr_jansAttrOrigin_idx CREATE INDEX \"jansAttr_jansAttrOrigin_idx\" ON public.\"jansAttr\" USING btree (\"jansAttrOrigin\") jansPassResetReq # tablename indexname indexdef jansPassResetReq jansPassResetReq_pkey CREATE UNIQUE INDEX \"jansPassResetReq_pkey\" ON public.\"jansPassResetReq\" USING btree (doc_id) jansPassResetReq jansPassResetReq_creationDate_idx CREATE INDEX \"jansPassResetReq_creationDate_idx\" ON public.\"jansPassResetReq\" USING btree (\"creationDate\") jansSessId # tablename indexname indexdef jansSessId jansSessId_pkey CREATE UNIQUE INDEX \"jansSessId_pkey\" ON public.\"jansSessId\" USING btree (doc_id) jansSessId jansSessId_sid_idx CREATE INDEX \"jansSessId_sid_idx\" ON public.\"jansSessId\" USING btree (sid) jansSessId jansSessId_deviceSecret_idx CREATE INDEX \"jansSessId_deviceSecret_idx\" ON public.\"jansSessId\" USING btree (\"deviceSecret\") jansSessId jansSessId_jansUsrDN_idx CREATE INDEX \"jansSessId_jansUsrDN_idx\" ON public.\"jansSessId\" USING btree (\"jansUsrDN\") jansSessId jansSessId_del_exp_idx CREATE INDEX \"jansSessId_del_exp_idx\" ON public.\"jansSessId\" USING btree (del, exp) jansUmaRPT # tablename indexname indexdef jansUmaRPT jansUmaRPT_pkey CREATE UNIQUE INDEX \"jansUmaRPT_pkey\" ON public.\"jansUmaRPT\" USING btree (doc_id) jansPushApp # tablename indexname indexdef jansPushApp jansPushApp_pkey CREATE UNIQUE INDEX \"jansPushApp_pkey\" ON public.\"jansPushApp\" USING btree (doc_id) jansScr # tablename indexname indexdef jansScr jansScr_pkey CREATE UNIQUE INDEX \"jansScr_pkey\" ON public.\"jansScr\" USING btree (doc_id) jansCustomScr # tablename indexname indexdef jansCustomScr jansCustomScr_pkey CREATE UNIQUE INDEX \"jansCustomScr_pkey\" ON public.\"jansCustomScr\" USING btree (doc_id) jansCustomScr jansCustomScr_inum_idx CREATE INDEX \"jansCustomScr_inum_idx\" ON public.\"jansCustomScr\" USING btree (inum) jansCustomScr jansCustomScr_jansScrTyp_idx CREATE INDEX \"jansCustomScr_jansScrTyp_idx\" ON public.\"jansCustomScr\" USING btree (\"jansScrTyp\") jansDeviceRegistration # tablename indexname indexdef jansDeviceRegistration jansDeviceRegistration_pkey CREATE UNIQUE INDEX \"jansDeviceRegistration_pkey\" ON public.\"jansDeviceRegistration\" USING btree (doc_id) jansDeviceRegistration jansDeviceRegistration_jansDeviceKeyHandle_idx CREATE INDEX \"jansDeviceRegistration_jansDeviceKeyHandle_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansDeviceKeyHandle\") jansDeviceRegistration jansDeviceRegistration_jansApp_idx CREATE INDEX \"jansDeviceRegistration_jansApp_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansApp\") jansDeviceRegistration jansDeviceRegistration_personInum_idx CREATE INDEX \"jansDeviceRegistration_personInum_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"personInum\") jansDeviceRegistration jansDeviceRegistration_del_exp_idx CREATE INDEX \"jansDeviceRegistration_del_exp_idx\" ON public.\"jansDeviceRegistration\" USING btree (del, exp) jansDeviceRegistration jansDeviceRegistration_jansDeviceHashCode_idx CREATE INDEX \"jansDeviceRegistration_jansDeviceHashCode_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansDeviceHashCode\") jansDeviceRegistration jansDeviceRegistration_jansStatus_idx CREATE INDEX \"jansDeviceRegistration_jansStatus_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansStatus\") jansDeviceRegistration jansDeviceRegistration_creationDate_idx CREATE INDEX \"jansDeviceRegistration_creationDate_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"creationDate\") jansU2fReq # tablename indexname indexdef jansU2fReq jansU2fReq_pkey CREATE UNIQUE INDEX \"jansU2fReq_pkey\" ON public.\"jansU2fReq\" USING btree (doc_id) jansU2fReq jansU2fReq_del_exp_idx CREATE INDEX \"jansU2fReq_del_exp_idx\" ON public.\"jansU2fReq\" USING btree (del, exp) jansU2fReq jansU2fReq_creationDate_idx CREATE INDEX \"jansU2fReq_creationDate_idx\" ON public.\"jansU2fReq\" USING btree (\"creationDate\") jansMetric # tablename indexname indexdef jansMetric jansMetric_pkey CREATE UNIQUE INDEX \"jansMetric_pkey\" ON public.\"jansMetric\" USING btree (doc_id) jansMetric jansMetric_jansEndDate_idx CREATE INDEX \"jansMetric_jansEndDate_idx\" ON public.\"jansMetric\" USING btree (\"jansEndDate\") jansMetric jansMetric_jansMetricTyp_idx CREATE INDEX \"jansMetric_jansMetricTyp_idx\" ON public.\"jansMetric\" USING btree (\"jansMetricTyp\") jansMetric jansMetric_jansStartDate_idx CREATE INDEX \"jansMetric_jansStartDate_idx\" ON public.\"jansMetric\" USING btree (\"jansStartDate\") jansMetric jansMetric_jansAppTyp_idx CREATE INDEX \"jansMetric_jansAppTyp_idx\" ON public.\"jansMetric\" USING btree (\"jansAppTyp\") jansMetric jansMetric_del_exp_idx CREATE INDEX \"jansMetric_del_exp_idx\" ON public.\"jansMetric\" USING btree (del, exp) jansUmaPCT # tablename indexname indexdef jansUmaPCT jansUmaPCT_pkey CREATE UNIQUE INDEX \"jansUmaPCT_pkey\" ON public.\"jansUmaPCT\" USING btree (doc_id) jansUmaPCT jansUmaPCT_tknCde_idx CREATE INDEX \"jansUmaPCT_tknCde_idx\" ON public.\"jansUmaPCT\" USING btree (\"tknCde\") jansUmaPCT jansUmaPCT_del_exp_idx CREATE INDEX \"jansUmaPCT_del_exp_idx\" ON public.\"jansUmaPCT\" USING btree (del, exp) jansCache # tablename indexname indexdef jansCache jansCache_pkey CREATE UNIQUE INDEX \"jansCache_pkey\" ON public.\"jansCache\" USING btree (doc_id) jansCache jansCache_del_exp_idx CREATE INDEX \"jansCache_del_exp_idx\" ON public.\"jansCache\" USING btree (del, exp) jansFido2RegistrationEntry # tablename indexname indexdef jansFido2RegistrationEntry jansFido2RegistrationEntry_pkey CREATE UNIQUE INDEX \"jansFido2RegistrationEntry_pkey\" ON public.\"jansFido2RegistrationEntry\" USING btree (doc_id) jansFido2RegistrationEntry jansFido2RegistrationEntry_jansApp_idx CREATE INDEX \"jansFido2RegistrationEntry_jansApp_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansApp\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansCodeChallengeHash_idx CREATE INDEX \"jansFido2RegistrationEntry_jansCodeChallengeHash_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansCodeChallengeHash\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansPublicKeyIdHash_idx CREATE INDEX \"jansFido2RegistrationEntry_jansPublicKeyIdHash_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansPublicKeyIdHash\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansStatus_idx CREATE INDEX \"jansFido2RegistrationEntry_jansStatus_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansStatus\") jansFido2RegistrationEntry jansFido2RegistrationEntry_creationDate_idx CREATE INDEX \"jansFido2RegistrationEntry_creationDate_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"creationDate\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansCodeChallenge_idx CREATE INDEX \"jansFido2RegistrationEntry_jansCodeChallenge_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansCodeChallenge\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansPublicKeyId_idx CREATE INDEX \"jansFido2RegistrationEntry_jansPublicKeyId_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansPublicKeyId\") jansFido2RegistrationEntry jansFido2RegistrationEntry_personInum_idx CREATE INDEX \"jansFido2RegistrationEntry_personInum_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"personInum\") jansFido2RegistrationEntry jansFido2RegistrationEntry_del_exp_idx CREATE INDEX \"jansFido2RegistrationEntry_del_exp_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (del, exp) jansPushDevice # tablename indexname indexdef jansPushDevice jansPushDevice_pkey CREATE UNIQUE INDEX \"jansPushDevice_pkey\" ON public.\"jansPushDevice\" USING btree (doc_id) jansClntAuthz # tablename indexname indexdef jansClntAuthz jansClntAuthz_pkey CREATE UNIQUE INDEX \"jansClntAuthz_pkey\" ON public.\"jansClntAuthz\" USING btree (doc_id) jansClntAuthz jansClntAuthz_jsonb_path_query_array_idx CREATE INDEX \"jansClntAuthz_jsonb_path_query_array_idx\" ON public.\"jansClntAuthz\" USING gin (jsonb_path_query_array(\"jansClntId\", '$[*]'::jsonpath)) jansClntAuthz jansClntAuthz_del_exp_idx CREATE INDEX \"jansClntAuthz_del_exp_idx\" ON public.\"jansClntAuthz\" USING btree (del, exp) jansClntAuthz jansClntAuthz_jansUsrId_idx CREATE INDEX \"jansClntAuthz_jansUsrId_idx\" ON public.\"jansClntAuthz\" USING btree (\"jansUsrId\") jansSectorIdentifier # tablename indexname indexdef jansSectorIdentifier jansSectorIdentifier_pkey CREATE UNIQUE INDEX \"jansSectorIdentifier_pkey\" ON public.\"jansSectorIdentifier\" USING btree (doc_id) jansFido2AuthnEntry # tablename indexname indexdef jansFido2AuthnEntry jansFido2AuthnEntry_pkey CREATE UNIQUE INDEX \"jansFido2AuthnEntry_pkey\" ON public.\"jansFido2AuthnEntry\" USING btree (doc_id) jansFido2AuthnEntry jansFido2AuthnEntry_jansApp_idx CREATE INDEX \"jansFido2AuthnEntry_jansApp_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansApp\") jansFido2AuthnEntry jansFido2AuthnEntry_jansCodeChallengeHash_idx CREATE INDEX \"jansFido2AuthnEntry_jansCodeChallengeHash_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansCodeChallengeHash\") jansFido2AuthnEntry jansFido2AuthnEntry_jansStatus_idx CREATE INDEX \"jansFido2AuthnEntry_jansStatus_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansStatus\") jansFido2AuthnEntry jansFido2AuthnEntry_creationDate_idx CREATE INDEX \"jansFido2AuthnEntry_creationDate_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"creationDate\") jansFido2AuthnEntry jansFido2AuthnEntry_jansCodeChallenge_idx CREATE INDEX \"jansFido2AuthnEntry_jansCodeChallenge_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansCodeChallenge\") jansFido2AuthnEntry jansFido2AuthnEntry_personInum_idx CREATE INDEX \"jansFido2AuthnEntry_personInum_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"personInum\") jansFido2AuthnEntry jansFido2AuthnEntry_del_exp_idx CREATE INDEX \"jansFido2AuthnEntry_del_exp_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (del, exp) jansRp # tablename indexname indexdef jansRp jansRp_pkey CREATE UNIQUE INDEX \"jansRp_pkey\" ON public.\"jansRp\" USING btree (doc_id) jansCibaReq # tablename indexname indexdef jansCibaReq jansCibaReq_pkey CREATE UNIQUE INDEX \"jansCibaReq_pkey\" ON public.\"jansCibaReq\" USING btree (doc_id) jansCibaReq jansCibaReq_jansStatus_exp_idx CREATE INDEX \"jansCibaReq_jansStatus_exp_idx\" ON public.\"jansCibaReq\" USING btree (\"jansStatus\", exp) jansStatEntry # tablename indexname indexdef jansStatEntry jansStatEntry_pkey CREATE UNIQUE INDEX \"jansStatEntry_pkey\" ON public.\"jansStatEntry\" USING btree (doc_id) jansStatEntry jansStatEntry_jansId_idx CREATE INDEX \"jansStatEntry_jansId_idx\" ON public.\"jansStatEntry\" USING btree (\"jansId\") jansPar # tablename indexname indexdef jansPar jansPar_pkey CREATE UNIQUE INDEX \"jansPar_pkey\" ON public.\"jansPar\" USING btree (doc_id) jansPar jansPar_jansId_idx CREATE INDEX \"jansPar_jansId_idx\" ON public.\"jansPar\" USING btree (\"jansId\") jansPar jansPar_del_exp_idx CREATE INDEX \"jansPar_del_exp_idx\" ON public.\"jansPar\" USING btree (del, exp) jansInumMap # tablename indexname indexdef jansInumMap jansInumMap_pkey CREATE UNIQUE INDEX \"jansInumMap_pkey\" ON public.\"jansInumMap\" USING btree (doc_id) jansInumMap jansInumMap_jansStatus_idx CREATE INDEX \"jansInumMap_jansStatus_idx\" ON public.\"jansInumMap\" USING btree (\"jansStatus\") jansInumMap jansInumMap_inum_idx CREATE INDEX \"jansInumMap_inum_idx\" ON public.\"jansInumMap\" USING btree (inum) agmFlowRun # tablename indexname indexdef agmFlowRun agmFlowRun_pkey CREATE UNIQUE INDEX \"agmFlowRun_pkey\" ON public.\"agmFlowRun\" USING btree (doc_id) agmFlow # tablename indexname indexdef agmFlow agmFlow_pkey CREATE UNIQUE INDEX \"agmFlow_pkey\" ON public.\"agmFlow\" USING btree (doc_id) adsPrjDeployment # tablename indexname indexdef adsPrjDeployment adsPrjDeployment_pkey CREATE UNIQUE INDEX \"adsPrjDeployment_pkey\" ON public.\"adsPrjDeployment\" USING btree (doc_id) jansDocument # tablename indexname indexdef jansDocument jansDocument_pkey CREATE UNIQUE INDEX \"jansDocument_pkey\" ON public.\"jansDocument\" USING btree (doc_id)", "title": "PostgreSQL Indexes"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#postgresql-indexes", "text": "", "title": "PostgreSQL Indexes"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janspairwiseidentifier", "text": "tablename indexname indexdef jansPairwiseIdentifier jansPairwiseIdentifier_pkey CREATE UNIQUE INDEX \"jansPairwiseIdentifier_pkey\" ON public.\"jansPairwiseIdentifier\" USING btree (doc_id)", "title": "jansPairwiseIdentifier"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansperson", "text": "tablename indexname indexdef jansPerson jansPerson_pkey CREATE UNIQUE INDEX \"jansPerson_pkey\" ON public.\"jansPerson\" USING btree (doc_id) jansPerson jansPerson_givenName_idx CREATE INDEX \"jansPerson_givenName_idx\" ON public.\"jansPerson\" USING btree (\"givenName\") jansPerson jansPerson_mail_idx CREATE INDEX \"jansPerson_mail_idx\" ON public.\"jansPerson\" USING btree (mail) jansPerson jansPerson_sn_idx CREATE INDEX \"jansPerson_sn_idx\" ON public.\"jansPerson\" USING btree (sn) jansPerson jansPerson_lower_idx CREATE INDEX \"jansPerson_lower_idx\" ON public.\"jansPerson\" USING btree (lower((uid)::text)) jansPerson jansPerson_displayName_idx CREATE INDEX \"jansPerson_displayName_idx\" ON public.\"jansPerson\" USING btree (\"displayName\") jansPerson jansPerson_inum_idx CREATE INDEX \"jansPerson_inum_idx\" ON public.\"jansPerson\" USING btree (inum) jansPerson jansPerson_jsonb_path_query_array_idx CREATE INDEX \"jansPerson_jsonb_path_query_array_idx\" ON public.\"jansPerson\" USING gin (jsonb_path_query_array(\"jansExtUid\", '$[*]'::jsonpath)) jansPerson jansPerson_uid_idx CREATE INDEX \"jansPerson_uid_idx\" ON public.\"jansPerson\" USING btree (uid) jansPerson jansPerson_lower_idx1 CREATE INDEX \"jansPerson_lower_idx1\" ON public.\"jansPerson\" USING btree (lower((mail)::text))", "title": "jansPerson"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansorganization", "text": "tablename indexname indexdef jansOrganization jansOrganization_pkey CREATE UNIQUE INDEX \"jansOrganization_pkey\" ON public.\"jansOrganization\" USING btree (doc_id) jansOrganization jansOrganization_uid_idx CREATE INDEX \"jansOrganization_uid_idx\" ON public.\"jansOrganization\" USING btree (uid)", "title": "jansOrganization"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansssa", "text": "tablename indexname indexdef jansSsa jansSsa_pkey CREATE UNIQUE INDEX \"jansSsa_pkey\" ON public.\"jansSsa\" USING btree (doc_id)", "title": "jansSsa"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansappconf", "text": "tablename indexname indexdef jansAppConf jansAppConf_pkey CREATE UNIQUE INDEX \"jansAppConf_pkey\" ON public.\"jansAppConf\" USING btree (doc_id)", "title": "jansAppConf"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansclnt", "text": "tablename indexname indexdef jansClnt jansClnt_pkey CREATE UNIQUE INDEX \"jansClnt_pkey\" ON public.\"jansClnt\" USING btree (doc_id) jansClnt jansClnt_description_idx CREATE INDEX \"jansClnt_description_idx\" ON public.\"jansClnt\" USING btree (description) jansClnt jansClnt_jansClntSecretExpAt_idx CREATE INDEX \"jansClnt_jansClntSecretExpAt_idx\" ON public.\"jansClnt\" USING btree (\"jansClntSecretExpAt\") jansClnt jansClnt_del_exp_idx CREATE INDEX \"jansClnt_del_exp_idx\" ON public.\"jansClnt\" USING btree (del, exp) jansClnt jansClnt_displayName_idx CREATE INDEX \"jansClnt_displayName_idx\" ON public.\"jansClnt\" USING btree (\"displayName\") jansClnt jansClnt_inum_idx CREATE INDEX \"jansClnt_inum_idx\" ON public.\"jansClnt\" USING btree (inum) jansClnt jansClnt_jansRegistrationAccessTkn_idx CREATE INDEX \"jansClnt_jansRegistrationAccessTkn_idx\" ON public.\"jansClnt\" USING btree (\"jansRegistrationAccessTkn\")", "title": "jansClnt"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansscope", "text": "tablename indexname indexdef jansScope jansScope_pkey CREATE UNIQUE INDEX \"jansScope_pkey\" ON public.\"jansScope\" USING btree (doc_id) jansScope jansScope_displayName_idx CREATE INDEX \"jansScope_displayName_idx\" ON public.\"jansScope\" USING btree (\"displayName\") jansScope jansScope_del_exp_idx CREATE INDEX \"jansScope_del_exp_idx\" ON public.\"jansScope\" USING btree (del, exp) jansScope jansScope_description_idx CREATE INDEX \"jansScope_description_idx\" ON public.\"jansScope\" USING btree (description) jansScope jansScope_jansId_idx CREATE INDEX \"jansScope_jansId_idx\" ON public.\"jansScope\" USING btree (\"jansId\")", "title": "jansScope"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansumaresource", "text": "tablename indexname indexdef jansUmaResource jansUmaResource_pkey CREATE UNIQUE INDEX \"jansUmaResource_pkey\" ON public.\"jansUmaResource\" USING btree (doc_id) jansUmaResource jansUmaResource_jansUmaScope_idx CREATE INDEX \"jansUmaResource_jansUmaScope_idx\" ON public.\"jansUmaResource\" USING btree (\"jansUmaScope\") jansUmaResource jansUmaResource_del_exp_idx CREATE INDEX \"jansUmaResource_del_exp_idx\" ON public.\"jansUmaResource\" USING btree (del, exp) jansUmaResource jansUmaResource_displayName_idx CREATE INDEX \"jansUmaResource_displayName_idx\" ON public.\"jansUmaResource\" USING btree (\"displayName\") jansUmaResource jansUmaResource_jansId_idx CREATE INDEX \"jansUmaResource_jansId_idx\" ON public.\"jansUmaResource\" USING btree (\"jansId\")", "title": "jansUmaResource"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansumaresourcepermission", "text": "tablename indexname indexdef jansUmaResourcePermission jansUmaResourcePermission_pkey CREATE UNIQUE INDEX \"jansUmaResourcePermission_pkey\" ON public.\"jansUmaResourcePermission\" USING btree (doc_id) jansUmaResourcePermission jansUmaResourcePermission_jansTicket_idx CREATE INDEX \"jansUmaResourcePermission_jansTicket_idx\" ON public.\"jansUmaResourcePermission\" USING btree (\"jansTicket\")", "title": "jansUmaResourcePermission"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansgrant", "text": "tablename indexname indexdef jansGrant jansGrant_pkey CREATE UNIQUE INDEX \"jansGrant_pkey\" ON public.\"jansGrant\" USING btree (doc_id)", "title": "jansGrant"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janstoken", "text": "tablename indexname indexdef jansToken jansToken_pkey CREATE UNIQUE INDEX \"jansToken_pkey\" ON public.\"jansToken\" USING btree (doc_id) jansToken jansToken_authzCode_idx CREATE INDEX \"jansToken_authzCode_idx\" ON public.\"jansToken\" USING btree (\"authzCode\") jansToken jansToken_grtId_idx CREATE INDEX \"jansToken_grtId_idx\" ON public.\"jansToken\" USING btree (\"grtId\") jansToken jansToken_ssnId_idx CREATE INDEX \"jansToken_ssnId_idx\" ON public.\"jansToken\" USING btree (\"ssnId\") jansToken jansToken_tknCde_idx CREATE INDEX \"jansToken_tknCde_idx\" ON public.\"jansToken\" USING btree (\"tknCde\") jansToken jansToken_del_exp_idx CREATE INDEX \"jansToken_del_exp_idx\" ON public.\"jansToken\" USING btree (del, exp)", "title": "jansToken"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansgrp", "text": "tablename indexname indexdef jansGrp jansGrp_pkey CREATE UNIQUE INDEX \"jansGrp_pkey\" ON public.\"jansGrp\" USING btree (doc_id) jansGrp jansGrp_description_idx CREATE INDEX \"jansGrp_description_idx\" ON public.\"jansGrp\" USING btree (description) jansGrp jansGrp_inum_idx CREATE INDEX \"jansGrp_inum_idx\" ON public.\"jansGrp\" USING btree (inum) jansGrp jansGrp_displayName_idx CREATE INDEX \"jansGrp_displayName_idx\" ON public.\"jansGrp\" USING btree (\"displayName\")", "title": "jansGrp"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansattr", "text": "tablename indexname indexdef jansAttr jansAttr_pkey CREATE UNIQUE INDEX \"jansAttr_pkey\" ON public.\"jansAttr\" USING btree (doc_id) jansAttr jansAttr_description_idx CREATE INDEX \"jansAttr_description_idx\" ON public.\"jansAttr\" USING btree (description) jansAttr jansAttr_jansAttrName_idx CREATE INDEX \"jansAttr_jansAttrName_idx\" ON public.\"jansAttr\" USING btree (\"jansAttrName\") jansAttr jansAttr_inum_idx CREATE INDEX \"jansAttr_inum_idx\" ON public.\"jansAttr\" USING btree (inum) jansAttr jansAttr_displayName_idx CREATE INDEX \"jansAttr_displayName_idx\" ON public.\"jansAttr\" USING btree (\"displayName\") jansAttr jansAttr_jansAttrOrigin_idx CREATE INDEX \"jansAttr_jansAttrOrigin_idx\" ON public.\"jansAttr\" USING btree (\"jansAttrOrigin\")", "title": "jansAttr"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janspassresetreq", "text": "tablename indexname indexdef jansPassResetReq jansPassResetReq_pkey CREATE UNIQUE INDEX \"jansPassResetReq_pkey\" ON public.\"jansPassResetReq\" USING btree (doc_id) jansPassResetReq jansPassResetReq_creationDate_idx CREATE INDEX \"jansPassResetReq_creationDate_idx\" ON public.\"jansPassResetReq\" USING btree (\"creationDate\")", "title": "jansPassResetReq"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janssessid", "text": "tablename indexname indexdef jansSessId jansSessId_pkey CREATE UNIQUE INDEX \"jansSessId_pkey\" ON public.\"jansSessId\" USING btree (doc_id) jansSessId jansSessId_sid_idx CREATE INDEX \"jansSessId_sid_idx\" ON public.\"jansSessId\" USING btree (sid) jansSessId jansSessId_deviceSecret_idx CREATE INDEX \"jansSessId_deviceSecret_idx\" ON public.\"jansSessId\" USING btree (\"deviceSecret\") jansSessId jansSessId_jansUsrDN_idx CREATE INDEX \"jansSessId_jansUsrDN_idx\" ON public.\"jansSessId\" USING btree (\"jansUsrDN\") jansSessId jansSessId_del_exp_idx CREATE INDEX \"jansSessId_del_exp_idx\" ON public.\"jansSessId\" USING btree (del, exp)", "title": "jansSessId"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansumarpt", "text": "tablename indexname indexdef jansUmaRPT jansUmaRPT_pkey CREATE UNIQUE INDEX \"jansUmaRPT_pkey\" ON public.\"jansUmaRPT\" USING btree (doc_id)", "title": "jansUmaRPT"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janspushapp", "text": "tablename indexname indexdef jansPushApp jansPushApp_pkey CREATE UNIQUE INDEX \"jansPushApp_pkey\" ON public.\"jansPushApp\" USING btree (doc_id)", "title": "jansPushApp"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansscr", "text": "tablename indexname indexdef jansScr jansScr_pkey CREATE UNIQUE INDEX \"jansScr_pkey\" ON public.\"jansScr\" USING btree (doc_id)", "title": "jansScr"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janscustomscr", "text": "tablename indexname indexdef jansCustomScr jansCustomScr_pkey CREATE UNIQUE INDEX \"jansCustomScr_pkey\" ON public.\"jansCustomScr\" USING btree (doc_id) jansCustomScr jansCustomScr_inum_idx CREATE INDEX \"jansCustomScr_inum_idx\" ON public.\"jansCustomScr\" USING btree (inum) jansCustomScr jansCustomScr_jansScrTyp_idx CREATE INDEX \"jansCustomScr_jansScrTyp_idx\" ON public.\"jansCustomScr\" USING btree (\"jansScrTyp\")", "title": "jansCustomScr"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansdeviceregistration", "text": "tablename indexname indexdef jansDeviceRegistration jansDeviceRegistration_pkey CREATE UNIQUE INDEX \"jansDeviceRegistration_pkey\" ON public.\"jansDeviceRegistration\" USING btree (doc_id) jansDeviceRegistration jansDeviceRegistration_jansDeviceKeyHandle_idx CREATE INDEX \"jansDeviceRegistration_jansDeviceKeyHandle_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansDeviceKeyHandle\") jansDeviceRegistration jansDeviceRegistration_jansApp_idx CREATE INDEX \"jansDeviceRegistration_jansApp_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansApp\") jansDeviceRegistration jansDeviceRegistration_personInum_idx CREATE INDEX \"jansDeviceRegistration_personInum_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"personInum\") jansDeviceRegistration jansDeviceRegistration_del_exp_idx CREATE INDEX \"jansDeviceRegistration_del_exp_idx\" ON public.\"jansDeviceRegistration\" USING btree (del, exp) jansDeviceRegistration jansDeviceRegistration_jansDeviceHashCode_idx CREATE INDEX \"jansDeviceRegistration_jansDeviceHashCode_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansDeviceHashCode\") jansDeviceRegistration jansDeviceRegistration_jansStatus_idx CREATE INDEX \"jansDeviceRegistration_jansStatus_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"jansStatus\") jansDeviceRegistration jansDeviceRegistration_creationDate_idx CREATE INDEX \"jansDeviceRegistration_creationDate_idx\" ON public.\"jansDeviceRegistration\" USING btree (\"creationDate\")", "title": "jansDeviceRegistration"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansu2freq", "text": "tablename indexname indexdef jansU2fReq jansU2fReq_pkey CREATE UNIQUE INDEX \"jansU2fReq_pkey\" ON public.\"jansU2fReq\" USING btree (doc_id) jansU2fReq jansU2fReq_del_exp_idx CREATE INDEX \"jansU2fReq_del_exp_idx\" ON public.\"jansU2fReq\" USING btree (del, exp) jansU2fReq jansU2fReq_creationDate_idx CREATE INDEX \"jansU2fReq_creationDate_idx\" ON public.\"jansU2fReq\" USING btree (\"creationDate\")", "title": "jansU2fReq"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansmetric", "text": "tablename indexname indexdef jansMetric jansMetric_pkey CREATE UNIQUE INDEX \"jansMetric_pkey\" ON public.\"jansMetric\" USING btree (doc_id) jansMetric jansMetric_jansEndDate_idx CREATE INDEX \"jansMetric_jansEndDate_idx\" ON public.\"jansMetric\" USING btree (\"jansEndDate\") jansMetric jansMetric_jansMetricTyp_idx CREATE INDEX \"jansMetric_jansMetricTyp_idx\" ON public.\"jansMetric\" USING btree (\"jansMetricTyp\") jansMetric jansMetric_jansStartDate_idx CREATE INDEX \"jansMetric_jansStartDate_idx\" ON public.\"jansMetric\" USING btree (\"jansStartDate\") jansMetric jansMetric_jansAppTyp_idx CREATE INDEX \"jansMetric_jansAppTyp_idx\" ON public.\"jansMetric\" USING btree (\"jansAppTyp\") jansMetric jansMetric_del_exp_idx CREATE INDEX \"jansMetric_del_exp_idx\" ON public.\"jansMetric\" USING btree (del, exp)", "title": "jansMetric"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansumapct", "text": "tablename indexname indexdef jansUmaPCT jansUmaPCT_pkey CREATE UNIQUE INDEX \"jansUmaPCT_pkey\" ON public.\"jansUmaPCT\" USING btree (doc_id) jansUmaPCT jansUmaPCT_tknCde_idx CREATE INDEX \"jansUmaPCT_tknCde_idx\" ON public.\"jansUmaPCT\" USING btree (\"tknCde\") jansUmaPCT jansUmaPCT_del_exp_idx CREATE INDEX \"jansUmaPCT_del_exp_idx\" ON public.\"jansUmaPCT\" USING btree (del, exp)", "title": "jansUmaPCT"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janscache", "text": "tablename indexname indexdef jansCache jansCache_pkey CREATE UNIQUE INDEX \"jansCache_pkey\" ON public.\"jansCache\" USING btree (doc_id) jansCache jansCache_del_exp_idx CREATE INDEX \"jansCache_del_exp_idx\" ON public.\"jansCache\" USING btree (del, exp)", "title": "jansCache"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansfido2registrationentry", "text": "tablename indexname indexdef jansFido2RegistrationEntry jansFido2RegistrationEntry_pkey CREATE UNIQUE INDEX \"jansFido2RegistrationEntry_pkey\" ON public.\"jansFido2RegistrationEntry\" USING btree (doc_id) jansFido2RegistrationEntry jansFido2RegistrationEntry_jansApp_idx CREATE INDEX \"jansFido2RegistrationEntry_jansApp_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansApp\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansCodeChallengeHash_idx CREATE INDEX \"jansFido2RegistrationEntry_jansCodeChallengeHash_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansCodeChallengeHash\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansPublicKeyIdHash_idx CREATE INDEX \"jansFido2RegistrationEntry_jansPublicKeyIdHash_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansPublicKeyIdHash\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansStatus_idx CREATE INDEX \"jansFido2RegistrationEntry_jansStatus_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansStatus\") jansFido2RegistrationEntry jansFido2RegistrationEntry_creationDate_idx CREATE INDEX \"jansFido2RegistrationEntry_creationDate_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"creationDate\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansCodeChallenge_idx CREATE INDEX \"jansFido2RegistrationEntry_jansCodeChallenge_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansCodeChallenge\") jansFido2RegistrationEntry jansFido2RegistrationEntry_jansPublicKeyId_idx CREATE INDEX \"jansFido2RegistrationEntry_jansPublicKeyId_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"jansPublicKeyId\") jansFido2RegistrationEntry jansFido2RegistrationEntry_personInum_idx CREATE INDEX \"jansFido2RegistrationEntry_personInum_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (\"personInum\") jansFido2RegistrationEntry jansFido2RegistrationEntry_del_exp_idx CREATE INDEX \"jansFido2RegistrationEntry_del_exp_idx\" ON public.\"jansFido2RegistrationEntry\" USING btree (del, exp)", "title": "jansFido2RegistrationEntry"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janspushdevice", "text": "tablename indexname indexdef jansPushDevice jansPushDevice_pkey CREATE UNIQUE INDEX \"jansPushDevice_pkey\" ON public.\"jansPushDevice\" USING btree (doc_id)", "title": "jansPushDevice"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansclntauthz", "text": "tablename indexname indexdef jansClntAuthz jansClntAuthz_pkey CREATE UNIQUE INDEX \"jansClntAuthz_pkey\" ON public.\"jansClntAuthz\" USING btree (doc_id) jansClntAuthz jansClntAuthz_jsonb_path_query_array_idx CREATE INDEX \"jansClntAuthz_jsonb_path_query_array_idx\" ON public.\"jansClntAuthz\" USING gin (jsonb_path_query_array(\"jansClntId\", '$[*]'::jsonpath)) jansClntAuthz jansClntAuthz_del_exp_idx CREATE INDEX \"jansClntAuthz_del_exp_idx\" ON public.\"jansClntAuthz\" USING btree (del, exp) jansClntAuthz jansClntAuthz_jansUsrId_idx CREATE INDEX \"jansClntAuthz_jansUsrId_idx\" ON public.\"jansClntAuthz\" USING btree (\"jansUsrId\")", "title": "jansClntAuthz"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janssectoridentifier", "text": "tablename indexname indexdef jansSectorIdentifier jansSectorIdentifier_pkey CREATE UNIQUE INDEX \"jansSectorIdentifier_pkey\" ON public.\"jansSectorIdentifier\" USING btree (doc_id)", "title": "jansSectorIdentifier"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansfido2authnentry", "text": "tablename indexname indexdef jansFido2AuthnEntry jansFido2AuthnEntry_pkey CREATE UNIQUE INDEX \"jansFido2AuthnEntry_pkey\" ON public.\"jansFido2AuthnEntry\" USING btree (doc_id) jansFido2AuthnEntry jansFido2AuthnEntry_jansApp_idx CREATE INDEX \"jansFido2AuthnEntry_jansApp_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansApp\") jansFido2AuthnEntry jansFido2AuthnEntry_jansCodeChallengeHash_idx CREATE INDEX \"jansFido2AuthnEntry_jansCodeChallengeHash_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansCodeChallengeHash\") jansFido2AuthnEntry jansFido2AuthnEntry_jansStatus_idx CREATE INDEX \"jansFido2AuthnEntry_jansStatus_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansStatus\") jansFido2AuthnEntry jansFido2AuthnEntry_creationDate_idx CREATE INDEX \"jansFido2AuthnEntry_creationDate_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"creationDate\") jansFido2AuthnEntry jansFido2AuthnEntry_jansCodeChallenge_idx CREATE INDEX \"jansFido2AuthnEntry_jansCodeChallenge_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"jansCodeChallenge\") jansFido2AuthnEntry jansFido2AuthnEntry_personInum_idx CREATE INDEX \"jansFido2AuthnEntry_personInum_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (\"personInum\") jansFido2AuthnEntry jansFido2AuthnEntry_del_exp_idx CREATE INDEX \"jansFido2AuthnEntry_del_exp_idx\" ON public.\"jansFido2AuthnEntry\" USING btree (del, exp)", "title": "jansFido2AuthnEntry"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansrp", "text": "tablename indexname indexdef jansRp jansRp_pkey CREATE UNIQUE INDEX \"jansRp_pkey\" ON public.\"jansRp\" USING btree (doc_id)", "title": "jansRp"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janscibareq", "text": "tablename indexname indexdef jansCibaReq jansCibaReq_pkey CREATE UNIQUE INDEX \"jansCibaReq_pkey\" ON public.\"jansCibaReq\" USING btree (doc_id) jansCibaReq jansCibaReq_jansStatus_exp_idx CREATE INDEX \"jansCibaReq_jansStatus_exp_idx\" ON public.\"jansCibaReq\" USING btree (\"jansStatus\", exp)", "title": "jansCibaReq"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansstatentry", "text": "tablename indexname indexdef jansStatEntry jansStatEntry_pkey CREATE UNIQUE INDEX \"jansStatEntry_pkey\" ON public.\"jansStatEntry\" USING btree (doc_id) jansStatEntry jansStatEntry_jansId_idx CREATE INDEX \"jansStatEntry_jansId_idx\" ON public.\"jansStatEntry\" USING btree (\"jansId\")", "title": "jansStatEntry"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#janspar", "text": "tablename indexname indexdef jansPar jansPar_pkey CREATE UNIQUE INDEX \"jansPar_pkey\" ON public.\"jansPar\" USING btree (doc_id) jansPar jansPar_jansId_idx CREATE INDEX \"jansPar_jansId_idx\" ON public.\"jansPar\" USING btree (\"jansId\") jansPar jansPar_del_exp_idx CREATE INDEX \"jansPar_del_exp_idx\" ON public.\"jansPar\" USING btree (del, exp)", "title": "jansPar"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansinummap", "text": "tablename indexname indexdef jansInumMap jansInumMap_pkey CREATE UNIQUE INDEX \"jansInumMap_pkey\" ON public.\"jansInumMap\" USING btree (doc_id) jansInumMap jansInumMap_jansStatus_idx CREATE INDEX \"jansInumMap_jansStatus_idx\" ON public.\"jansInumMap\" USING btree (\"jansStatus\") jansInumMap jansInumMap_inum_idx CREATE INDEX \"jansInumMap_inum_idx\" ON public.\"jansInumMap\" USING btree (inum)", "title": "jansInumMap"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#agmflowrun", "text": "tablename indexname indexdef agmFlowRun agmFlowRun_pkey CREATE UNIQUE INDEX \"agmFlowRun_pkey\" ON public.\"agmFlowRun\" USING btree (doc_id)", "title": "agmFlowRun"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#agmflow", "text": "tablename indexname indexdef agmFlow agmFlow_pkey CREATE UNIQUE INDEX \"agmFlow_pkey\" ON public.\"agmFlow\" USING btree (doc_id)", "title": "agmFlow"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#adsprjdeployment", "text": "tablename indexname indexdef adsPrjDeployment adsPrjDeployment_pkey CREATE UNIQUE INDEX \"adsPrjDeployment_pkey\" ON public.\"adsPrjDeployment\" USING btree (doc_id)", "title": "adsPrjDeployment"}, {"location": "janssen-server/reference/database/pgsql-schema-indexes/#jansdocument", "text": "tablename indexname indexdef jansDocument jansDocument_pkey CREATE UNIQUE INDEX \"jansDocument_pkey\" ON public.\"jansDocument\" USING btree (doc_id)", "title": "jansDocument"}, {"location": "janssen-server/reference/database/pgsql-schema/", "tags": ["administration", "database", "PostgreSQL", "Indexes"], "text": "PostgreSQL Schema # Tables # Table names jansPairwiseIdentifier jansPerson jansOrganization jansSsa jansAppConf jansClnt jansScope jansUmaResource jansUmaResourcePermission jansGrant jansToken jansGrp jansAttr jansPassResetReq jansSessId jansUmaRPT jansPushApp jansScr jansCustomScr jansDeviceRegistration jansU2fReq jansMetric jansUmaPCT jansCache jansFido2RegistrationEntry jansPushDevice jansClntAuthz jansSectorIdentifier jansFido2AuthnEntry jansRp jansCibaReq jansStatEntry jansPar jansInumMap agmFlowRun agmFlow adsPrjDeployment jansDocument jansPairwiseIdentifier # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansSectorIdentifier character varying 64 YES None jans Sector Identifier jansClntId jsonb None YES None jans Clnt id jansUsrId character varying 64 YES None jans user id jansPerson # Field Type Character Maximum Length Null Default Comment jansAssociatedClnt jsonb None YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansManagedOrganizations character varying 64 YES None Used to track with which organizations a person is associated jansOptOuts jsonb None YES None White pages attributes restricted by person in exclude profile management jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansPersistentJWT jsonb None YES None jans Persistent JWT jansCreationTimestamp timestamp without time zone None YES None Registration time jansOTPCache jsonb None YES None Stores a used OTP to prevent a hacker from using it again. Complementary to jansExtUid attribute jansLastLogonTime timestamp without time zone None YES None Last logon time jansPassExpDate timestamp without time zone None YES None Pass Exp date, represented as an ISO 8601 (YYYY-MM-DD) format persistentId character varying 64 YES None PersistentId middleName character varying 64 YES None Middle name(s) nickname character varying 64 YES None Casual name of the End-Usr jansPrefUsrName character varying 64 YES None Shorthand Name profile character varying 64 YES None Profile page URL of the person picture text None YES None Profile picture URL of the person website character varying 64 YES None Web page or blog URL of the person emailVerified boolean None YES None True if the e-mail address of the person has been verified; otherwise false gender character varying 32 YES None Gender of the person either female or male birthdate timestamp without time zone None YES None Birthday of the person, represented as an ISO 8601:2004 [ISO8601-2004] YYYY-MM-DD format zoneinfo character varying 64 YES None Time zone database representing the End-Usrs time zone. For example, Europe/Paris or America/Los_Angeles locale character varying 64 YES None Locale of the person, represented as a BCP47 [RFC5646] language tag phoneNumberVerified boolean None YES None True if the phone number of the person has been verified, otherwise false address text None YES None OpenID Connect formatted JSON object representing the address of the person updatedAt timestamp without time zone None YES None Time the information of the person was last updated. Seconds from 1970-01-01T0:0:0Z preferredLanguage character varying 64 YES None preferred written or spoken language for a person role jsonb None YES None Role secretAnswer text None YES None Secret Answer secretQuestion text None YES None Secret Question transientId character varying 64 YES None TransientId jansCountInvalidLogin character varying 64 YES None Invalid login attempts count jansEnrollmentCode character varying 64 YES None jansEnrollmentCode jansIMAPData character varying 64 YES None This data has information about your imap connection jansPPID jsonb None YES None Persistent Pairwise ID for OpenID Connect jansGuid character varying 64 YES None A random string to mark temporary tokens jansPreferredMethod character varying 64 YES None Casa - Preferred method to use for user authentication jansOTPDevices character varying 512 YES None Casa - Json representation of OTP devices. Complementary to jansExtUid attribute jansMobileDevices character varying 512 YES None Casa - Json representation of mobile devices. Complementary to mobile attribute jansTrustedDevices text None YES None Casa - Devices with which strong authentication may be skipped jansStrongAuthPolicy character varying 64 YES None Casa - 2FA Enforcement Policy for User jansUnlinkedExternalUids character varying 64 YES None Casa - List of unlinked social accounts (ie disabled jansExtUids) jansBackchannelDeviceRegistrationTkn character varying 64 YES None jans Backchannel Device Registration Tkn jansBackchannelUsrCode character varying 64 YES None jans Backchannel Usr Code carLicense character varying 64 YES None vehicle license or registration plate departmentNumber character varying 64 YES None identifies a department within an organization employeeType character varying 64 YES None type of employment for a person employeeNumber character varying 64 YES None numerically identifies an employee within an organization jansAdminUIRole jsonb None YES None jansAdminUIRole jansOrganization # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansCustomMessage character varying 128 YES None exclude custom welcome message jansFaviconImage character varying 64 YES None TODO - Stores URL of favicon jansLogoImage character varying 64 YES None Logo used by exclude for default look and feel. jansManager character varying 64 YES None Used to specify if a person has the manager role jansManagerGrp text None YES None Used in organizatoin entry to specifies the dn of the group that has admin priviledges in exclude. jansOrgShortName character varying 64 YES None Short description, as few letters as possible, no spaces. jansThemeColor character varying 64 YES None exclude login page configuration inum character varying 64 YES None XRI i-number jansCreationTimestamp timestamp without time zone None YES None Registration time jansRegistrationConf character varying 64 YES None Registration Conf jansLogoPath character varying 64 YES None jansLogoPath jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansFaviconPath character varying 64 YES None jansFaviconPath jansSsa # Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansState character varying 64 YES None jansState creatorId character varying 64 YES None Creator Id creatorTyp character varying 64 YES None Creator type creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansAppConf # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansHostname character varying 64 YES None The hostname of the Jans Server instance jansLastUpd timestamp without time zone None YES None Monitors last time the server was able to connect to the monitoring system. jansManager character varying 64 YES None Used to specify if a person has the manager role jansOrgProfileMgt boolean None YES None enable or disable profile management feature in exclude jansScimEnabled boolean None YES None exclude SCIM feature - enabled or disabled jansSmtpConf jsonb None YES None SMTP configuration jansSslExpiry character varying 64 YES None SAML Trust Relationship configuration jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansUrl character varying 64 YES None Jans instance URL inum character varying 64 YES None XRI i-number jansDbAuth jsonb None YES None Custom IDP authentication configuration jansLogViewerConfig character varying 64 YES None Log viewer configuration jansLogConfigLocation character varying 64 YES None Path to external log4j2.xml jansCacheConf text None YES None Cache configuration jansDocStoreConf text None YES None jansDocStoreConf jansConfDyn text None YES None jans Dyn Conf jansConfErrors text None YES None jans Errors Conf jansConfStatic text None YES None jans Static Conf jansConfWebKeys text None YES None jans Web Keys Conf jansWebKeysSettings character varying 64 YES None jans Web Keys Conf jansConfApp text None YES None jans App Conf jansRevision integer None YES None Revision jansClnt # Field Type Character Maximum Length Null Default Comment jansGrp character varying 64 YES None Group displayName character varying 128 YES None preferred name of a person to be used when displaying entries displayNameLocalized jsonb None YES None jans Display Name Localized inum character varying 64 YES None XRI i-number jansAppTyp character varying 64 YES None jans App Typ jansClntIdIssuedAt timestamp without time zone None YES None jans Clnt Issued At jansClntSecret character varying 64 YES None jans Clnt Secret jansClntSecretExpAt timestamp without time zone None YES None Date client expires exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansClntURI text None YES None jans Clnt URI jansClntURILocalized jsonb None YES None jans Clnt URI localized jansContact jsonb None YES None jans Contact jansDefAcrValues jsonb None YES None jans Def Acr Values jansDefMaxAge integer None YES None jans Def Max Age jansGrantTyp jsonb None YES None jans Grant Typ jansIdTknEncRespAlg character varying 64 YES None jans ID Tkn Enc Resp Alg jansIdTknEncRespEnc character varying 64 YES None jans ID Tkn Enc Resp Enc jansIdTknSignedRespAlg character varying 64 YES None jans ID Tkn Signed Resp Alg jansInitiateLoginURI text None YES None jans Initiate Login URI jansJwksURI text None YES None jans JWKs URI jansJwks text None YES None jans JWKs jansLogoURI text None YES None jans Logo URI jansLogoURILocalized jsonb None YES None jans Logo URI localized jansPolicyURI text None YES None jans Policy URI jansPolicyURILocalized jsonb None YES None jans Policy URI localized jansPostLogoutRedirectURI jsonb None YES None jans Post Logout Redirect URI jansRedirectURI jsonb None YES None jans Redirect URI jansRegistrationAccessTkn character varying 64 YES None jans Registration Access Tkn jansReqObjSigAlg character varying 64 YES None jans Req Obj Sig Alg jansReqObjEncAlg character varying 64 YES None jans Req Obj Enc Alg jansReqObjEncEnc character varying 64 YES None jans Req Obj Enc Enc jansReqURI jsonb None YES None jans Req URI jansRespTyp jsonb None YES None jans Resp Typ jansScope jsonb None YES None jans Attr Scope jansClaim jsonb None YES None jans Attr Claim jansSectorIdentifierURI text None YES None jans Sector Identifier URI jansSignedRespAlg character varying 64 YES None jans Signed Resp Alg jansSubjectTyp character varying 64 YES None jans Subject Typ jansTknEndpointAuthMethod character varying 64 YES None jans Tkn Endpoint Auth Method jansTknEndpointAuthSigAlg character varying 64 YES None jans Tkn Endpoint Auth Sig Alg jansTosURI text None YES None jans TOS URI jansTosURILocalized jsonb None YES None jans Tos URI localized jansTrustedClnt boolean None YES None jans Trusted Clnt jansUsrInfEncRespAlg character varying 64 YES None jans Usr Inf Enc Resp Alg jansUsrInfEncRespEnc character varying 64 YES None jans Usr Inf Enc Resp Enc jansExtraConf character varying 64 YES None jans additional configuration jansClaimRedirectURI jsonb None YES None Claim Redirect URI jansLastAccessTime timestamp without time zone None YES None Last access time jansLastLogonTime timestamp without time zone None YES None Last logon time jansPersistClntAuthzs boolean None YES None jans Persist Clnt Authzs jansInclClaimsInIdTkn boolean None YES None jans Incl Claims In Id Tkn jansRefreshTknLife integer None YES None Life of refresh token jansDisabled boolean None YES None Status of client jansLogoutURI jsonb None YES None jans Policy URI jansLogoutSessRequired boolean None YES None jans Policy URI jansdId character varying 64 YES None jansd Id jansAuthorizedOrigins jsonb None YES None jans Authorized Origins tknBndCnf text None YES None jansauth - Tkn Binding Id Hash jansAccessTknAsJwt boolean None YES None jansauth - indicator whether to return access token as JWT jansAccessTknSigAlg character varying 64 YES None jansauth - access token signing algorithm jansAccessTknLife integer None YES None Life of access token jansSoftId character varying 64 YES None Soft Identifier jansSoftStatement text None YES None Soft Statement jansRptAsJwt boolean None YES None jansRptAsJwt jansAttrs text None YES None Attrs jansBackchannelTknDeliveryMode character varying 64 YES None jans Backchannel Tkn Delivery Mode jansBackchannelClntNotificationEndpoint character varying 64 YES None jans Backchannel Clnt Notification Endpoint jansBackchannelAuthnReqSigAlg character varying 64 YES None jans Backchannel Authn Req Sig Alg jansBackchannelUsrCodeParameter boolean None YES None jans Backchannel Usr Code Parameter jansScope # Field Type Character Maximum Length Null Default Comment jansDefScope boolean None YES None Track the default scope for an custom OAuth2 Scope. displayName character varying 128 YES None preferred name of a person to be used when displaying entries inum character varying 64 YES None XRI i-number jansScopeTyp character varying 64 YES None OX Attr Scope type creatorId character varying 64 YES None Creator Id creatorTyp character varying 64 YES None Creator type creatorAttrs character varying 64 YES None Creator Attrs creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansClaim jsonb None YES None jans Attr Claim jansScrDn jsonb None YES None Script object DN jansGrpClaims boolean None YES None jans Grp Attr Claims (true or false) jansId character varying 128 YES None Identifier jansIconUrl character varying 64 YES None jans icon url jansUmaPolicyScrDn text None YES None OX policy script Dn jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansUmaResource # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries inum character varying 64 YES None XRI i-number jansAssociatedClnt jsonb None YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. jansUmaScope character varying 768 YES None URI reference of scope descriptor jansFaviconImage character varying 64 YES None TODO - Stores URL of favicon jansGrp character varying 64 YES None Group jansId character varying 128 YES None Identifier jansResource text None YES None Host path jansRevision integer None YES None Revision jansTyp character varying 64 YES None jans type jansScopeExpression text None YES None Scope expression iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansUmaResourcePermission # Field Type Character Maximum Length Null Default Comment exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansUmaScope character varying 768 YES None URI reference of scope descriptor jansConfCode character varying 64 YES None jans configuration code jansResourceSetId character varying 64 YES None jans resource set id jansAttrs text None YES None Attrs jansTicket character varying 64 YES None jans ticket jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansGrant # Field Type Character Maximum Length Null Default Comment grtId character varying 64 YES None jans grant id iat timestamp without time zone None YES None jans Creation jansToken # Field Type Character Maximum Length Null Default Comment authnTime timestamp without time zone None YES None jans Authn Time authzCode character varying 64 YES None jans authorization code iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknCde character varying 80 YES None jans Tkn Code tknTyp character varying 32 YES None jans Tkn Typ usrId character varying 64 YES None jans user id jansUsrDN character varying 128 YES None jans Usr DN clnId character varying 64 YES None jans Clnt id uuid character varying 64 YES None Unique identifier chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims ssnId character varying 64 YES None jans Sess DN attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash dpop character varying 64 YES None DPoP Proof jansGrp # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansAttr # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansAttrEditTyp jsonb None YES None Specify in exclude who can update an attribute, admin or user jansAttrName character varying 64 YES None Specify an identifier for an attribute. May be multi-value where an attribute has two names, like givenName and first-name. jansAttrOrigin character varying 64 YES None Specify the person objectclass associated with the attribute, used for display purposes in exclude. jansAttrSystemEditTyp character varying 64 YES None TODO - still required? jansAttrTyp character varying 64 YES None Data type of attribute. Values can be string, photo, numeric, date jansClaimName character varying 64 YES None Used by jans in conjunction with jansttributeName to map claims to attributes in LDAP. jansAttrUsgTyp character varying 64 YES None TODO - Usg? Value can be OpenID jansAttrViewTyp jsonb None YES None Specify in exclude who can view an attribute, admin or user jansSAML1URI character varying 64 YES None SAML 1 uri of attribute jansSAML2URI character varying 64 YES None SAML 2 uri of attribute jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansNameIdTyp character varying 64 YES None NameId Typ jansSourceAttr character varying 64 YES None Source Attr for this Attr jansRegExp character varying 64 YES None Regular expression used to validate attribute data jansTooltip character varying 64 YES None Custom tooltip to be shown on the UI jansValidation text None YES None This data has information about attribute Validation jansPassResetReq # Field Type Character Maximum Length Null Default Comment creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansGuid character varying 64 YES None A random string to mark temporary tokens personInum character varying 64 YES None Inum of a person jansSessId # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier sid character varying 64 YES None Sess Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansLastAccessTime timestamp without time zone None YES None Last access time jansUsrDN character varying 128 YES None jans Usr DN authnTime timestamp without time zone None YES None jans Authn Time jansState character varying 64 YES None jansState jansSessState text None YES None jans Sess State jansPermissionGranted boolean None YES None jans Permission Granted jansAsJwt boolean None YES None Boolean field to indicate whether object is used as JWT jansJwt text None YES None JWT representation of the object or otherwise jwt associated with the object jansPermissionGrantedMap text None YES None jans Permission Granted Map jansInvolvedClnts text None YES None Involved clients deviceSecret character varying 64 YES None deviceSecret jansSessAttr text None YES None jansSessAttr jansUmaRPT # Field Type Character Maximum Length Null Default Comment authnTime timestamp without time zone None YES None jans Authn Time clnId character varying 64 YES None jans Clnt id iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del tknCde character varying 80 YES None jans Tkn Code usrId character varying 64 YES None jans user id ssnId character varying 64 YES None jans Sess DN jansUmaPermission jsonb None YES None jans uma permission uuid character varying 64 YES None Unique identifier dpop character varying 64 YES None DPoP Proof authzCode character varying 64 YES None jans authorization code grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknTyp character varying 32 YES None jans Tkn Typ jansUsrDN character varying 128 YES None jans Usr DN chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash jansPushApp # Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansId character varying 128 YES None Identifier jansName character varying 64 YES None Name jansPushAppConf character varying 64 YES None jansPush application configuration jansScr # Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number jansScr text None YES None Attr that contains script (python, java script) jansScrTyp character varying 64 YES None Attr that contains script type (e.g. python, java script) jansCustomScr # Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansScr text None YES None Attr that contains script (python, java script) jansScrTyp character varying 64 YES None Attr that contains script type (e.g. python, java script) jansProgLng character varying 64 YES None programming language jansModuleProperty jsonb None YES None Module property jansConfProperty jsonb None YES None Conf property jansLevel integer None YES None Level jansRevision integer None YES None Revision jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansScrError text None YES None Attr that contains first error which application get during it execution jansAlias jsonb None YES None jansAlias jansDeviceRegistration # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansDeviceKeyHandle character varying 128 YES None jansDeviceKeyHandle jansDeviceHashCode integer None YES None jansDeviceHashCode jansApp character varying 96 YES None jansApp jansDeviceRegistrationConf text None YES None jansDeviceRegistrationConf jansDeviceNotificationConf character varying 64 YES None Extended push notification configuration jansNickName character varying 64 YES None jansNickName jansDeviceData text None YES None jansDeviceData jansCounter integer None YES None jansCounter jansStatus character varying 16 YES None Status of the entry, used by many objectclasses del boolean None YES None del exp timestamp without time zone None YES None jans Exp personInum character varying 64 YES None Inum of a person creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansLastAccessTime timestamp without time zone None YES None Last access time jansU2fReq # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansReqId character varying 64 YES None jansReqId jansReq text None YES None jansReq jansSessStateId character varying 64 YES None jansSessStateId del boolean None YES None del exp timestamp without time zone None YES None jans Exp personInum character varying 64 YES None Inum of a person creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansMetric # Field Type Character Maximum Length Null Default Comment jansStartDate timestamp without time zone None YES None Start date jansEndDate timestamp without time zone None YES None End date jansAppTyp character varying 64 YES None jans App Typ jansMetricTyp character varying 64 YES None Metric type creationDate timestamp without time zone None YES None Creation Date used for password reset requests del boolean None YES None del exp timestamp without time zone None YES None jans Exp jansData text None YES None OX data jansHost character varying 64 YES None jans host jansUmaPCT # Field Type Character Maximum Length Null Default Comment clnId character varying 64 YES None jans Clnt id iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del tknCde character varying 80 YES None jans Tkn Code ssnId character varying 64 YES None jans Sess DN jansClaimValues character varying 64 YES None Claim Values dpop character varying 64 YES None DPoP Proof authnTime timestamp without time zone None YES None jans Authn Time authzCode character varying 64 YES None jans authorization code grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknTyp character varying 32 YES None jans Tkn Typ usrId character varying 64 YES None jans user id jansUsrDN character varying 128 YES None jans Usr DN uuid character varying 64 YES None Unique identifier chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash jansCache # Field Type Character Maximum Length Null Default Comment uuid character varying 64 YES None Unique identifier iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del dat text None YES None OX data jansFido2RegistrationEntry # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansApp character varying 96 YES None jansApp jansSessStateId character varying 64 YES None jansSessStateId jansCodeChallenge character varying 64 YES None OX PKCE code challenge jansCodeChallengeHash integer None YES None OX code challenge hash jansPublicKeyId character varying 96 YES None jansPublicKeyId jansPublicKeyIdHash integer None YES None jansPublicKeyIdHash personInum character varying 64 YES None Inum of a person jansRegistrationData text None YES None jansRegistrationData jansDeviceData text None YES None jansDeviceData jansDeviceNotificationConf character varying 64 YES None Extended push notification configuration jansCounter integer None YES None jansCounter jansStatus character varying 16 YES None Status of the entry, used by many objectclasses exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansPushDevice # Field Type Character Maximum Length Null Default Comment jansUsrId character varying 64 YES None jans user id jansId character varying 128 YES None Identifier jansPushApp text None YES None jansPush application DN jansPushDeviceConf character varying 64 YES None jansPush device configuration jansTyp character varying 64 YES None jans type jansClntAuthz # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansClntId jsonb None YES None jans Clnt id jansUsrId character varying 64 YES None jans user id exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansScope jsonb None YES None jans Attr Scope jansSectorIdentifier # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansRedirectURI jsonb None YES None jans Redirect URI jansClntId jsonb None YES None jans Clnt id jansFido2AuthnEntry # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansApp character varying 96 YES None jansApp jansSessStateId character varying 64 YES None jansSessStateId jansCodeChallenge character varying 64 YES None OX PKCE code challenge jansCodeChallengeHash integer None YES None OX code challenge hash personInum character varying 64 YES None Inum of a person jansAuthData text None YES None jansAuthData jansStatus character varying 16 YES None Status of the entry, used by many objectclasses exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansRp # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier dat text None YES None OX data jansCibaReq # Field Type Character Maximum Length Null Default Comment authReqId character varying 64 YES None Authn request id clnId character varying 64 YES None jans Clnt id usrId character varying 64 YES None jans user id creationDate timestamp without time zone None YES None Creation Date used for password reset requests exp timestamp without time zone None YES None jans Exp jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansStatEntry # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier dat text None YES None OX data jansData text None YES None OX data attr text None YES None Attrs jansPar # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansInumMap # Field Type Character Maximum Length Null Default Comment jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansPrimaryKeyAttrName character varying 64 YES None Primary Key Attribute Name jansPrimaryKeyValue character varying 64 YES None Primary Key Value jansSecondaryKeyAttrName character varying 64 YES None Secondary Key Attribute Name jansSecondaryKeyValue character varying 64 YES None Secondary Key Value jansTertiaryKeyAttrName character varying 64 YES None Tertiary Key Attribute Name jansTertiaryKeyValue character varying 64 YES None Tertiary Key Value agmFlowRun # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier agFlowSt text None YES None Details of a running agama flow instance agFlowEncCont text None YES None Continuation associated to a running agama flow instance jansCustomMessage character varying 128 YES None exclude custom welcome message exp timestamp without time zone None YES None jans Exp agmFlow # Field Type Character Maximum Length Null Default Comment agFlowQname character varying 64 YES None Full name of an agama flow agFlowMeta text None YES None Metadata of an agama flow jansScr text None YES None Attr that contains script (python, java script) jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansScrError text None YES None Attr that contains first error which application get during it execution agFlowTrans text None YES None Transpiled code of an agama flow jansRevision integer None YES None Revision jansCustomMessage character varying 128 YES None exclude custom welcome message adsPrjDeployment # Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansStartDate timestamp without time zone None YES None Start date jansEndDate timestamp without time zone None YES None End date adsPrjAssets text None YES None Assets of an ADS project adsPrjDeplDetails text None YES None Misc details associated to an ADS project jansDocument # Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number displayName character varying 128 YES None preferred name of a person to be used when displaying entries document character varying 64 YES None Save Document in DB creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansModuleProperty jsonb None YES None Module property jansLevel integer None YES None Level jansRevision integer None YES None Revision jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansAlias jsonb None YES None jansAlias", "title": "PostgreSQL Schema"}, {"location": "janssen-server/reference/database/pgsql-schema/#postgresql-schema", "text": "", "title": "PostgreSQL Schema"}, {"location": "janssen-server/reference/database/pgsql-schema/#tables", "text": "Table names jansPairwiseIdentifier jansPerson jansOrganization jansSsa jansAppConf jansClnt jansScope jansUmaResource jansUmaResourcePermission jansGrant jansToken jansGrp jansAttr jansPassResetReq jansSessId jansUmaRPT jansPushApp jansScr jansCustomScr jansDeviceRegistration jansU2fReq jansMetric jansUmaPCT jansCache jansFido2RegistrationEntry jansPushDevice jansClntAuthz jansSectorIdentifier jansFido2AuthnEntry jansRp jansCibaReq jansStatEntry jansPar jansInumMap agmFlowRun agmFlow adsPrjDeployment jansDocument", "title": "Tables"}, {"location": "janssen-server/reference/database/pgsql-schema/#janspairwiseidentifier", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansSectorIdentifier character varying 64 YES None jans Sector Identifier jansClntId jsonb None YES None jans Clnt id jansUsrId character varying 64 YES None jans user id", "title": "jansPairwiseIdentifier"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansperson", "text": "Field Type Character Maximum Length Null Default Comment jansAssociatedClnt jsonb None YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansManagedOrganizations character varying 64 YES None Used to track with which organizations a person is associated jansOptOuts jsonb None YES None White pages attributes restricted by person in exclude profile management jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansPersistentJWT jsonb None YES None jans Persistent JWT jansCreationTimestamp timestamp without time zone None YES None Registration time jansOTPCache jsonb None YES None Stores a used OTP to prevent a hacker from using it again. Complementary to jansExtUid attribute jansLastLogonTime timestamp without time zone None YES None Last logon time jansPassExpDate timestamp without time zone None YES None Pass Exp date, represented as an ISO 8601 (YYYY-MM-DD) format persistentId character varying 64 YES None PersistentId middleName character varying 64 YES None Middle name(s) nickname character varying 64 YES None Casual name of the End-Usr jansPrefUsrName character varying 64 YES None Shorthand Name profile character varying 64 YES None Profile page URL of the person picture text None YES None Profile picture URL of the person website character varying 64 YES None Web page or blog URL of the person emailVerified boolean None YES None True if the e-mail address of the person has been verified; otherwise false gender character varying 32 YES None Gender of the person either female or male birthdate timestamp without time zone None YES None Birthday of the person, represented as an ISO 8601:2004 [ISO8601-2004] YYYY-MM-DD format zoneinfo character varying 64 YES None Time zone database representing the End-Usrs time zone. For example, Europe/Paris or America/Los_Angeles locale character varying 64 YES None Locale of the person, represented as a BCP47 [RFC5646] language tag phoneNumberVerified boolean None YES None True if the phone number of the person has been verified, otherwise false address text None YES None OpenID Connect formatted JSON object representing the address of the person updatedAt timestamp without time zone None YES None Time the information of the person was last updated. Seconds from 1970-01-01T0:0:0Z preferredLanguage character varying 64 YES None preferred written or spoken language for a person role jsonb None YES None Role secretAnswer text None YES None Secret Answer secretQuestion text None YES None Secret Question transientId character varying 64 YES None TransientId jansCountInvalidLogin character varying 64 YES None Invalid login attempts count jansEnrollmentCode character varying 64 YES None jansEnrollmentCode jansIMAPData character varying 64 YES None This data has information about your imap connection jansPPID jsonb None YES None Persistent Pairwise ID for OpenID Connect jansGuid character varying 64 YES None A random string to mark temporary tokens jansPreferredMethod character varying 64 YES None Casa - Preferred method to use for user authentication jansOTPDevices character varying 512 YES None Casa - Json representation of OTP devices. Complementary to jansExtUid attribute jansMobileDevices character varying 512 YES None Casa - Json representation of mobile devices. Complementary to mobile attribute jansTrustedDevices text None YES None Casa - Devices with which strong authentication may be skipped jansStrongAuthPolicy character varying 64 YES None Casa - 2FA Enforcement Policy for User jansUnlinkedExternalUids character varying 64 YES None Casa - List of unlinked social accounts (ie disabled jansExtUids) jansBackchannelDeviceRegistrationTkn character varying 64 YES None jans Backchannel Device Registration Tkn jansBackchannelUsrCode character varying 64 YES None jans Backchannel Usr Code carLicense character varying 64 YES None vehicle license or registration plate departmentNumber character varying 64 YES None identifies a department within an organization employeeType character varying 64 YES None type of employment for a person employeeNumber character varying 64 YES None numerically identifies an employee within an organization jansAdminUIRole jsonb None YES None jansAdminUIRole", "title": "jansPerson"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansorganization", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansCustomMessage character varying 128 YES None exclude custom welcome message jansFaviconImage character varying 64 YES None TODO - Stores URL of favicon jansLogoImage character varying 64 YES None Logo used by exclude for default look and feel. jansManager character varying 64 YES None Used to specify if a person has the manager role jansManagerGrp text None YES None Used in organizatoin entry to specifies the dn of the group that has admin priviledges in exclude. jansOrgShortName character varying 64 YES None Short description, as few letters as possible, no spaces. jansThemeColor character varying 64 YES None exclude login page configuration inum character varying 64 YES None XRI i-number jansCreationTimestamp timestamp without time zone None YES None Registration time jansRegistrationConf character varying 64 YES None Registration Conf jansLogoPath character varying 64 YES None jansLogoPath jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansFaviconPath character varying 64 YES None jansFaviconPath", "title": "jansOrganization"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansssa", "text": "Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansState character varying 64 YES None jansState creatorId character varying 64 YES None Creator Id creatorTyp character varying 64 YES None Creator type creationDate timestamp without time zone None YES None Creation Date used for password reset requests", "title": "jansSsa"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansappconf", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansHostname character varying 64 YES None The hostname of the Jans Server instance jansLastUpd timestamp without time zone None YES None Monitors last time the server was able to connect to the monitoring system. jansManager character varying 64 YES None Used to specify if a person has the manager role jansOrgProfileMgt boolean None YES None enable or disable profile management feature in exclude jansScimEnabled boolean None YES None exclude SCIM feature - enabled or disabled jansSmtpConf jsonb None YES None SMTP configuration jansSslExpiry character varying 64 YES None SAML Trust Relationship configuration jansStatus character varying 16 YES None Status of the entry, used by many objectclasses jansUrl character varying 64 YES None Jans instance URL inum character varying 64 YES None XRI i-number jansDbAuth jsonb None YES None Custom IDP authentication configuration jansLogViewerConfig character varying 64 YES None Log viewer configuration jansLogConfigLocation character varying 64 YES None Path to external log4j2.xml jansCacheConf text None YES None Cache configuration jansDocStoreConf text None YES None jansDocStoreConf jansConfDyn text None YES None jans Dyn Conf jansConfErrors text None YES None jans Errors Conf jansConfStatic text None YES None jans Static Conf jansConfWebKeys text None YES None jans Web Keys Conf jansWebKeysSettings character varying 64 YES None jans Web Keys Conf jansConfApp text None YES None jans App Conf jansRevision integer None YES None Revision", "title": "jansAppConf"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansclnt", "text": "Field Type Character Maximum Length Null Default Comment jansGrp character varying 64 YES None Group displayName character varying 128 YES None preferred name of a person to be used when displaying entries displayNameLocalized jsonb None YES None jans Display Name Localized inum character varying 64 YES None XRI i-number jansAppTyp character varying 64 YES None jans App Typ jansClntIdIssuedAt timestamp without time zone None YES None jans Clnt Issued At jansClntSecret character varying 64 YES None jans Clnt Secret jansClntSecretExpAt timestamp without time zone None YES None Date client expires exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansClntURI text None YES None jans Clnt URI jansClntURILocalized jsonb None YES None jans Clnt URI localized jansContact jsonb None YES None jans Contact jansDefAcrValues jsonb None YES None jans Def Acr Values jansDefMaxAge integer None YES None jans Def Max Age jansGrantTyp jsonb None YES None jans Grant Typ jansIdTknEncRespAlg character varying 64 YES None jans ID Tkn Enc Resp Alg jansIdTknEncRespEnc character varying 64 YES None jans ID Tkn Enc Resp Enc jansIdTknSignedRespAlg character varying 64 YES None jans ID Tkn Signed Resp Alg jansInitiateLoginURI text None YES None jans Initiate Login URI jansJwksURI text None YES None jans JWKs URI jansJwks text None YES None jans JWKs jansLogoURI text None YES None jans Logo URI jansLogoURILocalized jsonb None YES None jans Logo URI localized jansPolicyURI text None YES None jans Policy URI jansPolicyURILocalized jsonb None YES None jans Policy URI localized jansPostLogoutRedirectURI jsonb None YES None jans Post Logout Redirect URI jansRedirectURI jsonb None YES None jans Redirect URI jansRegistrationAccessTkn character varying 64 YES None jans Registration Access Tkn jansReqObjSigAlg character varying 64 YES None jans Req Obj Sig Alg jansReqObjEncAlg character varying 64 YES None jans Req Obj Enc Alg jansReqObjEncEnc character varying 64 YES None jans Req Obj Enc Enc jansReqURI jsonb None YES None jans Req URI jansRespTyp jsonb None YES None jans Resp Typ jansScope jsonb None YES None jans Attr Scope jansClaim jsonb None YES None jans Attr Claim jansSectorIdentifierURI text None YES None jans Sector Identifier URI jansSignedRespAlg character varying 64 YES None jans Signed Resp Alg jansSubjectTyp character varying 64 YES None jans Subject Typ jansTknEndpointAuthMethod character varying 64 YES None jans Tkn Endpoint Auth Method jansTknEndpointAuthSigAlg character varying 64 YES None jans Tkn Endpoint Auth Sig Alg jansTosURI text None YES None jans TOS URI jansTosURILocalized jsonb None YES None jans Tos URI localized jansTrustedClnt boolean None YES None jans Trusted Clnt jansUsrInfEncRespAlg character varying 64 YES None jans Usr Inf Enc Resp Alg jansUsrInfEncRespEnc character varying 64 YES None jans Usr Inf Enc Resp Enc jansExtraConf character varying 64 YES None jans additional configuration jansClaimRedirectURI jsonb None YES None Claim Redirect URI jansLastAccessTime timestamp without time zone None YES None Last access time jansLastLogonTime timestamp without time zone None YES None Last logon time jansPersistClntAuthzs boolean None YES None jans Persist Clnt Authzs jansInclClaimsInIdTkn boolean None YES None jans Incl Claims In Id Tkn jansRefreshTknLife integer None YES None Life of refresh token jansDisabled boolean None YES None Status of client jansLogoutURI jsonb None YES None jans Policy URI jansLogoutSessRequired boolean None YES None jans Policy URI jansdId character varying 64 YES None jansd Id jansAuthorizedOrigins jsonb None YES None jans Authorized Origins tknBndCnf text None YES None jansauth - Tkn Binding Id Hash jansAccessTknAsJwt boolean None YES None jansauth - indicator whether to return access token as JWT jansAccessTknSigAlg character varying 64 YES None jansauth - access token signing algorithm jansAccessTknLife integer None YES None Life of access token jansSoftId character varying 64 YES None Soft Identifier jansSoftStatement text None YES None Soft Statement jansRptAsJwt boolean None YES None jansRptAsJwt jansAttrs text None YES None Attrs jansBackchannelTknDeliveryMode character varying 64 YES None jans Backchannel Tkn Delivery Mode jansBackchannelClntNotificationEndpoint character varying 64 YES None jans Backchannel Clnt Notification Endpoint jansBackchannelAuthnReqSigAlg character varying 64 YES None jans Backchannel Authn Req Sig Alg jansBackchannelUsrCodeParameter boolean None YES None jans Backchannel Usr Code Parameter", "title": "jansClnt"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansscope", "text": "Field Type Character Maximum Length Null Default Comment jansDefScope boolean None YES None Track the default scope for an custom OAuth2 Scope. displayName character varying 128 YES None preferred name of a person to be used when displaying entries inum character varying 64 YES None XRI i-number jansScopeTyp character varying 64 YES None OX Attr Scope type creatorId character varying 64 YES None Creator Id creatorTyp character varying 64 YES None Creator type creatorAttrs character varying 64 YES None Creator Attrs creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansClaim jsonb None YES None jans Attr Claim jansScrDn jsonb None YES None Script object DN jansGrpClaims boolean None YES None jans Grp Attr Claims (true or false) jansId character varying 128 YES None Identifier jansIconUrl character varying 64 YES None jans icon url jansUmaPolicyScrDn text None YES None OX policy script Dn jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del", "title": "jansScope"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansumaresource", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries inum character varying 64 YES None XRI i-number jansAssociatedClnt jsonb None YES None Associate the dn of an OAuth2 client with a person or UMA Resource Set. jansUmaScope character varying 768 YES None URI reference of scope descriptor jansFaviconImage character varying 64 YES None TODO - Stores URL of favicon jansGrp character varying 64 YES None Group jansId character varying 128 YES None Identifier jansResource text None YES None Host path jansRevision integer None YES None Revision jansTyp character varying 64 YES None jans type jansScopeExpression text None YES None Scope expression iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del", "title": "jansUmaResource"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansumaresourcepermission", "text": "Field Type Character Maximum Length Null Default Comment exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansUmaScope character varying 768 YES None URI reference of scope descriptor jansConfCode character varying 64 YES None jans configuration code jansResourceSetId character varying 64 YES None jans resource set id jansAttrs text None YES None Attrs jansTicket character varying 64 YES None jans ticket jansStatus character varying 16 YES None Status of the entry, used by many objectclasses", "title": "jansUmaResourcePermission"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansgrant", "text": "Field Type Character Maximum Length Null Default Comment grtId character varying 64 YES None jans grant id iat timestamp without time zone None YES None jans Creation", "title": "jansGrant"}, {"location": "janssen-server/reference/database/pgsql-schema/#janstoken", "text": "Field Type Character Maximum Length Null Default Comment authnTime timestamp without time zone None YES None jans Authn Time authzCode character varying 64 YES None jans authorization code iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknCde character varying 80 YES None jans Tkn Code tknTyp character varying 32 YES None jans Tkn Typ usrId character varying 64 YES None jans user id jansUsrDN character varying 128 YES None jans Usr DN clnId character varying 64 YES None jans Clnt id uuid character varying 64 YES None Unique identifier chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims ssnId character varying 64 YES None jans Sess DN attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash dpop character varying 64 YES None DPoP Proof", "title": "jansToken"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansgrp", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number", "title": "jansGrp"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansattr", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansAttrEditTyp jsonb None YES None Specify in exclude who can update an attribute, admin or user jansAttrName character varying 64 YES None Specify an identifier for an attribute. May be multi-value where an attribute has two names, like givenName and first-name. jansAttrOrigin character varying 64 YES None Specify the person objectclass associated with the attribute, used for display purposes in exclude. jansAttrSystemEditTyp character varying 64 YES None TODO - still required? jansAttrTyp character varying 64 YES None Data type of attribute. Values can be string, photo, numeric, date jansClaimName character varying 64 YES None Used by jans in conjunction with jansttributeName to map claims to attributes in LDAP. jansAttrUsgTyp character varying 64 YES None TODO - Usg? Value can be OpenID jansAttrViewTyp jsonb None YES None Specify in exclude who can view an attribute, admin or user jansSAML1URI character varying 64 YES None SAML 1 uri of attribute jansSAML2URI character varying 64 YES None SAML 2 uri of attribute jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansNameIdTyp character varying 64 YES None NameId Typ jansSourceAttr character varying 64 YES None Source Attr for this Attr jansRegExp character varying 64 YES None Regular expression used to validate attribute data jansTooltip character varying 64 YES None Custom tooltip to be shown on the UI jansValidation text None YES None This data has information about attribute Validation", "title": "jansAttr"}, {"location": "janssen-server/reference/database/pgsql-schema/#janspassresetreq", "text": "Field Type Character Maximum Length Null Default Comment creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansGuid character varying 64 YES None A random string to mark temporary tokens personInum character varying 64 YES None Inum of a person", "title": "jansPassResetReq"}, {"location": "janssen-server/reference/database/pgsql-schema/#janssessid", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier sid character varying 64 YES None Sess Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansLastAccessTime timestamp without time zone None YES None Last access time jansUsrDN character varying 128 YES None jans Usr DN authnTime timestamp without time zone None YES None jans Authn Time jansState character varying 64 YES None jansState jansSessState text None YES None jans Sess State jansPermissionGranted boolean None YES None jans Permission Granted jansAsJwt boolean None YES None Boolean field to indicate whether object is used as JWT jansJwt text None YES None JWT representation of the object or otherwise jwt associated with the object jansPermissionGrantedMap text None YES None jans Permission Granted Map jansInvolvedClnts text None YES None Involved clients deviceSecret character varying 64 YES None deviceSecret jansSessAttr text None YES None jansSessAttr", "title": "jansSessId"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansumarpt", "text": "Field Type Character Maximum Length Null Default Comment authnTime timestamp without time zone None YES None jans Authn Time clnId character varying 64 YES None jans Clnt id iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del tknCde character varying 80 YES None jans Tkn Code usrId character varying 64 YES None jans user id ssnId character varying 64 YES None jans Sess DN jansUmaPermission jsonb None YES None jans uma permission uuid character varying 64 YES None Unique identifier dpop character varying 64 YES None DPoP Proof authzCode character varying 64 YES None jans authorization code grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknTyp character varying 32 YES None jans Tkn Typ jansUsrDN character varying 128 YES None jans Usr DN chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash", "title": "jansUmaRPT"}, {"location": "janssen-server/reference/database/pgsql-schema/#janspushapp", "text": "Field Type Character Maximum Length Null Default Comment displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansId character varying 128 YES None Identifier jansName character varying 64 YES None Name jansPushAppConf character varying 64 YES None jansPush application configuration", "title": "jansPushApp"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansscr", "text": "Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number jansScr text None YES None Attr that contains script (python, java script) jansScrTyp character varying 64 YES None Attr that contains script type (e.g. python, java script)", "title": "jansScr"}, {"location": "janssen-server/reference/database/pgsql-schema/#janscustomscr", "text": "Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansScr text None YES None Attr that contains script (python, java script) jansScrTyp character varying 64 YES None Attr that contains script type (e.g. python, java script) jansProgLng character varying 64 YES None programming language jansModuleProperty jsonb None YES None Module property jansConfProperty jsonb None YES None Conf property jansLevel integer None YES None Level jansRevision integer None YES None Revision jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansScrError text None YES None Attr that contains first error which application get during it execution jansAlias jsonb None YES None jansAlias", "title": "jansCustomScr"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansdeviceregistration", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansDeviceKeyHandle character varying 128 YES None jansDeviceKeyHandle jansDeviceHashCode integer None YES None jansDeviceHashCode jansApp character varying 96 YES None jansApp jansDeviceRegistrationConf text None YES None jansDeviceRegistrationConf jansDeviceNotificationConf character varying 64 YES None Extended push notification configuration jansNickName character varying 64 YES None jansNickName jansDeviceData text None YES None jansDeviceData jansCounter integer None YES None jansCounter jansStatus character varying 16 YES None Status of the entry, used by many objectclasses del boolean None YES None del exp timestamp without time zone None YES None jans Exp personInum character varying 64 YES None Inum of a person creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansLastAccessTime timestamp without time zone None YES None Last access time", "title": "jansDeviceRegistration"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansu2freq", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansReqId character varying 64 YES None jansReqId jansReq text None YES None jansReq jansSessStateId character varying 64 YES None jansSessStateId del boolean None YES None del exp timestamp without time zone None YES None jans Exp personInum character varying 64 YES None Inum of a person creationDate timestamp without time zone None YES None Creation Date used for password reset requests", "title": "jansU2fReq"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansmetric", "text": "Field Type Character Maximum Length Null Default Comment jansStartDate timestamp without time zone None YES None Start date jansEndDate timestamp without time zone None YES None End date jansAppTyp character varying 64 YES None jans App Typ jansMetricTyp character varying 64 YES None Metric type creationDate timestamp without time zone None YES None Creation Date used for password reset requests del boolean None YES None del exp timestamp without time zone None YES None jans Exp jansData text None YES None OX data jansHost character varying 64 YES None jans host", "title": "jansMetric"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansumapct", "text": "Field Type Character Maximum Length Null Default Comment clnId character varying 64 YES None jans Clnt id iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del tknCde character varying 80 YES None jans Tkn Code ssnId character varying 64 YES None jans Sess DN jansClaimValues character varying 64 YES None Claim Values dpop character varying 64 YES None DPoP Proof authnTime timestamp without time zone None YES None jans Authn Time authzCode character varying 64 YES None jans authorization code grtId character varying 64 YES None jans grant id grtTyp character varying 64 YES None jans Grant Typ jwtReq text None YES None jans JWT Req nnc text None YES None jans nonce scp text None YES None jans Attr Scope tknTyp character varying 32 YES None jans Tkn Typ usrId character varying 64 YES None jans user id jansUsrDN character varying 128 YES None jans Usr DN uuid character varying 64 YES None Unique identifier chlng character varying 64 YES None OX PKCE code challenge chlngMth character varying 64 YES None OX PKCE code challenge method clms character varying 64 YES None jans Claims attr text None YES None Attrs tknBndCnf text None YES None jansauth - Tkn Binding Id Hash", "title": "jansUmaPCT"}, {"location": "janssen-server/reference/database/pgsql-schema/#janscache", "text": "Field Type Character Maximum Length Null Default Comment uuid character varying 64 YES None Unique identifier iat timestamp without time zone None YES None jans Creation exp timestamp without time zone None YES None jans Exp del boolean None YES None del dat text None YES None OX data", "title": "jansCache"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansfido2registrationentry", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests displayName character varying 128 YES None preferred name of a person to be used when displaying entries jansApp character varying 96 YES None jansApp jansSessStateId character varying 64 YES None jansSessStateId jansCodeChallenge character varying 64 YES None OX PKCE code challenge jansCodeChallengeHash integer None YES None OX code challenge hash jansPublicKeyId character varying 96 YES None jansPublicKeyId jansPublicKeyIdHash integer None YES None jansPublicKeyIdHash personInum character varying 64 YES None Inum of a person jansRegistrationData text None YES None jansRegistrationData jansDeviceData text None YES None jansDeviceData jansDeviceNotificationConf character varying 64 YES None Extended push notification configuration jansCounter integer None YES None jansCounter jansStatus character varying 16 YES None Status of the entry, used by many objectclasses exp timestamp without time zone None YES None jans Exp del boolean None YES None del", "title": "jansFido2RegistrationEntry"}, {"location": "janssen-server/reference/database/pgsql-schema/#janspushdevice", "text": "Field Type Character Maximum Length Null Default Comment jansUsrId character varying 64 YES None jans user id jansId character varying 128 YES None Identifier jansPushApp text None YES None jansPush application DN jansPushDeviceConf character varying 64 YES None jansPush device configuration jansTyp character varying 64 YES None jans type", "title": "jansPushDevice"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansclntauthz", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansClntId jsonb None YES None jans Clnt id jansUsrId character varying 64 YES None jans user id exp timestamp without time zone None YES None jans Exp del boolean None YES None del jansScope jsonb None YES None jans Attr Scope", "title": "jansClntAuthz"}, {"location": "janssen-server/reference/database/pgsql-schema/#janssectoridentifier", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansRedirectURI jsonb None YES None jans Redirect URI jansClntId jsonb None YES None jans Clnt id", "title": "jansSectorIdentifier"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansfido2authnentry", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansApp character varying 96 YES None jansApp jansSessStateId character varying 64 YES None jansSessStateId jansCodeChallenge character varying 64 YES None OX PKCE code challenge jansCodeChallengeHash integer None YES None OX code challenge hash personInum character varying 64 YES None Inum of a person jansAuthData text None YES None jansAuthData jansStatus character varying 16 YES None Status of the entry, used by many objectclasses exp timestamp without time zone None YES None jans Exp del boolean None YES None del", "title": "jansFido2AuthnEntry"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansrp", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier dat text None YES None OX data", "title": "jansRp"}, {"location": "janssen-server/reference/database/pgsql-schema/#janscibareq", "text": "Field Type Character Maximum Length Null Default Comment authReqId character varying 64 YES None Authn request id clnId character varying 64 YES None jans Clnt id usrId character varying 64 YES None jans user id creationDate timestamp without time zone None YES None Creation Date used for password reset requests exp timestamp without time zone None YES None jans Exp jansStatus character varying 16 YES None Status of the entry, used by many objectclasses", "title": "jansCibaReq"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansstatentry", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier dat text None YES None OX data jansData text None YES None OX data attr text None YES None Attrs", "title": "jansStatEntry"}, {"location": "janssen-server/reference/database/pgsql-schema/#janspar", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansAttrs text None YES None Attrs exp timestamp without time zone None YES None jans Exp del boolean None YES None del", "title": "jansPar"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansinummap", "text": "Field Type Character Maximum Length Null Default Comment jansStatus character varying 16 YES None Status of the entry, used by many objectclasses inum character varying 64 YES None XRI i-number jansPrimaryKeyAttrName character varying 64 YES None Primary Key Attribute Name jansPrimaryKeyValue character varying 64 YES None Primary Key Value jansSecondaryKeyAttrName character varying 64 YES None Secondary Key Attribute Name jansSecondaryKeyValue character varying 64 YES None Secondary Key Value jansTertiaryKeyAttrName character varying 64 YES None Tertiary Key Attribute Name jansTertiaryKeyValue character varying 64 YES None Tertiary Key Value", "title": "jansInumMap"}, {"location": "janssen-server/reference/database/pgsql-schema/#agmflowrun", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier agFlowSt text None YES None Details of a running agama flow instance agFlowEncCont text None YES None Continuation associated to a running agama flow instance jansCustomMessage character varying 128 YES None exclude custom welcome message exp timestamp without time zone None YES None jans Exp", "title": "agmFlowRun"}, {"location": "janssen-server/reference/database/pgsql-schema/#agmflow", "text": "Field Type Character Maximum Length Null Default Comment agFlowQname character varying 64 YES None Full name of an agama flow agFlowMeta text None YES None Metadata of an agama flow jansScr text None YES None Attr that contains script (python, java script) jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansScrError text None YES None Attr that contains first error which application get during it execution agFlowTrans text None YES None Transpiled code of an agama flow jansRevision integer None YES None Revision jansCustomMessage character varying 128 YES None exclude custom welcome message", "title": "agmFlow"}, {"location": "janssen-server/reference/database/pgsql-schema/#adsprjdeployment", "text": "Field Type Character Maximum Length Null Default Comment jansId character varying 128 YES None Identifier jansStartDate timestamp without time zone None YES None Start date jansEndDate timestamp without time zone None YES None End date adsPrjAssets text None YES None Assets of an ADS project adsPrjDeplDetails text None YES None Misc details associated to an ADS project", "title": "adsPrjDeployment"}, {"location": "janssen-server/reference/database/pgsql-schema/#jansdocument", "text": "Field Type Character Maximum Length Null Default Comment inum character varying 64 YES None XRI i-number displayName character varying 128 YES None preferred name of a person to be used when displaying entries document character varying 64 YES None Save Document in DB creationDate timestamp without time zone None YES None Creation Date used for password reset requests jansModuleProperty jsonb None YES None Module property jansLevel integer None YES None Level jansRevision integer None YES None Revision jansEnabled boolean None YES None Status of the entry, used by many objectclasses jansAlias jsonb None YES None jansAlias", "title": "jansDocument"}, {"location": "janssen-server/reference/database/rdbms-erwin/", "tags": ["administration", "reference", "database"], "text": "Generic tables structure #", "title": "RDBMS Erwin Table"}, {"location": "janssen-server/reference/database/rdbms-erwin/#generic-tables-structure", "text": "", "title": "Generic tables structure"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/", "tags": ["administration", "reference", "json", "feature-flags"], "text": "Janssen Auth Server Feature Flags # Feature Flag Name Description ACTIVE_SESSION Enable/Disable active session endpoint Details CIBA Enable/Disable OpenID Connect Client Initiated Backchannel Authentication Flow(CIBA) flow support Details CLIENTINFO Enable/Disable client info endpoint Details DEVICE_AUTHZ Enable/Disable support for device authorization Details END_SESSION Enable/Disable end session endpoint Details HEALTH_CHECK Enable/Disable health-check endpoint Details ID_GENERATION Enable/Disable ID Generation endpoint Details INTROSPECTION Enable/Disable token introspection endpoint Details JANS_CONFIGURATION Enable/Disable .well-known configuration endpoint Details METRIC Enable/Disable metric reporter feature Details PAR Enable/Disable Pushed Authorization Requests(PAR) feature Details REGISTRATION Enable/Disable client registration endpoint Details REVOKE_SESSION Enable/Disable session revocation endpoint Details REVOKE_TOKEN Enable/Disable token revocation endpoint Details SSA Enable/Disable Software Statement Assertion(SSA) feature Details STAT Enable/Disable Stat service Details STATUS_SESSION Enable/Disable session status check endpoint Details U2F Enable/Disable support for Universal 2nd Factor(U2F) protocol Details UMA Enable/Disable support for User-Managed Access (UMA) Details USERINFO Enable/Disable OpenID Connect userinfo endpoint Details ACTIVE_SESSION # Description: Enable/Disable active session endpoint Required: No Default value: None CIBA # Description: Enable/Disable OpenID Connect Client Initiated Backchannel Authentication Flow(CIBA) flow support Required: No Default value: None CLIENTINFO # Description: Enable/Disable client info endpoint Required: No Default value: None DEVICE_AUTHZ # Description: Enable/Disable support for device authorization Required: No Default value: None END_SESSION # Description: Enable/Disable end session endpoint Required: No Default value: None HEALTH_CHECK # Description: Enable/Disable health-check endpoint Required: No Default value: None ID_GENERATION # Description: Enable/Disable ID Generation endpoint Required: No Default value: None INTROSPECTION # Description: Enable/Disable token introspection endpoint Required: No Default value: None JANS_CONFIGURATION # Description: Enable/Disable .well-known configuration endpoint Required: No Default value: None METRIC # Description: Enable/Disable metric reporter feature Required: No Default value: None PAR # Description: Enable/Disable Pushed Authorization Requests(PAR) feature Required: No Default value: None REGISTRATION # Description: Enable/Disable client registration endpoint Required: No Default value: None REVOKE_SESSION # Description: Enable/Disable session revocation endpoint Required: No Default value: None REVOKE_TOKEN # Description: Enable/Disable token revocation endpoint Required: No Default value: None SSA # Description: Enable/Disable Software Statement Assertion(SSA) feature Required: No Default value: None STAT # Description: Enable/Disable Stat service Required: No Default value: None STATUS_SESSION # Description: Enable/Disable session status check endpoint Required: No Default value: None U2F # Description: Enable/Disable support for Universal 2nd Factor(U2F) protocol Required: No Default value: None UMA # Description: Enable/Disable support for User-Managed Access (UMA) Required: No Default value: None USERINFO # Description: Enable/Disable OpenID Connect userinfo endpoint Required: No Default value: None", "title": "Auth Server"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#janssen-auth-server-feature-flags", "text": "Feature Flag Name Description ACTIVE_SESSION Enable/Disable active session endpoint Details CIBA Enable/Disable OpenID Connect Client Initiated Backchannel Authentication Flow(CIBA) flow support Details CLIENTINFO Enable/Disable client info endpoint Details DEVICE_AUTHZ Enable/Disable support for device authorization Details END_SESSION Enable/Disable end session endpoint Details HEALTH_CHECK Enable/Disable health-check endpoint Details ID_GENERATION Enable/Disable ID Generation endpoint Details INTROSPECTION Enable/Disable token introspection endpoint Details JANS_CONFIGURATION Enable/Disable .well-known configuration endpoint Details METRIC Enable/Disable metric reporter feature Details PAR Enable/Disable Pushed Authorization Requests(PAR) feature Details REGISTRATION Enable/Disable client registration endpoint Details REVOKE_SESSION Enable/Disable session revocation endpoint Details REVOKE_TOKEN Enable/Disable token revocation endpoint Details SSA Enable/Disable Software Statement Assertion(SSA) feature Details STAT Enable/Disable Stat service Details STATUS_SESSION Enable/Disable session status check endpoint Details U2F Enable/Disable support for Universal 2nd Factor(U2F) protocol Details UMA Enable/Disable support for User-Managed Access (UMA) Details USERINFO Enable/Disable OpenID Connect userinfo endpoint Details", "title": "Janssen Auth Server Feature Flags"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#active_session", "text": "Description: Enable/Disable active session endpoint Required: No Default value: None", "title": "ACTIVE_SESSION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#ciba", "text": "Description: Enable/Disable OpenID Connect Client Initiated Backchannel Authentication Flow(CIBA) flow support Required: No Default value: None", "title": "CIBA"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#clientinfo", "text": "Description: Enable/Disable client info endpoint Required: No Default value: None", "title": "CLIENTINFO"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#device_authz", "text": "Description: Enable/Disable support for device authorization Required: No Default value: None", "title": "DEVICE_AUTHZ"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#end_session", "text": "Description: Enable/Disable end session endpoint Required: No Default value: None", "title": "END_SESSION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#health_check", "text": "Description: Enable/Disable health-check endpoint Required: No Default value: None", "title": "HEALTH_CHECK"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#id_generation", "text": "Description: Enable/Disable ID Generation endpoint Required: No Default value: None", "title": "ID_GENERATION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#introspection", "text": "Description: Enable/Disable token introspection endpoint Required: No Default value: None", "title": "INTROSPECTION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#jans_configuration", "text": "Description: Enable/Disable .well-known configuration endpoint Required: No Default value: None", "title": "JANS_CONFIGURATION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#metric", "text": "Description: Enable/Disable metric reporter feature Required: No Default value: None", "title": "METRIC"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#par", "text": "Description: Enable/Disable Pushed Authorization Requests(PAR) feature Required: No Default value: None", "title": "PAR"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#registration", "text": "Description: Enable/Disable client registration endpoint Required: No Default value: None", "title": "REGISTRATION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#revoke_session", "text": "Description: Enable/Disable session revocation endpoint Required: No Default value: None", "title": "REVOKE_SESSION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#revoke_token", "text": "Description: Enable/Disable token revocation endpoint Required: No Default value: None", "title": "REVOKE_TOKEN"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#ssa", "text": "Description: Enable/Disable Software Statement Assertion(SSA) feature Required: No Default value: None", "title": "SSA"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#stat", "text": "Description: Enable/Disable Stat service Required: No Default value: None", "title": "STAT"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#status_session", "text": "Description: Enable/Disable session status check endpoint Required: No Default value: None", "title": "STATUS_SESSION"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#u2f", "text": "Description: Enable/Disable support for Universal 2nd Factor(U2F) protocol Required: No Default value: None", "title": "U2F"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#uma", "text": "Description: Enable/Disable support for User-Managed Access (UMA) Required: No Default value: None", "title": "UMA"}, {"location": "janssen-server/reference/json/feature-flags/janssenauthserver-feature-flags/#userinfo", "text": "Description: Enable/Disable OpenID Connect userinfo endpoint Required: No Default value: None", "title": "USERINFO"}, {"location": "janssen-server/reference/json/properties/config-api-properties/", "text": "Overview # Please use the left navigation menu to browse the content of this section while we are still working on developing content for Overview page. Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "Config API"}, {"location": "janssen-server/reference/json/properties/config-api-properties/#overview", "text": "Please use the left navigation menu to browse the content of this section while we are still working on developing content for Overview page. Contribute If you\u2019d like to contribute to this document, get started with the Contribution Guide", "title": "Overview"}, {"location": "janssen-server/reference/json/properties/fido2-properties/", "tags": ["administration", "reference", "json", "properties"], "text": "Fido2 Configuration Properties # Property Name Description authenticationHistoryExpiration Expiration time in seconds for approved authentication requests Details authenticatorCertsFolder Authenticators certificates folder Details baseEndpoint The base URL for Fido2 endpoints Details checkU2fAttestations Boolean value indicating if U2f attestation needs to be checked Details cleanServiceBatchChunkSize Each clean up iteration fetches chunk of expired data per base dn and removes it from storage Details cleanServiceInterval Time interval for the Clean Service in seconds Details disableJdkLogger Boolean value specifying whether to enable JDK Loggers Details externalLoggerConfiguration Path to external Fido2 logging configuration Details issuer URL using the https scheme for Issuer identifier Details loggingLayout Logging layout used for Fido2 Details loggingLevel Logging level for Fido2 logger Details mdsAccessToken MDS access token Details mdsCertsFolder MDS TOC root certificates folder Details mdsTocsFolder MDS TOC files folder Details metadataUrlsProvider String value to provide source of URLs with external metadata Details metricReporterEnabled Boolean value specifying whether metric reporter is enabled Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep report data Details personCustomObjectClassList Custom object class list for dynamic person enrolment Details enabledFidoAlgorithms List of Requested Credential Types Details rp Requested Parties Authenticators metadata in json format Details serverMetadataFolder Authenticators metadata in json format Details sessionIdPersistInCache Boolean value specifying whether to persist session_id in cache Details unfinishedRequestExpiration Expiration time in seconds for pending enrollment/authentication requests Details useLocalCache Boolean value to indicate if Local Cache is to be used Details debugUserAutoEnrollment Allow to enroll users on enrollment/authentication requests Details authenticationHistoryExpiration # Description: Expiration time in seconds for approved authentication requests Required: No Default value: None authenticatorCertsFolder # Description: Authenticators certificates folder Required: No Default value: None baseEndpoint # Description: The base URL for Fido2 endpoints Required: No Default value: None checkU2fAttestations # Description: Boolean value indicating if U2f attestation needs to be checked Required: No Default value: None cleanServiceBatchChunkSize # Description: Each clean up iteration fetches chunk of expired data per base dn and removes it from storage Required: No Default value: None cleanServiceInterval # Description: Time interval for the Clean Service in seconds Required: No Default value: None disableJdkLogger # Description: Boolean value specifying whether to enable JDK Loggers Required: No Default value: None externalLoggerConfiguration # Description: Path to external Fido2 logging configuration Required: No Default value: None issuer # Description: URL using the https scheme for Issuer identifier Required: No Default value: None loggingLayout # Description: Logging layout used for Fido2 Required: No Default value: None loggingLevel # Description: Logging level for Fido2 logger Required: No Default value: None mdsAccessToken # Description: MDS access token Required: No Default value: None mdsCertsFolder # Description: MDS TOC root certificates folder Required: No Default value: None mdsTocsFolder # Description: MDS TOC files folder Required: No Default value: None metadataUrlsProvider # Description: String value to provide source of URLs with external metadata Required: No Default value: None metricReporterEnabled # Description: Boolean value specifying whether metric reporter is enabled Required: No Default value: None metricReporterInterval # Description: The interval for metric reporter in seconds Required: No Default value: None metricReporterKeepDataDays # Description: The days to keep report data Required: No Default value: None personCustomObjectClassList # Description: Custom object class list for dynamic person enrolment Required: No Default value: None enabledFidoAlgorithms # Description: List of Requested Credential Types Required: No Default value: None rp # Description: Requested Parties Authenticators metadata in json format Required: No Default value: None serverMetadataFolder # Description: Authenticators metadata in json format Required: No Default value: None sessionIdPersistInCache # Description: Boolean value specifying whether to persist session_id in cache Required: No Default value: false unfinishedRequestExpiration # Description: Expiration time in seconds for pending enrollment/authentication requests Required: No Default value: None useLocalCache # Description: Boolean value to indicate if Local Cache is to be used Required: No Default value: None debugUserAutoEnrollment # Description: Allow to enroll users on enrollment/authentication requests Required: No Default value: None", "title": "FIDO"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#fido2-configuration-properties", "text": "Property Name Description authenticationHistoryExpiration Expiration time in seconds for approved authentication requests Details authenticatorCertsFolder Authenticators certificates folder Details baseEndpoint The base URL for Fido2 endpoints Details checkU2fAttestations Boolean value indicating if U2f attestation needs to be checked Details cleanServiceBatchChunkSize Each clean up iteration fetches chunk of expired data per base dn and removes it from storage Details cleanServiceInterval Time interval for the Clean Service in seconds Details disableJdkLogger Boolean value specifying whether to enable JDK Loggers Details externalLoggerConfiguration Path to external Fido2 logging configuration Details issuer URL using the https scheme for Issuer identifier Details loggingLayout Logging layout used for Fido2 Details loggingLevel Logging level for Fido2 logger Details mdsAccessToken MDS access token Details mdsCertsFolder MDS TOC root certificates folder Details mdsTocsFolder MDS TOC files folder Details metadataUrlsProvider String value to provide source of URLs with external metadata Details metricReporterEnabled Boolean value specifying whether metric reporter is enabled Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep report data Details personCustomObjectClassList Custom object class list for dynamic person enrolment Details enabledFidoAlgorithms List of Requested Credential Types Details rp Requested Parties Authenticators metadata in json format Details serverMetadataFolder Authenticators metadata in json format Details sessionIdPersistInCache Boolean value specifying whether to persist session_id in cache Details unfinishedRequestExpiration Expiration time in seconds for pending enrollment/authentication requests Details useLocalCache Boolean value to indicate if Local Cache is to be used Details debugUserAutoEnrollment Allow to enroll users on enrollment/authentication requests Details", "title": "Fido2 Configuration Properties"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#authenticationhistoryexpiration", "text": "Description: Expiration time in seconds for approved authentication requests Required: No Default value: None", "title": "authenticationHistoryExpiration"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#authenticatorcertsfolder", "text": "Description: Authenticators certificates folder Required: No Default value: None", "title": "authenticatorCertsFolder"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#baseendpoint", "text": "Description: The base URL for Fido2 endpoints Required: No Default value: None", "title": "baseEndpoint"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#checku2fattestations", "text": "Description: Boolean value indicating if U2f attestation needs to be checked Required: No Default value: None", "title": "checkU2fAttestations"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#cleanservicebatchchunksize", "text": "Description: Each clean up iteration fetches chunk of expired data per base dn and removes it from storage Required: No Default value: None", "title": "cleanServiceBatchChunkSize"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#cleanserviceinterval", "text": "Description: Time interval for the Clean Service in seconds Required: No Default value: None", "title": "cleanServiceInterval"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#disablejdklogger", "text": "Description: Boolean value specifying whether to enable JDK Loggers Required: No Default value: None", "title": "disableJdkLogger"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#externalloggerconfiguration", "text": "Description: Path to external Fido2 logging configuration Required: No Default value: None", "title": "externalLoggerConfiguration"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#issuer", "text": "Description: URL using the https scheme for Issuer identifier Required: No Default value: None", "title": "issuer"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#logginglayout", "text": "Description: Logging layout used for Fido2 Required: No Default value: None", "title": "loggingLayout"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#logginglevel", "text": "Description: Logging level for Fido2 logger Required: No Default value: None", "title": "loggingLevel"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#mdsaccesstoken", "text": "Description: MDS access token Required: No Default value: None", "title": "mdsAccessToken"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#mdscertsfolder", "text": "Description: MDS TOC root certificates folder Required: No Default value: None", "title": "mdsCertsFolder"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#mdstocsfolder", "text": "Description: MDS TOC files folder Required: No Default value: None", "title": "mdsTocsFolder"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#metadataurlsprovider", "text": "Description: String value to provide source of URLs with external metadata Required: No Default value: None", "title": "metadataUrlsProvider"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#metricreporterenabled", "text": "Description: Boolean value specifying whether metric reporter is enabled Required: No Default value: None", "title": "metricReporterEnabled"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#metricreporterinterval", "text": "Description: The interval for metric reporter in seconds Required: No Default value: None", "title": "metricReporterInterval"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#metricreporterkeepdatadays", "text": "Description: The days to keep report data Required: No Default value: None", "title": "metricReporterKeepDataDays"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#personcustomobjectclasslist", "text": "Description: Custom object class list for dynamic person enrolment Required: No Default value: None", "title": "personCustomObjectClassList"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#enabledfidoalgorithms", "text": "Description: List of Requested Credential Types Required: No Default value: None", "title": "enabledFidoAlgorithms"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#rp", "text": "Description: Requested Parties Authenticators metadata in json format Required: No Default value: None", "title": "rp"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#servermetadatafolder", "text": "Description: Authenticators metadata in json format Required: No Default value: None", "title": "serverMetadataFolder"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#sessionidpersistincache", "text": "Description: Boolean value specifying whether to persist session_id in cache Required: No Default value: false", "title": "sessionIdPersistInCache"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#unfinishedrequestexpiration", "text": "Description: Expiration time in seconds for pending enrollment/authentication requests Required: No Default value: None", "title": "unfinishedRequestExpiration"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#uselocalcache", "text": "Description: Boolean value to indicate if Local Cache is to be used Required: No Default value: None", "title": "useLocalCache"}, {"location": "janssen-server/reference/json/properties/fido2-properties/#debuguserautoenrollment", "text": "Description: Allow to enroll users on enrollment/authentication requests Required: No Default value: None", "title": "debugUserAutoEnrollment"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/", "tags": ["administration", "reference", "json", "properties"], "text": "Janssen Auth Server Configuration Properties # Property Name Description accessTokenLifetime The lifetime of the short lived Access Token Details accessTokenSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for the access token to encode the Claims in a JWT Details activeSessionAuthorizationScope Authorization Scope for active session Details agamaConfiguration Engine Config which offers an alternative way to build authentication flows in Janssen server Details allowAllValueForRevokeEndpoint Boolean value true allow all value for revoke endpoint Details allowBlankValuesInDiscoveryResponse Boolean value specifying whether to allow blank values in discovery response Details allowEndSessionWithUnmatchedSid default value false. If true, sid check will be skipped Details allowIdTokenWithoutImplicitGrantType Specifies if a token without implicit grant types is allowed Details allowPostLogoutRedirectWithoutValidation Allows post-logout redirect without validation for the End Session endpoint (still AS validates it against clientWhiteList url pattern property) Details allowSpontaneousScopes Specifies whether to allow spontaneous scopes Details authenticationFilters This list details filters for user authentication Details authenticationFiltersEnabled Boolean value specifying whether to enable user authentication filters Details authenticationProtectionConfiguration Authentication Brute Force Protection Configuration Details authorizationCodeLifetime The lifetime of the Authorization Code Details authorizationEncryptionAlgValuesSupported List of authorization encryption algorithms supported by this OP Details authorizationEncryptionEncValuesSupported A list of the authorization encryption algorithms supported Details authorizationEndpoint The authorization endpoint URL Details authorizationRequestCustomAllowedParameters This list details the allowed custom parameters for authorization requests Details authorizationSigningAlgValuesSupported List of authorization signing algorithms supported by this OP Details backchannelAuthenticationEndpoint Backchannel Authentication Endpoint Details backchannelAuthenticationRequestSigningAlgValuesSupported Backchannel Authentication Request Signing Alg Values Supported Details backchannelAuthenticationResponseExpiresIn Backchannel Authentication Response Expires In Details backchannelAuthenticationResponseInterval Backchannel Authentication Response Interval Details backchannelBindingMessagePattern Backchannel Binding Message Pattern Details backchannelClientId Backchannel Client Id Details backchannelDeviceRegistrationEndpoint Backchannel Device Registration Endpoint Details backchannelLoginHintClaims Backchannel Login Hint Claims Details backchannelRedirectUri Backchannel Redirect Uri Details backchannelRequestsProcessorJobChunkSize Each backchannel request processor iteration fetches chunk of data to be processed Details backchannelRequestsProcessorJobIntervalSec Specifies the allowable elapsed time in seconds backchannel request processor executes Details backchannelTokenDeliveryModesSupported Backchannel Token Delivery Modes Supported Details backchannelUserCodeParameterSupported Backchannel User Code Parameter Supported Details baseEndpoint The base URL for endpoints Details blockWebviewAuthorizationEnabled Enable/Disable block authorizations that originate from Webview (Mobile apps). Details changeSessionIdOnAuthentication Boolean value specifying whether change session_id on authentication. Default value is true Details checkSessionIFrame URL for an OP IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Details checkUserPresenceOnRefreshToken Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check. Details cibaEndUserNotificationConfig CIBA End User Notification Config Details cibaGrantLifeExtraTimeSec Specifies the CIBA Grant life extra time in seconds Details cibaMaxExpirationTimeAllowedSec Specifies the CIBA token expiration time in seconds Details claimsLocalesSupported This list details the languages and scripts supported for values in the claims being returned Details claimsParameterSupported Specifies whether the OP supports use of the claims parameter Details claimTypesSupported A list of the Claim Types that the OpenID Provider supports Details cleanServiceBatchChunkSize Clean service chunk size which is used during clean up Details cleanServiceInterval Time interval for the Clean Service in seconds Details clientAuthenticationFilters This list details filters for client authentication Details clientAuthenticationFiltersEnabled Boolean value specifying whether to enable client authentication filters Details clientBlackList This list specified which client redirection URIs are black-listed Details clientInfoEndpoint The Client Info endpoint URL Details clientRegDefaultToCodeFlowWithRefresh Boolean value specifying whether to add Authorization Code Flow with Refresh grant during client registratio Details clientWhiteList This list specifies which client redirection URIs are white-listed Details configurationUpdateInterval The interval for configuration update in seconds Details consentGatheringScriptBackwardCompatibility Boolean value specifying whether to turn on Consent Gathering Script backward compatibility mode. If true AS will pick up script with higher level globally. If false (default) AS will pick up script based on client configuration Details cookieDomain Sets cookie domain for all cookies created by OP Details corsConfigurationFilters This list specifies the CORS configuration filters Details cssLocation The location for CSS files Details customHeadersWithAuthorizationResponse Choose whether to enable the custom response header parameter to return custom headers with the authorization response Details dateFormatterPatterns List of key value date formatters, e.g. 'userinfo: 'yyyy-MM-dd', etc. Details dcrAuthorizationWithClientCredentials Boolean value indicating if DCR authorization to be performed using client credentials Details dcrAuthorizationWithMTLS Boolean value indicating if DCR authorization allowed with MTLS Details dcrForbidExpirationTimeInRequest Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration. Details dcrSignatureValidationEnabled Boolean value enables DCR signature validation. Default is false Details dcrSignatureValidationJwks Specifies JWKS for all DCR's validations Details dcrSignatureValidationJwksUri Specifies JWKS URI for all DCR's validations Details dcrSignatureValidationSharedSecret Specifies shared secret for Dynamic Client Registration Details dcrSignatureValidationSoftwareStatementJwksClaim Specifies claim name inside software statement. Value of claim should point to inlined JWKS Details dcrSignatureValidationSoftwareStatementJwksURIClaim Specifies claim name inside software statement. Value of claim should point to JWKS URI Details dcrSsaValidationConfigs DCR SSA Validation configurations used to perform validation of SSA or DCR Details defaultSignatureAlgorithm The default signature algorithm to sign ID Tokens Details defaultSubjectType The default subject type used for dynamic client registration Details deviceAuthzAcr Device authz acr Details deviceAuthzEndpoint URL for the Device Authorization Details deviceAuthzRequestExpiresIn Expiration time given for device authorization requests Details deviceAuthzResponseTypeToProcessAuthz Response type used to process device authz requests Details deviceAuthzTokenPollInterval Default interval returned to the client to process device token requests Details disableAuthnForMaxAgeZero Boolean value specifying whether to disable authentication when max_age=0 Details disableJdkLogger Choose whether to disable JDK loggers Details disablePromptConsent Boolean value specifying whether to disable prompt=consent Details disablePromptLogin Boolean value specifying whether to disable prompt=login Details disableU2fEndpoint Choose whether to disable U2F endpoints Details discoveryAllowedKeys List of configuration response claim allowed to be displayed in discovery endpoint Details discoveryCacheLifetimeInMinutes Lifetime of discovery cache Details discoveryDenyKeys List of configuration response claims which must not be displayed in discovery endpoint response Details displayValuesSupported A list of the display parameter values that the OpenID Provider supports Details dnName DN of certificate issuer Details dpopJtiCacheTime Demonstration of Proof-of-Possession (DPoP) cache time Details dpopNonceCacheTime Demonstration of Proof-of-Possession (DPoP) nonce cache time Details dpopSigningAlgValuesSupported Demonstration of Proof-of-Possession (DPoP) authorization signing algorithms supported Details dpopTimeframe Demonstration of Proof-of-Possession (DPoP) timeout Details dpopUseNonce Demonstration of Proof-of-Possession (DPoP) use nonce Details grantTypesSupportedByDynamicRegistration This list details which OAuth 2.0 grant types can be set up with the client registration API Details dynamicRegistrationAllowedPasswordGrantScopes List of grant scopes for dynamic registration Details dynamicRegistrationCustomAttributes This list details the custom attributes allowed for dynamic registration Details dynamicRegistrationCustomObjectClass LDAP custom object class for dynamic registration Details dynamicRegistrationDefaultCustomAttributes This map provides default custom attributes with values for dynamic registration Details dynamicRegistrationExpirationTime Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire Details dynamicRegistrationPasswordGrantTypeEnabled Boolean value specifying whether to enable Password Grant Type during Dynamic Registration Details dynamicRegistrationPersistClientAuthorizations Boolean value specifying whether to persist client authorizations Details dynamicRegistrationScopesParamEnabled Boolean value specifying whether to enable scopes parameter in dynamic registration Details enableClientGrantTypeUpdate Choose if client can update Grant Type values Details enabledOAuthAuditLogging enable OAuth Audit Logging Details endSessionEndpoint URL at the OP to which an RP can perform a redirect to request that the end user be logged out at the OP Details endSessionWithAccessToken Choose whether to accept access tokens to call end_session endpoint Details errorHandlingMethod A list of possible error handling methods. Possible values: remote (send error back to RP), internal (show error page) Details errorReasonEnabled Boolean value specifying whether to return detailed reason of the error from AS. Default value is false Details expirationNotificatorEnabled Boolean value specifying whether expiration notificator is enabled (used to identify expiration for persistence that support TTL, like Couchbase) Details expirationNotificatorIntervalInSeconds The expiration notificator interval in second Details expirationNotificatorMapSizeLimit The expiration notificator maximum size limit Details externalLoggerConfiguration The path to the external log4j2 logging configuration Details externalUriWhiteList This list specifies which external URIs can be called by AS (if empty any URI can be called) Details fapiCompatibility Boolean value specifying whether to turn on FAPI compatibility mode. If true AS behaves in more strict mode Details featureFlags List of enabled feature flags Details forceIdTokenHintPresence Boolean value specifying whether force id_token_hint parameter presence Details forceOfflineAccessScopeToEnableRefreshToken Boolean value specifying whether force offline_access scope to enable refresh_token grant type. Default value is true Details forceSignedRequestObject Boolean value true indicates that signed request object is mandatory Details frontChannelLogoutSessionSupported Choose whether to support front channel session logout Details grantTypesAndResponseTypesAutofixEnabled Boolean value specifying whether to Grant types and Response types can be auto fixed Details grantTypesSupported This list details which OAuth 2.0 grant types are supported by this OP Details httpLoggingEnabled Enable/disable request/response logging filter Details httpLoggingExcludePaths This list details the base URIs for which the request/response logging filter will not record activity Details httpLoggingResponseBodyContent Defines if Response body will be logged. Default value is false Details idGenerationEndpoint ID Generation endpoint URL Details idTokenEncryptionAlgValuesSupported A list of the JWE encryption algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenEncryptionEncValuesSupported A list of the JWE encryption algorithms (enc values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenFilterClaimsBasedOnAccessToken Boolean value specifying whether idToken filters claims based on accessToken Details idTokenLifetime The lifetime of the ID Token Details idTokenSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenTokenBindingCnfValuesSupported Array containing a list of the JWT Confirmation Method member names supported by the OP for Token Binding of ID Tokens. The presence of this parameter indicates that the OpenID Provider supports Token Binding of ID Tokens. If omitted, the default is that the OpenID Provider does not support Token Binding of ID Tokens Details imgLocation The location for image files Details includeSidInResponse Boolean value specifying whether to include sessionId in response Details introspectionAccessTokenMustHaveIntrospectionScope If True, rejects introspection requests if access_token does not have the 'introspection' scope in its authorization header. Comparing to 'uma_protection', 'introspection' scope is not allowed for dynamic registration' Details introspectionAccessTokenMustHaveUmaProtectionScope If True, rejects introspection requests if access_token does not have the uma_protection scope in its authorization header Details introspectionEndpoint Introspection endpoint URL Details introspectionResponseScopesBackwardCompatibility Boolean value specifying introspection response backward compatibility mode Details introspectionScriptBackwardCompatibility Boolean value specifying whether switch off client's introspection scripts (true value) and run all scripts that exists on server. Default value is false Details introspectionSkipAuthorization Specifies if authorization to be skipped for introspection Details invalidateSessionCookiesAfterAuthorizationFlow Boolean value to specify whether to invalidate session_id and consent_session_id cookies right after successful or unsuccessful authorization Details issuer URL using the https scheme that OP asserts as Issuer identifier Details jansId URL for the Inum generator Service Details jansOpenIdConnectVersion OpenID Connect Version Details jmsBrokerURISet JMS Broker URI Set Details jmsPassword JMS Password Details jmsUserName JMS UserName Details jsLocation The location for JavaScript files Details jwksAlgorithmsSupported A list of algorithms that will be used in JWKS endpoint Details jwksUri URL of the OP's JSON Web Key Set (JWK) document. This contains the signing key(s) the RP uses to validate signatures from the OP Details keepAuthenticatorAttributesOnAcrChange Boolean value specifying whether to keep authenticator attributes on ACR change Details keyAlgsAllowedForGeneration List of algorithm allowed to be used for key generation Details keyRegenerationEnabled Boolean value specifying whether to regenerate keys Details keyRegenerationInterval The interval for key regeneration in hours Details keySelectionStrategy Key Selection Strategy : OLDER, NEWER, FIRST Details keySignWithSameKeyButDiffAlg Specifies if signing to be done with same key but apply different algorithms Details keyStoreFile The Key Store File (JKS) Details keyStoreSecret The Key Store password Details legacyIdTokenClaims Choose whether to include claims in ID tokens Details logClientIdOnClientAuthentication Choose if application should log the Client ID on client authentication Details logClientNameOnClientAuthentication Choose if application should log the Client Name on client authentication Details loggingLayout Logging layout used for Jans Authorization Server loggers Details loggingLevel Specify the logging level of loggers Details logNotFoundEntityAsError Boolean value specifying whether to log not_found entity exception as error or as trace. Default value is false (trace). Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep metric reported data Details mtlsAuthorizationEndpoint URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Endpoint Details mtlsCheckSessionIFrame URL for Mutual TLS (mTLS) IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Details mtlsClientInfoEndpoint URL for Mutual TLS (mTLS) Client Info endpoint Details mtlsDeviceAuthzEndpoint Mutual TLS (mTLS) device authorization endpoint URL Details mtlsEndSessionEndpoint URL for Mutual TLS (mTLS) to which an RP can perform a redirect to request that the end user be logged out at the OP Details mtlsIdGenerationEndpoint Mutual TLS (mTLS) ID generation endpoint URL Details mtlsIntrospectionEndpoint Mutual TLS (mTLS) introspection endpoint URL Details mtlsJwksUri URL for Mutual TLS (mTLS) of the OP's JSON Web Key Set (JWK) document Details mtlsParEndpoint Mutual TLS (mTLS) Pushed Authorization Requests(PAR) endpoint URL Details mtlsRegistrationEndpoint Mutual TLS (mTLS) registration endpoint URL Details mtlsTokenEndpoint URL for Mutual TLS (mTLS) Authorization token Endpoint Details mtlsTokenRevocationEndpoint URL for Mutual TLS (mTLS) Authorization token revocation endpoint Details mtlsUserInfoEndpoint Mutual TLS (mTLS) user info endpoint URL Details openIdConfigurationEndpoint URL for the Open ID Connect Configuration Endpoint Details openIdDiscoveryEndpoint Discovery endpoint URL Details openidScopeBackwardCompatibility Set to false to only allow token endpoint request for openid scope with grant type equals to authorization_code, restrict access to userinfo to scope openid and only return id_token if scope contains openid Details openidSubAttribute Specifies which LDAP attribute is used for the subject identifier claim Details opPolicyUri URL that the OpenID Provider provides to the person registering the Client to read about the OP's requirements on how the Relying Party can use the data provided by the OP Details opTosUri URL that the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service Details pairwiseCalculationKey Key to calculate algorithmic pairwise IDs Details pairwiseCalculationSalt Salt to calculate algorithmic pairwise IDs Details pairwiseIdType the pairwise ID type Details parEndpoint URL for Pushed Authorisation Request (PAR) Endpoint Details persistIdToken Specifies whether to persist id_token (otherwise saves into cache) Details persistRefreshToken Specifies whether to persist refresh_token (otherwise saves into cache) Details personCustomObjectClassList This list details LDAP custom object classes for dynamic person enrollment Details publicSubjectIdentifierPerClientEnabled Specifies whether public subject identifier is allowed per client Details redirectUrisRegexEnabled Enable/Disable redirect uris validation using regular expression Details refreshTokenExtendLifetimeOnRotation Boolean value specifying whether to extend refresh tokens on rotation Details refreshTokenLifetime The lifetime of the Refresh Token Details registrationEndpoint Registration endpoint URL Details rejectEndSessionIfIdTokenExpired default value false. If true and id_token is not found in db, request is rejected Details rejectJwtWithNoneAlg Boolean value specifying whether reject JWT requested or validated with algorithm None. Default value is true Details removeRefreshTokensForClientOnLogout Boolean value specifying whether to remove Refresh Tokens on logout. Default value is true Details requestObjectEncryptionAlgValuesSupported A list of the JWE encryption algorithms (alg values) supported by the OP for Request Objects Details requestObjectEncryptionEncValuesSupported A list of the JWE encryption algorithms (enc values) supported by the OP for Request Objects Details requestObjectSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for Request Objects Details requestParameterSupported Boolean value specifying whether the OP supports use of the request parameter Details requestUriBlockList Block list for requestUri that can come to Authorization Endpoint (e.g. localhost) Details requestUriHashVerificationEnabled Boolean value specifying whether the OP supports use of the request_uri hash verification Details requestUriParameterSupported Boolean value specifying whether the OP supports use of the request_uri parameter Details requirePar Boolean value to indicate of Pushed Authorisation Request(PAR)is required Details requirePkce Boolean value true check for Proof Key for Code Exchange (PKCE) Details requireRequestObjectEncryption Boolean value true encrypts request object Details requireRequestUriRegistration Boolean value specifying whether the OP requires any request_uri values used to be pre-registered using the request_uris registration parameter Details responseModesSupported This list details which OAuth 2.0 response modes are supported by this OP Details responseTypesSupported This list details which OAuth 2.0 response_type values are supported by this OP. Details returnClientSecretOnRead Boolean value specifying whether a client_secret is returned on client GET or PUT. Set to true by default which means to return secret Details returnDeviceSecretFromAuthzEndpoint Details rotateClientRegistrationAccessTokenOnUsage Boolean value specifying whether to rotate client registration access token after each usage Details rotateDeviceSecret Details sectorIdentifierCacheLifetimeInMinutes Sector Identifier cache lifetime in minutes Details serverSessionIdLifetime Dedicated property to control lifetime of the server side OP session object in seconds. Overrides sessionIdLifetime. By default value is 0, so object lifetime equals sessionIdLifetime (which sets both cookie and object expiration). It can be useful if goal is to keep different values for client cookie and server object Details serviceDocumentation URL of a page containing human-readable information that developers might want or need to know when using the OpenID Provider Details sessionIdLifetime The lifetime of session id in seconds. If 0 or -1 then expiration is not set. session_id cookie expires when browser session ends Details sessionIdPersistInCache Boolean value specifying whether to persist session_id in cache Details sessionIdPersistOnPromptNone Boolean value specifying whether to persist session ID on prompt none Details sessionIdRequestParameterEnabled Boolean value specifying whether to enable session_id HTTP request parameter Details sessionIdUnauthenticatedUnusedLifetime The lifetime for unused unauthenticated session states Details sessionIdUnusedLifetime The lifetime for unused session states Details shareSubjectIdBetweenClientsWithSameSectorId When true, clients with the same Sector ID also share the same Subject ID Details skipAuthenticationFilterOptionsMethod Force Authentication Filtker to process OPTIONS request Details skipAuthorizationForOpenIdScopeAndPairwiseId Choose whether to skip authorization if a client has an OpenId scope and a pairwise ID Details skipRefreshTokenDuringRefreshing Boolean value specifying whether to skip refreshing tokens on refreshing Details softwareStatementValidationClaimName Validation claim name for software statement Details softwareStatementValidationType Validation type used for software statement Details spontaneousScopeLifetime The lifetime of spontaneous scope in seconds Details ssaConfiguration SSA Configuration Details statAuthorizationScope Scope required for Statistical Authorization Details staticDecryptionKid Specifies static decryption Kid Details staticKid Specifies static Kid Details statTimerIntervalInSeconds Statistical data capture time interval Details subjectIdentifiersPerClientSupported A list of the subject identifiers supported per client Details subjectTypesSupported This list details which Subject Identifier types that the OP supports. Valid types include pairwise and public. Details tokenEndpoint The token endpoint URL Details tokenEndpointAuthMethodsSupported A list of Client Authentication methods supported by this Token Endpoint Details tokenEndpointAuthSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the Token Endpoint for the signature on the JWT used to authenticate the Client at the Token Endpoint for the private_key_jwt and client_secret_jwt authentication methods Details tokenRevocationEndpoint The URL for the access_token or refresh_token revocation endpoint Details trustedClientEnabled Boolean value specifying whether a client is trusted and no authorization is required Details trustedSsaIssuers List of trusted SSA issuers with configuration (e.g. automatically granted scopes). Details uiLocalesSupported This list details the languages and scripts supported for the user interface Details umaAddScopesAutomatically Add UMA scopes automatically if it is not registered yet Details umaConfigurationEndpoint UMA Configuration endpoint URL Details umaGrantAccessIfNoPolicies Specify whether to grant access to resources if there is no any policies associated with scopes Details umaPctLifetime UMA PCT lifetime Details umaResourceLifetime UMA Resource lifetime Details umaRestrictResourceToAssociatedClient Restrict access to resource by associated client Details umaRptAsJwt Issue RPT as JWT or as random string Details umaRptLifetime UMA RPT lifetime Details umaTicketLifetime UMA ticket lifetime Details umaValidateClaimToken Validate claim_token as id_token assuming it is issued by local id Details updateClientAccessTime Choose if application should update oxLastAccessTime/oxLastLogonTime attributes upon client authentication Details updateUserLastLogonTime Choose if application should update oxLastLogonTime attribute upon user authentication Details useHighestLevelScriptIfAcrScriptNotFound Enable/Disable usage of highest level script in case ACR script does not exist Details useLocalCache Cache in local memory cache attributes, scopes, clients and organization entry with expiration 60 seconds Details useNestedJwtDuringEncryption Boolean value specifying whether to use nested Jwt during encryption Details userInfoEncryptionAlgValuesSupported This JSON Array lists which JWS encryption algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details userInfoEncryptionEncValuesSupported This JSON Array lists which JWS encryption algorithms (enc values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details userInfoEndpoint The User Info endpoint URL Details userInfoSigningAlgValuesSupported This JSON Array lists which JWS signing algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details webKeysStorage Web Key Storage Type Details accessTokenLifetime # Description: The lifetime of the short lived Access Token Required: No Default value: None accessTokenSigningAlgValuesSupported # Description: A list of the JWS signing algorithms (alg values) supported by the OP for the access token to encode the Claims in a JWT Required: No Default value: None activeSessionAuthorizationScope # Description: Authorization Scope for active session Required: No Default value: None agamaConfiguration # Description: Engine Config which offers an alternative way to build authentication flows in Janssen server Required: No Default value: None allowAllValueForRevokeEndpoint # Description: Boolean value true allow all value for revoke endpoint Required: No Default value: false allowBlankValuesInDiscoveryResponse # Description: Boolean value specifying whether to allow blank values in discovery response Required: No Default value: false allowEndSessionWithUnmatchedSid # Description: default value false. If true, sid check will be skipped Required: No Default value: false allowIdTokenWithoutImplicitGrantType # Description: Specifies if a token without implicit grant types is allowed Required: No Default value: None allowPostLogoutRedirectWithoutValidation # Description: Allows post-logout redirect without validation for the End Session endpoint (still AS validates it against clientWhiteList url pattern property) Required: No Default value: false allowSpontaneousScopes # Description: Specifies whether to allow spontaneous scopes Required: No Default value: None authenticationFilters # Description: This list details filters for user authentication Required: No Default value: None authenticationFiltersEnabled # Description: Boolean value specifying whether to enable user authentication filters Required: No Default value: None authenticationProtectionConfiguration # Description: Authentication Brute Force Protection Configuration Required: No Default value: None authorizationCodeLifetime # Description: The lifetime of the Authorization Code Required: No Default value: None authorizationEncryptionAlgValuesSupported # Description: List of authorization encryption algorithms supported by this OP Required: No Default value: None authorizationEncryptionEncValuesSupported # Description: A list of the authorization encryption algorithms supported Required: No Default value: None authorizationEndpoint # Description: The authorization endpoint URL Required: No Default value: None authorizationRequestCustomAllowedParameters # Description: This list details the allowed custom parameters for authorization requests Required: No Default value: None authorizationSigningAlgValuesSupported # Description: List of authorization signing algorithms supported by this OP Required: No Default value: None backchannelAuthenticationEndpoint # Description: Backchannel Authentication Endpoint Required: No Default value: None backchannelAuthenticationRequestSigningAlgValuesSupported # Description: Backchannel Authentication Request Signing Alg Values Supported Required: No Default value: None backchannelAuthenticationResponseExpiresIn # Description: Backchannel Authentication Response Expires In Required: No Default value: None backchannelAuthenticationResponseInterval # Description: Backchannel Authentication Response Interval Required: No Default value: None backchannelBindingMessagePattern # Description: Backchannel Binding Message Pattern Required: No Default value: None backchannelClientId # Description: Backchannel Client Id Required: No Default value: None backchannelDeviceRegistrationEndpoint # Description: Backchannel Device Registration Endpoint Required: No Default value: None backchannelLoginHintClaims # Description: Backchannel Login Hint Claims Required: No Default value: None backchannelRedirectUri # Description: Backchannel Redirect Uri Required: No Default value: None backchannelRequestsProcessorJobChunkSize # Description: Each backchannel request processor iteration fetches chunk of data to be processed Required: No Default value: None backchannelRequestsProcessorJobIntervalSec # Description: Specifies the allowable elapsed time in seconds backchannel request processor executes Required: No Default value: None backchannelTokenDeliveryModesSupported # Description: Backchannel Token Delivery Modes Supported Required: No Default value: None backchannelUserCodeParameterSupported # Description: Backchannel User Code Parameter Supported Required: No Default value: None baseEndpoint # Description: The base URL for endpoints Required: No Default value: None blockWebviewAuthorizationEnabled # Description: Enable/Disable block authorizations that originate from Webview (Mobile apps). Required: No Default value: false changeSessionIdOnAuthentication # Description: Boolean value specifying whether change session_id on authentication. Default value is true Required: No Default value: true checkSessionIFrame # Description: URL for an OP IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Required: No Default value: None checkUserPresenceOnRefreshToken # Description: Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check. Required: No Default value: false cibaEndUserNotificationConfig # Description: CIBA End User Notification Config Required: No Default value: None cibaGrantLifeExtraTimeSec # Description: Specifies the CIBA Grant life extra time in seconds Required: No Default value: None cibaMaxExpirationTimeAllowedSec # Description: Specifies the CIBA token expiration time in seconds Required: No Default value: None claimsLocalesSupported # Description: This list details the languages and scripts supported for values in the claims being returned Required: No Default value: None claimsParameterSupported # Description: Specifies whether the OP supports use of the claims parameter Required: No Default value: None claimTypesSupported # Description: A list of the Claim Types that the OpenID Provider supports Required: No Default value: None cleanServiceBatchChunkSize # Description: Clean service chunk size which is used during clean up Required: No Default value: 100 cleanServiceInterval # Description: Time interval for the Clean Service in seconds Required: No Default value: None clientAuthenticationFilters # Description: This list details filters for client authentication Required: No Default value: None clientAuthenticationFiltersEnabled # Description: Boolean value specifying whether to enable client authentication filters Required: No Default value: None clientBlackList # Description: This list specified which client redirection URIs are black-listed Required: No Default value: None clientInfoEndpoint # Description: The Client Info endpoint URL Required: No Default value: None clientRegDefaultToCodeFlowWithRefresh # Description: Boolean value specifying whether to add Authorization Code Flow with Refresh grant during client registratio Required: No Default value: None clientWhiteList # Description: This list specifies which client redirection URIs are white-listed Required: No Default value: None configurationUpdateInterval # Description: The interval for configuration update in seconds Required: No Default value: None consentGatheringScriptBackwardCompatibility # Description: Boolean value specifying whether to turn on Consent Gathering Script backward compatibility mode. If true AS will pick up script with higher level globally. If false (default) AS will pick up script based on client configuration Required: No Default value: false cookieDomain # Description: Sets cookie domain for all cookies created by OP Required: No Default value: None corsConfigurationFilters # Description: This list specifies the CORS configuration filters Required: No Default value: None cssLocation # Description: The location for CSS files Required: No Default value: None customHeadersWithAuthorizationResponse # Description: Choose whether to enable the custom response header parameter to return custom headers with the authorization response Required: No Default value: None dateFormatterPatterns # Description: List of key value date formatters, e.g. 'userinfo: 'yyyy-MM-dd', etc. Required: No Default value: None dcrAuthorizationWithClientCredentials # Description: Boolean value indicating if DCR authorization to be performed using client credentials Required: No Default value: false dcrAuthorizationWithMTLS # Description: Boolean value indicating if DCR authorization allowed with MTLS Required: No Default value: false dcrForbidExpirationTimeInRequest # Description: Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration. Required: No Default value: false dcrSignatureValidationEnabled # Description: Boolean value enables DCR signature validation. Default is false Required: No Default value: false dcrSignatureValidationJwks # Description: Specifies JWKS for all DCR's validations Required: No Default value: None dcrSignatureValidationJwksUri # Description: Specifies JWKS URI for all DCR's validations Required: No Default value: None dcrSignatureValidationSharedSecret # Description: Specifies shared secret for Dynamic Client Registration Required: No Default value: None dcrSignatureValidationSoftwareStatementJwksClaim # Description: Specifies claim name inside software statement. Value of claim should point to inlined JWKS Required: No Default value: None dcrSignatureValidationSoftwareStatementJwksURIClaim # Description: Specifies claim name inside software statement. Value of claim should point to JWKS URI Required: No Default value: None dcrSsaValidationConfigs # Description: DCR SSA Validation configurations used to perform validation of SSA or DCR Required: No Default value: None defaultSignatureAlgorithm # Description: The default signature algorithm to sign ID Tokens Required: No Default value: None defaultSubjectType # Description: The default subject type used for dynamic client registration Required: No Default value: None deviceAuthzAcr # Description: Device authz acr Required: No Default value: None deviceAuthzEndpoint # Description: URL for the Device Authorization Required: No Default value: None deviceAuthzRequestExpiresIn # Description: Expiration time given for device authorization requests Required: No Default value: None deviceAuthzResponseTypeToProcessAuthz # Description: Response type used to process device authz requests Required: No Default value: None deviceAuthzTokenPollInterval # Description: Default interval returned to the client to process device token requests Required: No Default value: None disableAuthnForMaxAgeZero # Description: Boolean value specifying whether to disable authentication when max_age=0 Required: No Default value: false disableJdkLogger # Description: Choose whether to disable JDK loggers Required: No Default value: true disablePromptConsent # Description: Boolean value specifying whether to disable prompt=consent Required: No Default value: false disablePromptLogin # Description: Boolean value specifying whether to disable prompt=login Required: No Default value: false disableU2fEndpoint # Description: Choose whether to disable U2F endpoints Required: No Default value: false discoveryAllowedKeys # Description: List of configuration response claim allowed to be displayed in discovery endpoint Required: No Default value: None discoveryCacheLifetimeInMinutes # Description: Lifetime of discovery cache Required: No Default value: 60 discoveryDenyKeys # Description: List of configuration response claims which must not be displayed in discovery endpoint response Required: No Default value: None displayValuesSupported # Description: A list of the display parameter values that the OpenID Provider supports Required: No Default value: None dnName # Description: DN of certificate issuer Required: No Default value: None dpopJtiCacheTime # Description: Demonstration of Proof-of-Possession (DPoP) cache time Required: No Default value: 3600 dpopNonceCacheTime # Description: Demonstration of Proof-of-Possession (DPoP) nonce cache time Required: No Default value: 3600 dpopSigningAlgValuesSupported # Description: Demonstration of Proof-of-Possession (DPoP) authorization signing algorithms supported Required: No Default value: None dpopTimeframe # Description: Demonstration of Proof-of-Possession (DPoP) timeout Required: No Default value: 5 dpopUseNonce # Description: Demonstration of Proof-of-Possession (DPoP) use nonce Required: No Default value: false grantTypesSupportedByDynamicRegistration # Description: This list details which OAuth 2.0 grant types can be set up with the client registration API Required: No Default value: None dynamicRegistrationAllowedPasswordGrantScopes # Description: List of grant scopes for dynamic registration Required: No Default value: None dynamicRegistrationCustomAttributes # Description: This list details the custom attributes allowed for dynamic registration Required: No Default value: None dynamicRegistrationCustomObjectClass # Description: LDAP custom object class for dynamic registration Required: No Default value: None dynamicRegistrationDefaultCustomAttributes # Description: This map provides default custom attributes with values for dynamic registration Required: No Default value: None dynamicRegistrationExpirationTime # Description: Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire Required: No Default value: -1 dynamicRegistrationPasswordGrantTypeEnabled # Description: Boolean value specifying whether to enable Password Grant Type during Dynamic Registration Required: No Default value: false dynamicRegistrationPersistClientAuthorizations # Description: Boolean value specifying whether to persist client authorizations Required: No Default value: None dynamicRegistrationScopesParamEnabled # Description: Boolean value specifying whether to enable scopes parameter in dynamic registration Required: No Default value: None enableClientGrantTypeUpdate # Description: Choose if client can update Grant Type values Required: No Default value: None enabledOAuthAuditLogging # Description: enable OAuth Audit Logging Required: No Default value: None endSessionEndpoint # Description: URL at the OP to which an RP can perform a redirect to request that the end user be logged out at the OP Required: No Default value: None endSessionWithAccessToken # Description: Choose whether to accept access tokens to call end_session endpoint Required: No Default value: None errorHandlingMethod # Description: A list of possible error handling methods. Possible values: remote (send error back to RP), internal (show error page) Required: No Default value: remote errorReasonEnabled # Description: Boolean value specifying whether to return detailed reason of the error from AS. Default value is false Required: No Default value: false expirationNotificatorEnabled # Description: Boolean value specifying whether expiration notificator is enabled (used to identify expiration for persistence that support TTL, like Couchbase) Required: No Default value: false expirationNotificatorIntervalInSeconds # Description: The expiration notificator interval in second Required: No Default value: None expirationNotificatorMapSizeLimit # Description: The expiration notificator maximum size limit Required: No Default value: None externalLoggerConfiguration # Description: The path to the external log4j2 logging configuration Required: No Default value: None externalUriWhiteList # Description: This list specifies which external URIs can be called by AS (if empty any URI can be called) Required: No Default value: None fapiCompatibility # Description: Boolean value specifying whether to turn on FAPI compatibility mode. If true AS behaves in more strict mode Required: No Default value: false featureFlags # Description: List of enabled feature flags Required: No Default value: None forceIdTokenHintPresence # Description: Boolean value specifying whether force id_token_hint parameter presence Required: No Default value: false forceOfflineAccessScopeToEnableRefreshToken # Description: Boolean value specifying whether force offline_access scope to enable refresh_token grant type. Default value is true Required: No Default value: true forceSignedRequestObject # Description: Boolean value true indicates that signed request object is mandatory Required: No Default value: false frontChannelLogoutSessionSupported # Description: Choose whether to support front channel session logout Required: No Default value: None grantTypesAndResponseTypesAutofixEnabled # Description: Boolean value specifying whether to Grant types and Response types can be auto fixed Required: No Default value: None grantTypesSupported # Description: This list details which OAuth 2.0 grant types are supported by this OP Required: No Default value: None httpLoggingEnabled # Description: Enable/disable request/response logging filter Required: No Default value: None httpLoggingExcludePaths # Description: This list details the base URIs for which the request/response logging filter will not record activity Required: No Default value: None httpLoggingResponseBodyContent # Description: Defines if Response body will be logged. Default value is false Required: No Default value: false idGenerationEndpoint # Description: ID Generation endpoint URL Required: No Default value: None idTokenEncryptionAlgValuesSupported # Description: A list of the JWE encryption algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None idTokenEncryptionEncValuesSupported # Description: A list of the JWE encryption algorithms (enc values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None idTokenFilterClaimsBasedOnAccessToken # Description: Boolean value specifying whether idToken filters claims based on accessToken Required: No Default value: None idTokenLifetime # Description: The lifetime of the ID Token Required: No Default value: None idTokenSigningAlgValuesSupported # Description: A list of the JWS signing algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None idTokenTokenBindingCnfValuesSupported # Description: Array containing a list of the JWT Confirmation Method member names supported by the OP for Token Binding of ID Tokens. The presence of this parameter indicates that the OpenID Provider supports Token Binding of ID Tokens. If omitted, the default is that the OpenID Provider does not support Token Binding of ID Tokens Required: No Default value: None imgLocation # Description: The location for image files Required: No Default value: None includeSidInResponse # Description: Boolean value specifying whether to include sessionId in response Required: No Default value: false introspectionAccessTokenMustHaveIntrospectionScope # Description: If True, rejects introspection requests if access_token does not have the 'introspection' scope in its authorization header. Comparing to 'uma_protection', 'introspection' scope is not allowed for dynamic registration' Required: No Default value: false introspectionAccessTokenMustHaveUmaProtectionScope # Description: If True, rejects introspection requests if access_token does not have the uma_protection scope in its authorization header Required: No Default value: false introspectionEndpoint # Description: Introspection endpoint URL Required: No Default value: None introspectionResponseScopesBackwardCompatibility # Description: Boolean value specifying introspection response backward compatibility mode Required: No Default value: false introspectionScriptBackwardCompatibility # Description: Boolean value specifying whether switch off client's introspection scripts (true value) and run all scripts that exists on server. Default value is false Required: No Default value: false introspectionSkipAuthorization # Description: Specifies if authorization to be skipped for introspection Required: No Default value: None invalidateSessionCookiesAfterAuthorizationFlow # Description: Boolean value to specify whether to invalidate session_id and consent_session_id cookies right after successful or unsuccessful authorization Required: No Default value: false issuer # Description: URL using the https scheme that OP asserts as Issuer identifier Required: No Default value: None jansId # Description: URL for the Inum generator Service Required: No Default value: None jansOpenIdConnectVersion # Description: OpenID Connect Version Required: No Default value: None jmsBrokerURISet # Description: JMS Broker URI Set Required: No Default value: None jmsPassword # Description: JMS Password Required: No Default value: None jmsUserName # Description: JMS UserName Required: No Default value: None jsLocation # Description: The location for JavaScript files Required: No Default value: None jwksAlgorithmsSupported # Description: A list of algorithms that will be used in JWKS endpoint Required: No Default value: None jwksUri # Description: URL of the OP's JSON Web Key Set (JWK) document. This contains the signing key(s) the RP uses to validate signatures from the OP Required: No Default value: None keepAuthenticatorAttributesOnAcrChange # Description: Boolean value specifying whether to keep authenticator attributes on ACR change Required: No Default value: false keyAlgsAllowedForGeneration # Description: List of algorithm allowed to be used for key generation Required: No Default value: None keyRegenerationEnabled # Description: Boolean value specifying whether to regenerate keys Required: No Default value: None keyRegenerationInterval # Description: The interval for key regeneration in hours Required: No Default value: None keySelectionStrategy # Description: Key Selection Strategy : OLDER, NEWER, FIRST Required: No Default value: OLDER keySignWithSameKeyButDiffAlg # Description: Specifies if signing to be done with same key but apply different algorithms Required: No Default value: None keyStoreFile # Description: The Key Store File (JKS) Required: No Default value: None keyStoreSecret # Description: The Key Store password Required: No Default value: None legacyIdTokenClaims # Description: Choose whether to include claims in ID tokens Required: No Default value: None logClientIdOnClientAuthentication # Description: Choose if application should log the Client ID on client authentication Required: No Default value: None logClientNameOnClientAuthentication # Description: Choose if application should log the Client Name on client authentication Required: No Default value: None loggingLayout # Description: Logging layout used for Jans Authorization Server loggers Required: No Default value: None loggingLevel # Description: Specify the logging level of loggers Required: No Default value: None logNotFoundEntityAsError # Description: Boolean value specifying whether to log not_found entity exception as error or as trace. Default value is false (trace). Required: No Default value: None metricReporterInterval # Description: The interval for metric reporter in seconds Required: No Default value: None metricReporterKeepDataDays # Description: The days to keep metric reported data Required: No Default value: None mtlsAuthorizationEndpoint # Description: URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Endpoint Required: No Default value: None mtlsCheckSessionIFrame # Description: URL for Mutual TLS (mTLS) IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Required: No Default value: None mtlsClientInfoEndpoint # Description: URL for Mutual TLS (mTLS) Client Info endpoint Required: No Default value: None mtlsDeviceAuthzEndpoint # Description: Mutual TLS (mTLS) device authorization endpoint URL Required: No Default value: None mtlsEndSessionEndpoint # Description: URL for Mutual TLS (mTLS) to which an RP can perform a redirect to request that the end user be logged out at the OP Required: No Default value: None mtlsIdGenerationEndpoint # Description: Mutual TLS (mTLS) ID generation endpoint URL Required: No Default value: None mtlsIntrospectionEndpoint # Description: Mutual TLS (mTLS) introspection endpoint URL Required: No Default value: None mtlsJwksUri # Description: URL for Mutual TLS (mTLS) of the OP's JSON Web Key Set (JWK) document Required: No Default value: None mtlsParEndpoint # Description: Mutual TLS (mTLS) Pushed Authorization Requests(PAR) endpoint URL Required: No Default value: None mtlsRegistrationEndpoint # Description: Mutual TLS (mTLS) registration endpoint URL Required: No Default value: None mtlsTokenEndpoint # Description: URL for Mutual TLS (mTLS) Authorization token Endpoint Required: No Default value: None mtlsTokenRevocationEndpoint # Description: URL for Mutual TLS (mTLS) Authorization token revocation endpoint Required: No Default value: None mtlsUserInfoEndpoint # Description: Mutual TLS (mTLS) user info endpoint URL Required: No Default value: None openIdConfigurationEndpoint # Description: URL for the Open ID Connect Configuration Endpoint Required: No Default value: None openIdDiscoveryEndpoint # Description: Discovery endpoint URL Required: No Default value: None openidScopeBackwardCompatibility # Description: Set to false to only allow token endpoint request for openid scope with grant type equals to authorization_code, restrict access to userinfo to scope openid and only return id_token if scope contains openid Required: No Default value: false openidSubAttribute # Description: Specifies which LDAP attribute is used for the subject identifier claim Required: No Default value: None opPolicyUri # Description: URL that the OpenID Provider provides to the person registering the Client to read about the OP's requirements on how the Relying Party can use the data provided by the OP Required: No Default value: None opTosUri # Description: URL that the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service Required: No Default value: None pairwiseCalculationKey # Description: Key to calculate algorithmic pairwise IDs Required: No Default value: None pairwiseCalculationSalt # Description: Salt to calculate algorithmic pairwise IDs Required: No Default value: None pairwiseIdType # Description: the pairwise ID type Required: No Default value: None parEndpoint # Description: URL for Pushed Authorisation Request (PAR) Endpoint Required: No Default value: None persistIdToken # Description: Specifies whether to persist id_token (otherwise saves into cache) Required: No Default value: false persistRefreshToken # Description: Specifies whether to persist refresh_token (otherwise saves into cache) Required: No Default value: true personCustomObjectClassList # Description: This list details LDAP custom object classes for dynamic person enrollment Required: No Default value: None publicSubjectIdentifierPerClientEnabled # Description: Specifies whether public subject identifier is allowed per client Required: No Default value: false redirectUrisRegexEnabled # Description: Enable/Disable redirect uris validation using regular expression Required: No Default value: false refreshTokenExtendLifetimeOnRotation # Description: Boolean value specifying whether to extend refresh tokens on rotation Required: No Default value: false refreshTokenLifetime # Description: The lifetime of the Refresh Token Required: No Default value: None registrationEndpoint # Description: Registration endpoint URL Required: No Default value: None rejectEndSessionIfIdTokenExpired # Description: default value false. If true and id_token is not found in db, request is rejected Required: No Default value: false rejectJwtWithNoneAlg # Description: Boolean value specifying whether reject JWT requested or validated with algorithm None. Default value is true Required: No Default value: true removeRefreshTokensForClientOnLogout # Description: Boolean value specifying whether to remove Refresh Tokens on logout. Default value is true Required: No Default value: true requestObjectEncryptionAlgValuesSupported # Description: A list of the JWE encryption algorithms (alg values) supported by the OP for Request Objects Required: No Default value: None requestObjectEncryptionEncValuesSupported # Description: A list of the JWE encryption algorithms (enc values) supported by the OP for Request Objects Required: No Default value: None requestObjectSigningAlgValuesSupported # Description: A list of the JWS signing algorithms (alg values) supported by the OP for Request Objects Required: No Default value: None requestParameterSupported # Description: Boolean value specifying whether the OP supports use of the request parameter Required: No Default value: None requestUriBlockList # Description: Block list for requestUri that can come to Authorization Endpoint (e.g. localhost) Required: No Default value: None requestUriHashVerificationEnabled # Description: Boolean value specifying whether the OP supports use of the request_uri hash verification Required: No Default value: None requestUriParameterSupported # Description: Boolean value specifying whether the OP supports use of the request_uri parameter Required: No Default value: None requirePar # Description: Boolean value to indicate of Pushed Authorisation Request(PAR)is required Required: No Default value: false requirePkce # Description: Boolean value true check for Proof Key for Code Exchange (PKCE) Required: No Default value: false requireRequestObjectEncryption # Description: Boolean value true encrypts request object Required: No Default value: false requireRequestUriRegistration # Description: Boolean value specifying whether the OP requires any request_uri values used to be pre-registered using the request_uris registration parameter Required: No Default value: None responseModesSupported # Description: This list details which OAuth 2.0 response modes are supported by this OP Required: No Default value: None responseTypesSupported # Description: This list details which OAuth 2.0 response_type values are supported by this OP. Required: No Default value: By default, every combination of code, token and id_token is supported. returnClientSecretOnRead # Description: Boolean value specifying whether a client_secret is returned on client GET or PUT. Set to true by default which means to return secret Required: No Default value: false returnDeviceSecretFromAuthzEndpoint # Description: Required: No Default value: false rotateClientRegistrationAccessTokenOnUsage # Description: Boolean value specifying whether to rotate client registration access token after each usage Required: No Default value: false rotateDeviceSecret # Description: Required: No Default value: false sectorIdentifierCacheLifetimeInMinutes # Description: Sector Identifier cache lifetime in minutes Required: No Default value: 1440 serverSessionIdLifetime # Description: Dedicated property to control lifetime of the server side OP session object in seconds. Overrides sessionIdLifetime. By default value is 0, so object lifetime equals sessionIdLifetime (which sets both cookie and object expiration). It can be useful if goal is to keep different values for client cookie and server object Required: No Default value: None serviceDocumentation # Description: URL of a page containing human-readable information that developers might want or need to know when using the OpenID Provider Required: No Default value: None sessionIdLifetime # Description: The lifetime of session id in seconds. If 0 or -1 then expiration is not set. session_id cookie expires when browser session ends Required: No Default value: None sessionIdPersistInCache # Description: Boolean value specifying whether to persist session_id in cache Required: No Default value: false sessionIdPersistOnPromptNone # Description: Boolean value specifying whether to persist session ID on prompt none Required: No Default value: None sessionIdRequestParameterEnabled # Description: Boolean value specifying whether to enable session_id HTTP request parameter Required: No Default value: false sessionIdUnauthenticatedUnusedLifetime # Description: The lifetime for unused unauthenticated session states Required: No Default value: None sessionIdUnusedLifetime # Description: The lifetime for unused session states Required: No Default value: None shareSubjectIdBetweenClientsWithSameSectorId # Description: When true, clients with the same Sector ID also share the same Subject ID Required: No Default value: false skipAuthenticationFilterOptionsMethod # Description: Force Authentication Filtker to process OPTIONS request Required: No Default value: true skipAuthorizationForOpenIdScopeAndPairwiseId # Description: Choose whether to skip authorization if a client has an OpenId scope and a pairwise ID Required: No Default value: false skipRefreshTokenDuringRefreshing # Description: Boolean value specifying whether to skip refreshing tokens on refreshing Required: No Default value: false softwareStatementValidationClaimName # Description: Validation claim name for software statement Required: No Default value: None softwareStatementValidationType # Description: Validation type used for software statement Required: No Default value: None spontaneousScopeLifetime # Description: The lifetime of spontaneous scope in seconds Required: No Default value: None ssaConfiguration # Description: SSA Configuration Required: No Default value: None statAuthorizationScope # Description: Scope required for Statistical Authorization Required: No Default value: None staticDecryptionKid # Description: Specifies static decryption Kid Required: No Default value: None staticKid # Description: Specifies static Kid Required: No Default value: None statTimerIntervalInSeconds # Description: Statistical data capture time interval Required: No Default value: None subjectIdentifiersPerClientSupported # Description: A list of the subject identifiers supported per client Required: No Default value: None subjectTypesSupported # Description: This list details which Subject Identifier types that the OP supports. Valid types include pairwise and public. Required: No Default value: None tokenEndpoint # Description: The token endpoint URL Required: No Default value: None tokenEndpointAuthMethodsSupported # Description: A list of Client Authentication methods supported by this Token Endpoint Required: No Default value: None tokenEndpointAuthSigningAlgValuesSupported # Description: A list of the JWS signing algorithms (alg values) supported by the Token Endpoint for the signature on the JWT used to authenticate the Client at the Token Endpoint for the private_key_jwt and client_secret_jwt authentication methods Required: No Default value: None tokenRevocationEndpoint # Description: The URL for the access_token or refresh_token revocation endpoint Required: No Default value: None trustedClientEnabled # Description: Boolean value specifying whether a client is trusted and no authorization is required Required: No Default value: None trustedSsaIssuers # Description: List of trusted SSA issuers with configuration (e.g. automatically granted scopes). Required: No Default value: None uiLocalesSupported # Description: This list details the languages and scripts supported for the user interface Required: No Default value: None umaAddScopesAutomatically # Description: Add UMA scopes automatically if it is not registered yet Required: No Default value: None umaConfigurationEndpoint # Description: UMA Configuration endpoint URL Required: No Default value: None umaGrantAccessIfNoPolicies # Description: Specify whether to grant access to resources if there is no any policies associated with scopes Required: No Default value: false umaPctLifetime # Description: UMA PCT lifetime Required: No Default value: None umaResourceLifetime # Description: UMA Resource lifetime Required: No Default value: None umaRestrictResourceToAssociatedClient # Description: Restrict access to resource by associated client Required: No Default value: false umaRptAsJwt # Description: Issue RPT as JWT or as random string Required: No Default value: false umaRptLifetime # Description: UMA RPT lifetime Required: No Default value: None umaTicketLifetime # Description: UMA ticket lifetime Required: No Default value: None umaValidateClaimToken # Description: Validate claim_token as id_token assuming it is issued by local id Required: No Default value: false updateClientAccessTime # Description: Choose if application should update oxLastAccessTime/oxLastLogonTime attributes upon client authentication Required: No Default value: None updateUserLastLogonTime # Description: Choose if application should update oxLastLogonTime attribute upon user authentication Required: No Default value: None useHighestLevelScriptIfAcrScriptNotFound # Description: Enable/Disable usage of highest level script in case ACR script does not exist Required: No Default value: false useLocalCache # Description: Cache in local memory cache attributes, scopes, clients and organization entry with expiration 60 seconds Required: No Default value: false useNestedJwtDuringEncryption # Description: Boolean value specifying whether to use nested Jwt during encryption Required: No Default value: true userInfoEncryptionAlgValuesSupported # Description: This JSON Array lists which JWS encryption algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None userInfoEncryptionEncValuesSupported # Description: This JSON Array lists which JWS encryption algorithms (enc values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None userInfoEndpoint # Description: The User Info endpoint URL Required: No Default value: None userInfoSigningAlgValuesSupported # Description: This JSON Array lists which JWS signing algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None webKeysStorage # Description: Web Key Storage Type Required: No Default value: None", "title": "Auth Server"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#janssen-auth-server-configuration-properties", "text": "Property Name Description accessTokenLifetime The lifetime of the short lived Access Token Details accessTokenSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for the access token to encode the Claims in a JWT Details activeSessionAuthorizationScope Authorization Scope for active session Details agamaConfiguration Engine Config which offers an alternative way to build authentication flows in Janssen server Details allowAllValueForRevokeEndpoint Boolean value true allow all value for revoke endpoint Details allowBlankValuesInDiscoveryResponse Boolean value specifying whether to allow blank values in discovery response Details allowEndSessionWithUnmatchedSid default value false. If true, sid check will be skipped Details allowIdTokenWithoutImplicitGrantType Specifies if a token without implicit grant types is allowed Details allowPostLogoutRedirectWithoutValidation Allows post-logout redirect without validation for the End Session endpoint (still AS validates it against clientWhiteList url pattern property) Details allowSpontaneousScopes Specifies whether to allow spontaneous scopes Details authenticationFilters This list details filters for user authentication Details authenticationFiltersEnabled Boolean value specifying whether to enable user authentication filters Details authenticationProtectionConfiguration Authentication Brute Force Protection Configuration Details authorizationCodeLifetime The lifetime of the Authorization Code Details authorizationEncryptionAlgValuesSupported List of authorization encryption algorithms supported by this OP Details authorizationEncryptionEncValuesSupported A list of the authorization encryption algorithms supported Details authorizationEndpoint The authorization endpoint URL Details authorizationRequestCustomAllowedParameters This list details the allowed custom parameters for authorization requests Details authorizationSigningAlgValuesSupported List of authorization signing algorithms supported by this OP Details backchannelAuthenticationEndpoint Backchannel Authentication Endpoint Details backchannelAuthenticationRequestSigningAlgValuesSupported Backchannel Authentication Request Signing Alg Values Supported Details backchannelAuthenticationResponseExpiresIn Backchannel Authentication Response Expires In Details backchannelAuthenticationResponseInterval Backchannel Authentication Response Interval Details backchannelBindingMessagePattern Backchannel Binding Message Pattern Details backchannelClientId Backchannel Client Id Details backchannelDeviceRegistrationEndpoint Backchannel Device Registration Endpoint Details backchannelLoginHintClaims Backchannel Login Hint Claims Details backchannelRedirectUri Backchannel Redirect Uri Details backchannelRequestsProcessorJobChunkSize Each backchannel request processor iteration fetches chunk of data to be processed Details backchannelRequestsProcessorJobIntervalSec Specifies the allowable elapsed time in seconds backchannel request processor executes Details backchannelTokenDeliveryModesSupported Backchannel Token Delivery Modes Supported Details backchannelUserCodeParameterSupported Backchannel User Code Parameter Supported Details baseEndpoint The base URL for endpoints Details blockWebviewAuthorizationEnabled Enable/Disable block authorizations that originate from Webview (Mobile apps). Details changeSessionIdOnAuthentication Boolean value specifying whether change session_id on authentication. Default value is true Details checkSessionIFrame URL for an OP IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Details checkUserPresenceOnRefreshToken Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check. Details cibaEndUserNotificationConfig CIBA End User Notification Config Details cibaGrantLifeExtraTimeSec Specifies the CIBA Grant life extra time in seconds Details cibaMaxExpirationTimeAllowedSec Specifies the CIBA token expiration time in seconds Details claimsLocalesSupported This list details the languages and scripts supported for values in the claims being returned Details claimsParameterSupported Specifies whether the OP supports use of the claims parameter Details claimTypesSupported A list of the Claim Types that the OpenID Provider supports Details cleanServiceBatchChunkSize Clean service chunk size which is used during clean up Details cleanServiceInterval Time interval for the Clean Service in seconds Details clientAuthenticationFilters This list details filters for client authentication Details clientAuthenticationFiltersEnabled Boolean value specifying whether to enable client authentication filters Details clientBlackList This list specified which client redirection URIs are black-listed Details clientInfoEndpoint The Client Info endpoint URL Details clientRegDefaultToCodeFlowWithRefresh Boolean value specifying whether to add Authorization Code Flow with Refresh grant during client registratio Details clientWhiteList This list specifies which client redirection URIs are white-listed Details configurationUpdateInterval The interval for configuration update in seconds Details consentGatheringScriptBackwardCompatibility Boolean value specifying whether to turn on Consent Gathering Script backward compatibility mode. If true AS will pick up script with higher level globally. If false (default) AS will pick up script based on client configuration Details cookieDomain Sets cookie domain for all cookies created by OP Details corsConfigurationFilters This list specifies the CORS configuration filters Details cssLocation The location for CSS files Details customHeadersWithAuthorizationResponse Choose whether to enable the custom response header parameter to return custom headers with the authorization response Details dateFormatterPatterns List of key value date formatters, e.g. 'userinfo: 'yyyy-MM-dd', etc. Details dcrAuthorizationWithClientCredentials Boolean value indicating if DCR authorization to be performed using client credentials Details dcrAuthorizationWithMTLS Boolean value indicating if DCR authorization allowed with MTLS Details dcrForbidExpirationTimeInRequest Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration. Details dcrSignatureValidationEnabled Boolean value enables DCR signature validation. Default is false Details dcrSignatureValidationJwks Specifies JWKS for all DCR's validations Details dcrSignatureValidationJwksUri Specifies JWKS URI for all DCR's validations Details dcrSignatureValidationSharedSecret Specifies shared secret for Dynamic Client Registration Details dcrSignatureValidationSoftwareStatementJwksClaim Specifies claim name inside software statement. Value of claim should point to inlined JWKS Details dcrSignatureValidationSoftwareStatementJwksURIClaim Specifies claim name inside software statement. Value of claim should point to JWKS URI Details dcrSsaValidationConfigs DCR SSA Validation configurations used to perform validation of SSA or DCR Details defaultSignatureAlgorithm The default signature algorithm to sign ID Tokens Details defaultSubjectType The default subject type used for dynamic client registration Details deviceAuthzAcr Device authz acr Details deviceAuthzEndpoint URL for the Device Authorization Details deviceAuthzRequestExpiresIn Expiration time given for device authorization requests Details deviceAuthzResponseTypeToProcessAuthz Response type used to process device authz requests Details deviceAuthzTokenPollInterval Default interval returned to the client to process device token requests Details disableAuthnForMaxAgeZero Boolean value specifying whether to disable authentication when max_age=0 Details disableJdkLogger Choose whether to disable JDK loggers Details disablePromptConsent Boolean value specifying whether to disable prompt=consent Details disablePromptLogin Boolean value specifying whether to disable prompt=login Details disableU2fEndpoint Choose whether to disable U2F endpoints Details discoveryAllowedKeys List of configuration response claim allowed to be displayed in discovery endpoint Details discoveryCacheLifetimeInMinutes Lifetime of discovery cache Details discoveryDenyKeys List of configuration response claims which must not be displayed in discovery endpoint response Details displayValuesSupported A list of the display parameter values that the OpenID Provider supports Details dnName DN of certificate issuer Details dpopJtiCacheTime Demonstration of Proof-of-Possession (DPoP) cache time Details dpopNonceCacheTime Demonstration of Proof-of-Possession (DPoP) nonce cache time Details dpopSigningAlgValuesSupported Demonstration of Proof-of-Possession (DPoP) authorization signing algorithms supported Details dpopTimeframe Demonstration of Proof-of-Possession (DPoP) timeout Details dpopUseNonce Demonstration of Proof-of-Possession (DPoP) use nonce Details grantTypesSupportedByDynamicRegistration This list details which OAuth 2.0 grant types can be set up with the client registration API Details dynamicRegistrationAllowedPasswordGrantScopes List of grant scopes for dynamic registration Details dynamicRegistrationCustomAttributes This list details the custom attributes allowed for dynamic registration Details dynamicRegistrationCustomObjectClass LDAP custom object class for dynamic registration Details dynamicRegistrationDefaultCustomAttributes This map provides default custom attributes with values for dynamic registration Details dynamicRegistrationExpirationTime Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire Details dynamicRegistrationPasswordGrantTypeEnabled Boolean value specifying whether to enable Password Grant Type during Dynamic Registration Details dynamicRegistrationPersistClientAuthorizations Boolean value specifying whether to persist client authorizations Details dynamicRegistrationScopesParamEnabled Boolean value specifying whether to enable scopes parameter in dynamic registration Details enableClientGrantTypeUpdate Choose if client can update Grant Type values Details enabledOAuthAuditLogging enable OAuth Audit Logging Details endSessionEndpoint URL at the OP to which an RP can perform a redirect to request that the end user be logged out at the OP Details endSessionWithAccessToken Choose whether to accept access tokens to call end_session endpoint Details errorHandlingMethod A list of possible error handling methods. Possible values: remote (send error back to RP), internal (show error page) Details errorReasonEnabled Boolean value specifying whether to return detailed reason of the error from AS. Default value is false Details expirationNotificatorEnabled Boolean value specifying whether expiration notificator is enabled (used to identify expiration for persistence that support TTL, like Couchbase) Details expirationNotificatorIntervalInSeconds The expiration notificator interval in second Details expirationNotificatorMapSizeLimit The expiration notificator maximum size limit Details externalLoggerConfiguration The path to the external log4j2 logging configuration Details externalUriWhiteList This list specifies which external URIs can be called by AS (if empty any URI can be called) Details fapiCompatibility Boolean value specifying whether to turn on FAPI compatibility mode. If true AS behaves in more strict mode Details featureFlags List of enabled feature flags Details forceIdTokenHintPresence Boolean value specifying whether force id_token_hint parameter presence Details forceOfflineAccessScopeToEnableRefreshToken Boolean value specifying whether force offline_access scope to enable refresh_token grant type. Default value is true Details forceSignedRequestObject Boolean value true indicates that signed request object is mandatory Details frontChannelLogoutSessionSupported Choose whether to support front channel session logout Details grantTypesAndResponseTypesAutofixEnabled Boolean value specifying whether to Grant types and Response types can be auto fixed Details grantTypesSupported This list details which OAuth 2.0 grant types are supported by this OP Details httpLoggingEnabled Enable/disable request/response logging filter Details httpLoggingExcludePaths This list details the base URIs for which the request/response logging filter will not record activity Details httpLoggingResponseBodyContent Defines if Response body will be logged. Default value is false Details idGenerationEndpoint ID Generation endpoint URL Details idTokenEncryptionAlgValuesSupported A list of the JWE encryption algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenEncryptionEncValuesSupported A list of the JWE encryption algorithms (enc values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenFilterClaimsBasedOnAccessToken Boolean value specifying whether idToken filters claims based on accessToken Details idTokenLifetime The lifetime of the ID Token Details idTokenSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Details idTokenTokenBindingCnfValuesSupported Array containing a list of the JWT Confirmation Method member names supported by the OP for Token Binding of ID Tokens. The presence of this parameter indicates that the OpenID Provider supports Token Binding of ID Tokens. If omitted, the default is that the OpenID Provider does not support Token Binding of ID Tokens Details imgLocation The location for image files Details includeSidInResponse Boolean value specifying whether to include sessionId in response Details introspectionAccessTokenMustHaveIntrospectionScope If True, rejects introspection requests if access_token does not have the 'introspection' scope in its authorization header. Comparing to 'uma_protection', 'introspection' scope is not allowed for dynamic registration' Details introspectionAccessTokenMustHaveUmaProtectionScope If True, rejects introspection requests if access_token does not have the uma_protection scope in its authorization header Details introspectionEndpoint Introspection endpoint URL Details introspectionResponseScopesBackwardCompatibility Boolean value specifying introspection response backward compatibility mode Details introspectionScriptBackwardCompatibility Boolean value specifying whether switch off client's introspection scripts (true value) and run all scripts that exists on server. Default value is false Details introspectionSkipAuthorization Specifies if authorization to be skipped for introspection Details invalidateSessionCookiesAfterAuthorizationFlow Boolean value to specify whether to invalidate session_id and consent_session_id cookies right after successful or unsuccessful authorization Details issuer URL using the https scheme that OP asserts as Issuer identifier Details jansId URL for the Inum generator Service Details jansOpenIdConnectVersion OpenID Connect Version Details jmsBrokerURISet JMS Broker URI Set Details jmsPassword JMS Password Details jmsUserName JMS UserName Details jsLocation The location for JavaScript files Details jwksAlgorithmsSupported A list of algorithms that will be used in JWKS endpoint Details jwksUri URL of the OP's JSON Web Key Set (JWK) document. This contains the signing key(s) the RP uses to validate signatures from the OP Details keepAuthenticatorAttributesOnAcrChange Boolean value specifying whether to keep authenticator attributes on ACR change Details keyAlgsAllowedForGeneration List of algorithm allowed to be used for key generation Details keyRegenerationEnabled Boolean value specifying whether to regenerate keys Details keyRegenerationInterval The interval for key regeneration in hours Details keySelectionStrategy Key Selection Strategy : OLDER, NEWER, FIRST Details keySignWithSameKeyButDiffAlg Specifies if signing to be done with same key but apply different algorithms Details keyStoreFile The Key Store File (JKS) Details keyStoreSecret The Key Store password Details legacyIdTokenClaims Choose whether to include claims in ID tokens Details logClientIdOnClientAuthentication Choose if application should log the Client ID on client authentication Details logClientNameOnClientAuthentication Choose if application should log the Client Name on client authentication Details loggingLayout Logging layout used for Jans Authorization Server loggers Details loggingLevel Specify the logging level of loggers Details logNotFoundEntityAsError Boolean value specifying whether to log not_found entity exception as error or as trace. Default value is false (trace). Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep metric reported data Details mtlsAuthorizationEndpoint URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Endpoint Details mtlsCheckSessionIFrame URL for Mutual TLS (mTLS) IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Details mtlsClientInfoEndpoint URL for Mutual TLS (mTLS) Client Info endpoint Details mtlsDeviceAuthzEndpoint Mutual TLS (mTLS) device authorization endpoint URL Details mtlsEndSessionEndpoint URL for Mutual TLS (mTLS) to which an RP can perform a redirect to request that the end user be logged out at the OP Details mtlsIdGenerationEndpoint Mutual TLS (mTLS) ID generation endpoint URL Details mtlsIntrospectionEndpoint Mutual TLS (mTLS) introspection endpoint URL Details mtlsJwksUri URL for Mutual TLS (mTLS) of the OP's JSON Web Key Set (JWK) document Details mtlsParEndpoint Mutual TLS (mTLS) Pushed Authorization Requests(PAR) endpoint URL Details mtlsRegistrationEndpoint Mutual TLS (mTLS) registration endpoint URL Details mtlsTokenEndpoint URL for Mutual TLS (mTLS) Authorization token Endpoint Details mtlsTokenRevocationEndpoint URL for Mutual TLS (mTLS) Authorization token revocation endpoint Details mtlsUserInfoEndpoint Mutual TLS (mTLS) user info endpoint URL Details openIdConfigurationEndpoint URL for the Open ID Connect Configuration Endpoint Details openIdDiscoveryEndpoint Discovery endpoint URL Details openidScopeBackwardCompatibility Set to false to only allow token endpoint request for openid scope with grant type equals to authorization_code, restrict access to userinfo to scope openid and only return id_token if scope contains openid Details openidSubAttribute Specifies which LDAP attribute is used for the subject identifier claim Details opPolicyUri URL that the OpenID Provider provides to the person registering the Client to read about the OP's requirements on how the Relying Party can use the data provided by the OP Details opTosUri URL that the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service Details pairwiseCalculationKey Key to calculate algorithmic pairwise IDs Details pairwiseCalculationSalt Salt to calculate algorithmic pairwise IDs Details pairwiseIdType the pairwise ID type Details parEndpoint URL for Pushed Authorisation Request (PAR) Endpoint Details persistIdToken Specifies whether to persist id_token (otherwise saves into cache) Details persistRefreshToken Specifies whether to persist refresh_token (otherwise saves into cache) Details personCustomObjectClassList This list details LDAP custom object classes for dynamic person enrollment Details publicSubjectIdentifierPerClientEnabled Specifies whether public subject identifier is allowed per client Details redirectUrisRegexEnabled Enable/Disable redirect uris validation using regular expression Details refreshTokenExtendLifetimeOnRotation Boolean value specifying whether to extend refresh tokens on rotation Details refreshTokenLifetime The lifetime of the Refresh Token Details registrationEndpoint Registration endpoint URL Details rejectEndSessionIfIdTokenExpired default value false. If true and id_token is not found in db, request is rejected Details rejectJwtWithNoneAlg Boolean value specifying whether reject JWT requested or validated with algorithm None. Default value is true Details removeRefreshTokensForClientOnLogout Boolean value specifying whether to remove Refresh Tokens on logout. Default value is true Details requestObjectEncryptionAlgValuesSupported A list of the JWE encryption algorithms (alg values) supported by the OP for Request Objects Details requestObjectEncryptionEncValuesSupported A list of the JWE encryption algorithms (enc values) supported by the OP for Request Objects Details requestObjectSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the OP for Request Objects Details requestParameterSupported Boolean value specifying whether the OP supports use of the request parameter Details requestUriBlockList Block list for requestUri that can come to Authorization Endpoint (e.g. localhost) Details requestUriHashVerificationEnabled Boolean value specifying whether the OP supports use of the request_uri hash verification Details requestUriParameterSupported Boolean value specifying whether the OP supports use of the request_uri parameter Details requirePar Boolean value to indicate of Pushed Authorisation Request(PAR)is required Details requirePkce Boolean value true check for Proof Key for Code Exchange (PKCE) Details requireRequestObjectEncryption Boolean value true encrypts request object Details requireRequestUriRegistration Boolean value specifying whether the OP requires any request_uri values used to be pre-registered using the request_uris registration parameter Details responseModesSupported This list details which OAuth 2.0 response modes are supported by this OP Details responseTypesSupported This list details which OAuth 2.0 response_type values are supported by this OP. Details returnClientSecretOnRead Boolean value specifying whether a client_secret is returned on client GET or PUT. Set to true by default which means to return secret Details returnDeviceSecretFromAuthzEndpoint Details rotateClientRegistrationAccessTokenOnUsage Boolean value specifying whether to rotate client registration access token after each usage Details rotateDeviceSecret Details sectorIdentifierCacheLifetimeInMinutes Sector Identifier cache lifetime in minutes Details serverSessionIdLifetime Dedicated property to control lifetime of the server side OP session object in seconds. Overrides sessionIdLifetime. By default value is 0, so object lifetime equals sessionIdLifetime (which sets both cookie and object expiration). It can be useful if goal is to keep different values for client cookie and server object Details serviceDocumentation URL of a page containing human-readable information that developers might want or need to know when using the OpenID Provider Details sessionIdLifetime The lifetime of session id in seconds. If 0 or -1 then expiration is not set. session_id cookie expires when browser session ends Details sessionIdPersistInCache Boolean value specifying whether to persist session_id in cache Details sessionIdPersistOnPromptNone Boolean value specifying whether to persist session ID on prompt none Details sessionIdRequestParameterEnabled Boolean value specifying whether to enable session_id HTTP request parameter Details sessionIdUnauthenticatedUnusedLifetime The lifetime for unused unauthenticated session states Details sessionIdUnusedLifetime The lifetime for unused session states Details shareSubjectIdBetweenClientsWithSameSectorId When true, clients with the same Sector ID also share the same Subject ID Details skipAuthenticationFilterOptionsMethod Force Authentication Filtker to process OPTIONS request Details skipAuthorizationForOpenIdScopeAndPairwiseId Choose whether to skip authorization if a client has an OpenId scope and a pairwise ID Details skipRefreshTokenDuringRefreshing Boolean value specifying whether to skip refreshing tokens on refreshing Details softwareStatementValidationClaimName Validation claim name for software statement Details softwareStatementValidationType Validation type used for software statement Details spontaneousScopeLifetime The lifetime of spontaneous scope in seconds Details ssaConfiguration SSA Configuration Details statAuthorizationScope Scope required for Statistical Authorization Details staticDecryptionKid Specifies static decryption Kid Details staticKid Specifies static Kid Details statTimerIntervalInSeconds Statistical data capture time interval Details subjectIdentifiersPerClientSupported A list of the subject identifiers supported per client Details subjectTypesSupported This list details which Subject Identifier types that the OP supports. Valid types include pairwise and public. Details tokenEndpoint The token endpoint URL Details tokenEndpointAuthMethodsSupported A list of Client Authentication methods supported by this Token Endpoint Details tokenEndpointAuthSigningAlgValuesSupported A list of the JWS signing algorithms (alg values) supported by the Token Endpoint for the signature on the JWT used to authenticate the Client at the Token Endpoint for the private_key_jwt and client_secret_jwt authentication methods Details tokenRevocationEndpoint The URL for the access_token or refresh_token revocation endpoint Details trustedClientEnabled Boolean value specifying whether a client is trusted and no authorization is required Details trustedSsaIssuers List of trusted SSA issuers with configuration (e.g. automatically granted scopes). Details uiLocalesSupported This list details the languages and scripts supported for the user interface Details umaAddScopesAutomatically Add UMA scopes automatically if it is not registered yet Details umaConfigurationEndpoint UMA Configuration endpoint URL Details umaGrantAccessIfNoPolicies Specify whether to grant access to resources if there is no any policies associated with scopes Details umaPctLifetime UMA PCT lifetime Details umaResourceLifetime UMA Resource lifetime Details umaRestrictResourceToAssociatedClient Restrict access to resource by associated client Details umaRptAsJwt Issue RPT as JWT or as random string Details umaRptLifetime UMA RPT lifetime Details umaTicketLifetime UMA ticket lifetime Details umaValidateClaimToken Validate claim_token as id_token assuming it is issued by local id Details updateClientAccessTime Choose if application should update oxLastAccessTime/oxLastLogonTime attributes upon client authentication Details updateUserLastLogonTime Choose if application should update oxLastLogonTime attribute upon user authentication Details useHighestLevelScriptIfAcrScriptNotFound Enable/Disable usage of highest level script in case ACR script does not exist Details useLocalCache Cache in local memory cache attributes, scopes, clients and organization entry with expiration 60 seconds Details useNestedJwtDuringEncryption Boolean value specifying whether to use nested Jwt during encryption Details userInfoEncryptionAlgValuesSupported This JSON Array lists which JWS encryption algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details userInfoEncryptionEncValuesSupported This JSON Array lists which JWS encryption algorithms (enc values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details userInfoEndpoint The User Info endpoint URL Details userInfoSigningAlgValuesSupported This JSON Array lists which JWS signing algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Details webKeysStorage Web Key Storage Type Details", "title": "Janssen Auth Server Configuration Properties"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#accesstokenlifetime", "text": "Description: The lifetime of the short lived Access Token Required: No Default value: None", "title": "accessTokenLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#accesstokensigningalgvaluessupported", "text": "Description: A list of the JWS signing algorithms (alg values) supported by the OP for the access token to encode the Claims in a JWT Required: No Default value: None", "title": "accessTokenSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#activesessionauthorizationscope", "text": "Description: Authorization Scope for active session Required: No Default value: None", "title": "activeSessionAuthorizationScope"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#agamaconfiguration", "text": "Description: Engine Config which offers an alternative way to build authentication flows in Janssen server Required: No Default value: None", "title": "agamaConfiguration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowallvalueforrevokeendpoint", "text": "Description: Boolean value true allow all value for revoke endpoint Required: No Default value: false", "title": "allowAllValueForRevokeEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowblankvaluesindiscoveryresponse", "text": "Description: Boolean value specifying whether to allow blank values in discovery response Required: No Default value: false", "title": "allowBlankValuesInDiscoveryResponse"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowendsessionwithunmatchedsid", "text": "Description: default value false. If true, sid check will be skipped Required: No Default value: false", "title": "allowEndSessionWithUnmatchedSid"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowidtokenwithoutimplicitgranttype", "text": "Description: Specifies if a token without implicit grant types is allowed Required: No Default value: None", "title": "allowIdTokenWithoutImplicitGrantType"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowpostlogoutredirectwithoutvalidation", "text": "Description: Allows post-logout redirect without validation for the End Session endpoint (still AS validates it against clientWhiteList url pattern property) Required: No Default value: false", "title": "allowPostLogoutRedirectWithoutValidation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#allowspontaneousscopes", "text": "Description: Specifies whether to allow spontaneous scopes Required: No Default value: None", "title": "allowSpontaneousScopes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authenticationfilters", "text": "Description: This list details filters for user authentication Required: No Default value: None", "title": "authenticationFilters"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authenticationfiltersenabled", "text": "Description: Boolean value specifying whether to enable user authentication filters Required: No Default value: None", "title": "authenticationFiltersEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authenticationprotectionconfiguration", "text": "Description: Authentication Brute Force Protection Configuration Required: No Default value: None", "title": "authenticationProtectionConfiguration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationcodelifetime", "text": "Description: The lifetime of the Authorization Code Required: No Default value: None", "title": "authorizationCodeLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationencryptionalgvaluessupported", "text": "Description: List of authorization encryption algorithms supported by this OP Required: No Default value: None", "title": "authorizationEncryptionAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationencryptionencvaluessupported", "text": "Description: A list of the authorization encryption algorithms supported Required: No Default value: None", "title": "authorizationEncryptionEncValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationendpoint", "text": "Description: The authorization endpoint URL Required: No Default value: None", "title": "authorizationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationrequestcustomallowedparameters", "text": "Description: This list details the allowed custom parameters for authorization requests Required: No Default value: None", "title": "authorizationRequestCustomAllowedParameters"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#authorizationsigningalgvaluessupported", "text": "Description: List of authorization signing algorithms supported by this OP Required: No Default value: None", "title": "authorizationSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelauthenticationendpoint", "text": "Description: Backchannel Authentication Endpoint Required: No Default value: None", "title": "backchannelAuthenticationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelauthenticationrequestsigningalgvaluessupported", "text": "Description: Backchannel Authentication Request Signing Alg Values Supported Required: No Default value: None", "title": "backchannelAuthenticationRequestSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelauthenticationresponseexpiresin", "text": "Description: Backchannel Authentication Response Expires In Required: No Default value: None", "title": "backchannelAuthenticationResponseExpiresIn"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelauthenticationresponseinterval", "text": "Description: Backchannel Authentication Response Interval Required: No Default value: None", "title": "backchannelAuthenticationResponseInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelbindingmessagepattern", "text": "Description: Backchannel Binding Message Pattern Required: No Default value: None", "title": "backchannelBindingMessagePattern"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelclientid", "text": "Description: Backchannel Client Id Required: No Default value: None", "title": "backchannelClientId"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchanneldeviceregistrationendpoint", "text": "Description: Backchannel Device Registration Endpoint Required: No Default value: None", "title": "backchannelDeviceRegistrationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelloginhintclaims", "text": "Description: Backchannel Login Hint Claims Required: No Default value: None", "title": "backchannelLoginHintClaims"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelredirecturi", "text": "Description: Backchannel Redirect Uri Required: No Default value: None", "title": "backchannelRedirectUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelrequestsprocessorjobchunksize", "text": "Description: Each backchannel request processor iteration fetches chunk of data to be processed Required: No Default value: None", "title": "backchannelRequestsProcessorJobChunkSize"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelrequestsprocessorjobintervalsec", "text": "Description: Specifies the allowable elapsed time in seconds backchannel request processor executes Required: No Default value: None", "title": "backchannelRequestsProcessorJobIntervalSec"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchanneltokendeliverymodessupported", "text": "Description: Backchannel Token Delivery Modes Supported Required: No Default value: None", "title": "backchannelTokenDeliveryModesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#backchannelusercodeparametersupported", "text": "Description: Backchannel User Code Parameter Supported Required: No Default value: None", "title": "backchannelUserCodeParameterSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#baseendpoint", "text": "Description: The base URL for endpoints Required: No Default value: None", "title": "baseEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#blockwebviewauthorizationenabled", "text": "Description: Enable/Disable block authorizations that originate from Webview (Mobile apps). Required: No Default value: false", "title": "blockWebviewAuthorizationEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#changesessionidonauthentication", "text": "Description: Boolean value specifying whether change session_id on authentication. Default value is true Required: No Default value: true", "title": "changeSessionIdOnAuthentication"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#checksessioniframe", "text": "Description: URL for an OP IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Required: No Default value: None", "title": "checkSessionIFrame"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#checkuserpresenceonrefreshtoken", "text": "Description: Check whether user exists and is active before creating RefreshToken. Set it to true if check is needed(Default value is false - don't check. Required: No Default value: false", "title": "checkUserPresenceOnRefreshToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cibaendusernotificationconfig", "text": "Description: CIBA End User Notification Config Required: No Default value: None", "title": "cibaEndUserNotificationConfig"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cibagrantlifeextratimesec", "text": "Description: Specifies the CIBA Grant life extra time in seconds Required: No Default value: None", "title": "cibaGrantLifeExtraTimeSec"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cibamaxexpirationtimeallowedsec", "text": "Description: Specifies the CIBA token expiration time in seconds Required: No Default value: None", "title": "cibaMaxExpirationTimeAllowedSec"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#claimslocalessupported", "text": "Description: This list details the languages and scripts supported for values in the claims being returned Required: No Default value: None", "title": "claimsLocalesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#claimsparametersupported", "text": "Description: Specifies whether the OP supports use of the claims parameter Required: No Default value: None", "title": "claimsParameterSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#claimtypessupported", "text": "Description: A list of the Claim Types that the OpenID Provider supports Required: No Default value: None", "title": "claimTypesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cleanservicebatchchunksize", "text": "Description: Clean service chunk size which is used during clean up Required: No Default value: 100", "title": "cleanServiceBatchChunkSize"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cleanserviceinterval", "text": "Description: Time interval for the Clean Service in seconds Required: No Default value: None", "title": "cleanServiceInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientauthenticationfilters", "text": "Description: This list details filters for client authentication Required: No Default value: None", "title": "clientAuthenticationFilters"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientauthenticationfiltersenabled", "text": "Description: Boolean value specifying whether to enable client authentication filters Required: No Default value: None", "title": "clientAuthenticationFiltersEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientblacklist", "text": "Description: This list specified which client redirection URIs are black-listed Required: No Default value: None", "title": "clientBlackList"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientinfoendpoint", "text": "Description: The Client Info endpoint URL Required: No Default value: None", "title": "clientInfoEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientregdefaulttocodeflowwithrefresh", "text": "Description: Boolean value specifying whether to add Authorization Code Flow with Refresh grant during client registratio Required: No Default value: None", "title": "clientRegDefaultToCodeFlowWithRefresh"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#clientwhitelist", "text": "Description: This list specifies which client redirection URIs are white-listed Required: No Default value: None", "title": "clientWhiteList"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#configurationupdateinterval", "text": "Description: The interval for configuration update in seconds Required: No Default value: None", "title": "configurationUpdateInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#consentgatheringscriptbackwardcompatibility", "text": "Description: Boolean value specifying whether to turn on Consent Gathering Script backward compatibility mode. If true AS will pick up script with higher level globally. If false (default) AS will pick up script based on client configuration Required: No Default value: false", "title": "consentGatheringScriptBackwardCompatibility"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#cookiedomain", "text": "Description: Sets cookie domain for all cookies created by OP Required: No Default value: None", "title": "cookieDomain"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#corsconfigurationfilters", "text": "Description: This list specifies the CORS configuration filters Required: No Default value: None", "title": "corsConfigurationFilters"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#csslocation", "text": "Description: The location for CSS files Required: No Default value: None", "title": "cssLocation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#customheaderswithauthorizationresponse", "text": "Description: Choose whether to enable the custom response header parameter to return custom headers with the authorization response Required: No Default value: None", "title": "customHeadersWithAuthorizationResponse"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dateformatterpatterns", "text": "Description: List of key value date formatters, e.g. 'userinfo: 'yyyy-MM-dd', etc. Required: No Default value: None", "title": "dateFormatterPatterns"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrauthorizationwithclientcredentials", "text": "Description: Boolean value indicating if DCR authorization to be performed using client credentials Required: No Default value: false", "title": "dcrAuthorizationWithClientCredentials"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrauthorizationwithmtls", "text": "Description: Boolean value indicating if DCR authorization allowed with MTLS Required: No Default value: false", "title": "dcrAuthorizationWithMTLS"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrforbidexpirationtimeinrequest", "text": "Description: Boolean value specifying whether to allow to set client's expiration time in seconds during dynamic registration. Required: No Default value: false", "title": "dcrForbidExpirationTimeInRequest"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationenabled", "text": "Description: Boolean value enables DCR signature validation. Default is false Required: No Default value: false", "title": "dcrSignatureValidationEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationjwks", "text": "Description: Specifies JWKS for all DCR's validations Required: No Default value: None", "title": "dcrSignatureValidationJwks"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationjwksuri", "text": "Description: Specifies JWKS URI for all DCR's validations Required: No Default value: None", "title": "dcrSignatureValidationJwksUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationsharedsecret", "text": "Description: Specifies shared secret for Dynamic Client Registration Required: No Default value: None", "title": "dcrSignatureValidationSharedSecret"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationsoftwarestatementjwksclaim", "text": "Description: Specifies claim name inside software statement. Value of claim should point to inlined JWKS Required: No Default value: None", "title": "dcrSignatureValidationSoftwareStatementJwksClaim"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrsignaturevalidationsoftwarestatementjwksuriclaim", "text": "Description: Specifies claim name inside software statement. Value of claim should point to JWKS URI Required: No Default value: None", "title": "dcrSignatureValidationSoftwareStatementJwksURIClaim"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dcrssavalidationconfigs", "text": "Description: DCR SSA Validation configurations used to perform validation of SSA or DCR Required: No Default value: None", "title": "dcrSsaValidationConfigs"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#defaultsignaturealgorithm", "text": "Description: The default signature algorithm to sign ID Tokens Required: No Default value: None", "title": "defaultSignatureAlgorithm"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#defaultsubjecttype", "text": "Description: The default subject type used for dynamic client registration Required: No Default value: None", "title": "defaultSubjectType"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#deviceauthzacr", "text": "Description: Device authz acr Required: No Default value: None", "title": "deviceAuthzAcr"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#deviceauthzendpoint", "text": "Description: URL for the Device Authorization Required: No Default value: None", "title": "deviceAuthzEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#deviceauthzrequestexpiresin", "text": "Description: Expiration time given for device authorization requests Required: No Default value: None", "title": "deviceAuthzRequestExpiresIn"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#deviceauthzresponsetypetoprocessauthz", "text": "Description: Response type used to process device authz requests Required: No Default value: None", "title": "deviceAuthzResponseTypeToProcessAuthz"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#deviceauthztokenpollinterval", "text": "Description: Default interval returned to the client to process device token requests Required: No Default value: None", "title": "deviceAuthzTokenPollInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#disableauthnformaxagezero", "text": "Description: Boolean value specifying whether to disable authentication when max_age=0 Required: No Default value: false", "title": "disableAuthnForMaxAgeZero"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#disablejdklogger", "text": "Description: Choose whether to disable JDK loggers Required: No Default value: true", "title": "disableJdkLogger"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#disablepromptconsent", "text": "Description: Boolean value specifying whether to disable prompt=consent Required: No Default value: false", "title": "disablePromptConsent"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#disablepromptlogin", "text": "Description: Boolean value specifying whether to disable prompt=login Required: No Default value: false", "title": "disablePromptLogin"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#disableu2fendpoint", "text": "Description: Choose whether to disable U2F endpoints Required: No Default value: false", "title": "disableU2fEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#discoveryallowedkeys", "text": "Description: List of configuration response claim allowed to be displayed in discovery endpoint Required: No Default value: None", "title": "discoveryAllowedKeys"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#discoverycachelifetimeinminutes", "text": "Description: Lifetime of discovery cache Required: No Default value: 60", "title": "discoveryCacheLifetimeInMinutes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#discoverydenykeys", "text": "Description: List of configuration response claims which must not be displayed in discovery endpoint response Required: No Default value: None", "title": "discoveryDenyKeys"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#displayvaluessupported", "text": "Description: A list of the display parameter values that the OpenID Provider supports Required: No Default value: None", "title": "displayValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dnname", "text": "Description: DN of certificate issuer Required: No Default value: None", "title": "dnName"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dpopjticachetime", "text": "Description: Demonstration of Proof-of-Possession (DPoP) cache time Required: No Default value: 3600", "title": "dpopJtiCacheTime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dpopnoncecachetime", "text": "Description: Demonstration of Proof-of-Possession (DPoP) nonce cache time Required: No Default value: 3600", "title": "dpopNonceCacheTime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dpopsigningalgvaluessupported", "text": "Description: Demonstration of Proof-of-Possession (DPoP) authorization signing algorithms supported Required: No Default value: None", "title": "dpopSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dpoptimeframe", "text": "Description: Demonstration of Proof-of-Possession (DPoP) timeout Required: No Default value: 5", "title": "dpopTimeframe"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dpopusenonce", "text": "Description: Demonstration of Proof-of-Possession (DPoP) use nonce Required: No Default value: false", "title": "dpopUseNonce"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#granttypessupportedbydynamicregistration", "text": "Description: This list details which OAuth 2.0 grant types can be set up with the client registration API Required: No Default value: None", "title": "grantTypesSupportedByDynamicRegistration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationallowedpasswordgrantscopes", "text": "Description: List of grant scopes for dynamic registration Required: No Default value: None", "title": "dynamicRegistrationAllowedPasswordGrantScopes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationcustomattributes", "text": "Description: This list details the custom attributes allowed for dynamic registration Required: No Default value: None", "title": "dynamicRegistrationCustomAttributes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationcustomobjectclass", "text": "Description: LDAP custom object class for dynamic registration Required: No Default value: None", "title": "dynamicRegistrationCustomObjectClass"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationdefaultcustomattributes", "text": "Description: This map provides default custom attributes with values for dynamic registration Required: No Default value: None", "title": "dynamicRegistrationDefaultCustomAttributes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationexpirationtime", "text": "Description: Expiration time in seconds for clients created with dynamic registration, 0 or -1 means never expire Required: No Default value: -1", "title": "dynamicRegistrationExpirationTime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationpasswordgranttypeenabled", "text": "Description: Boolean value specifying whether to enable Password Grant Type during Dynamic Registration Required: No Default value: false", "title": "dynamicRegistrationPasswordGrantTypeEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationpersistclientauthorizations", "text": "Description: Boolean value specifying whether to persist client authorizations Required: No Default value: None", "title": "dynamicRegistrationPersistClientAuthorizations"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#dynamicregistrationscopesparamenabled", "text": "Description: Boolean value specifying whether to enable scopes parameter in dynamic registration Required: No Default value: None", "title": "dynamicRegistrationScopesParamEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#enableclientgranttypeupdate", "text": "Description: Choose if client can update Grant Type values Required: No Default value: None", "title": "enableClientGrantTypeUpdate"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#enabledoauthauditlogging", "text": "Description: enable OAuth Audit Logging Required: No Default value: None", "title": "enabledOAuthAuditLogging"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#endsessionendpoint", "text": "Description: URL at the OP to which an RP can perform a redirect to request that the end user be logged out at the OP Required: No Default value: None", "title": "endSessionEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#endsessionwithaccesstoken", "text": "Description: Choose whether to accept access tokens to call end_session endpoint Required: No Default value: None", "title": "endSessionWithAccessToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#errorhandlingmethod", "text": "Description: A list of possible error handling methods. Possible values: remote (send error back to RP), internal (show error page) Required: No Default value: remote", "title": "errorHandlingMethod"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#errorreasonenabled", "text": "Description: Boolean value specifying whether to return detailed reason of the error from AS. Default value is false Required: No Default value: false", "title": "errorReasonEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#expirationnotificatorenabled", "text": "Description: Boolean value specifying whether expiration notificator is enabled (used to identify expiration for persistence that support TTL, like Couchbase) Required: No Default value: false", "title": "expirationNotificatorEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#expirationnotificatorintervalinseconds", "text": "Description: The expiration notificator interval in second Required: No Default value: None", "title": "expirationNotificatorIntervalInSeconds"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#expirationnotificatormapsizelimit", "text": "Description: The expiration notificator maximum size limit Required: No Default value: None", "title": "expirationNotificatorMapSizeLimit"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#externalloggerconfiguration", "text": "Description: The path to the external log4j2 logging configuration Required: No Default value: None", "title": "externalLoggerConfiguration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#externaluriwhitelist", "text": "Description: This list specifies which external URIs can be called by AS (if empty any URI can be called) Required: No Default value: None", "title": "externalUriWhiteList"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#fapicompatibility", "text": "Description: Boolean value specifying whether to turn on FAPI compatibility mode. If true AS behaves in more strict mode Required: No Default value: false", "title": "fapiCompatibility"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#featureflags", "text": "Description: List of enabled feature flags Required: No Default value: None", "title": "featureFlags"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#forceidtokenhintpresence", "text": "Description: Boolean value specifying whether force id_token_hint parameter presence Required: No Default value: false", "title": "forceIdTokenHintPresence"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#forceofflineaccessscopetoenablerefreshtoken", "text": "Description: Boolean value specifying whether force offline_access scope to enable refresh_token grant type. Default value is true Required: No Default value: true", "title": "forceOfflineAccessScopeToEnableRefreshToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#forcesignedrequestobject", "text": "Description: Boolean value true indicates that signed request object is mandatory Required: No Default value: false", "title": "forceSignedRequestObject"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#frontchannellogoutsessionsupported", "text": "Description: Choose whether to support front channel session logout Required: No Default value: None", "title": "frontChannelLogoutSessionSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#granttypesandresponsetypesautofixenabled", "text": "Description: Boolean value specifying whether to Grant types and Response types can be auto fixed Required: No Default value: None", "title": "grantTypesAndResponseTypesAutofixEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#granttypessupported", "text": "Description: This list details which OAuth 2.0 grant types are supported by this OP Required: No Default value: None", "title": "grantTypesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#httploggingenabled", "text": "Description: Enable/disable request/response logging filter Required: No Default value: None", "title": "httpLoggingEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#httploggingexcludepaths", "text": "Description: This list details the base URIs for which the request/response logging filter will not record activity Required: No Default value: None", "title": "httpLoggingExcludePaths"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#httploggingresponsebodycontent", "text": "Description: Defines if Response body will be logged. Default value is false Required: No Default value: false", "title": "httpLoggingResponseBodyContent"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idgenerationendpoint", "text": "Description: ID Generation endpoint URL Required: No Default value: None", "title": "idGenerationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokenencryptionalgvaluessupported", "text": "Description: A list of the JWE encryption algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None", "title": "idTokenEncryptionAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokenencryptionencvaluessupported", "text": "Description: A list of the JWE encryption algorithms (enc values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None", "title": "idTokenEncryptionEncValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokenfilterclaimsbasedonaccesstoken", "text": "Description: Boolean value specifying whether idToken filters claims based on accessToken Required: No Default value: None", "title": "idTokenFilterClaimsBasedOnAccessToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokenlifetime", "text": "Description: The lifetime of the ID Token Required: No Default value: None", "title": "idTokenLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokensigningalgvaluessupported", "text": "Description: A list of the JWS signing algorithms (alg values) supported by the OP for the ID Token to encode the Claims in a JWT Required: No Default value: None", "title": "idTokenSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#idtokentokenbindingcnfvaluessupported", "text": "Description: Array containing a list of the JWT Confirmation Method member names supported by the OP for Token Binding of ID Tokens. The presence of this parameter indicates that the OpenID Provider supports Token Binding of ID Tokens. If omitted, the default is that the OpenID Provider does not support Token Binding of ID Tokens Required: No Default value: None", "title": "idTokenTokenBindingCnfValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#imglocation", "text": "Description: The location for image files Required: No Default value: None", "title": "imgLocation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#includesidinresponse", "text": "Description: Boolean value specifying whether to include sessionId in response Required: No Default value: false", "title": "includeSidInResponse"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionaccesstokenmusthaveintrospectionscope", "text": "Description: If True, rejects introspection requests if access_token does not have the 'introspection' scope in its authorization header. Comparing to 'uma_protection', 'introspection' scope is not allowed for dynamic registration' Required: No Default value: false", "title": "introspectionAccessTokenMustHaveIntrospectionScope"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionaccesstokenmusthaveumaprotectionscope", "text": "Description: If True, rejects introspection requests if access_token does not have the uma_protection scope in its authorization header Required: No Default value: false", "title": "introspectionAccessTokenMustHaveUmaProtectionScope"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionendpoint", "text": "Description: Introspection endpoint URL Required: No Default value: None", "title": "introspectionEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionresponsescopesbackwardcompatibility", "text": "Description: Boolean value specifying introspection response backward compatibility mode Required: No Default value: false", "title": "introspectionResponseScopesBackwardCompatibility"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionscriptbackwardcompatibility", "text": "Description: Boolean value specifying whether switch off client's introspection scripts (true value) and run all scripts that exists on server. Default value is false Required: No Default value: false", "title": "introspectionScriptBackwardCompatibility"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#introspectionskipauthorization", "text": "Description: Specifies if authorization to be skipped for introspection Required: No Default value: None", "title": "introspectionSkipAuthorization"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#invalidatesessioncookiesafterauthorizationflow", "text": "Description: Boolean value to specify whether to invalidate session_id and consent_session_id cookies right after successful or unsuccessful authorization Required: No Default value: false", "title": "invalidateSessionCookiesAfterAuthorizationFlow"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#issuer", "text": "Description: URL using the https scheme that OP asserts as Issuer identifier Required: No Default value: None", "title": "issuer"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jansid", "text": "Description: URL for the Inum generator Service Required: No Default value: None", "title": "jansId"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jansopenidconnectversion", "text": "Description: OpenID Connect Version Required: No Default value: None", "title": "jansOpenIdConnectVersion"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jmsbrokeruriset", "text": "Description: JMS Broker URI Set Required: No Default value: None", "title": "jmsBrokerURISet"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jmspassword", "text": "Description: JMS Password Required: No Default value: None", "title": "jmsPassword"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jmsusername", "text": "Description: JMS UserName Required: No Default value: None", "title": "jmsUserName"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jslocation", "text": "Description: The location for JavaScript files Required: No Default value: None", "title": "jsLocation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jwksalgorithmssupported", "text": "Description: A list of algorithms that will be used in JWKS endpoint Required: No Default value: None", "title": "jwksAlgorithmsSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#jwksuri", "text": "Description: URL of the OP's JSON Web Key Set (JWK) document. This contains the signing key(s) the RP uses to validate signatures from the OP Required: No Default value: None", "title": "jwksUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keepauthenticatorattributesonacrchange", "text": "Description: Boolean value specifying whether to keep authenticator attributes on ACR change Required: No Default value: false", "title": "keepAuthenticatorAttributesOnAcrChange"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keyalgsallowedforgeneration", "text": "Description: List of algorithm allowed to be used for key generation Required: No Default value: None", "title": "keyAlgsAllowedForGeneration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keyregenerationenabled", "text": "Description: Boolean value specifying whether to regenerate keys Required: No Default value: None", "title": "keyRegenerationEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keyregenerationinterval", "text": "Description: The interval for key regeneration in hours Required: No Default value: None", "title": "keyRegenerationInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keyselectionstrategy", "text": "Description: Key Selection Strategy : OLDER, NEWER, FIRST Required: No Default value: OLDER", "title": "keySelectionStrategy"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keysignwithsamekeybutdiffalg", "text": "Description: Specifies if signing to be done with same key but apply different algorithms Required: No Default value: None", "title": "keySignWithSameKeyButDiffAlg"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keystorefile", "text": "Description: The Key Store File (JKS) Required: No Default value: None", "title": "keyStoreFile"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#keystoresecret", "text": "Description: The Key Store password Required: No Default value: None", "title": "keyStoreSecret"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#legacyidtokenclaims", "text": "Description: Choose whether to include claims in ID tokens Required: No Default value: None", "title": "legacyIdTokenClaims"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#logclientidonclientauthentication", "text": "Description: Choose if application should log the Client ID on client authentication Required: No Default value: None", "title": "logClientIdOnClientAuthentication"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#logclientnameonclientauthentication", "text": "Description: Choose if application should log the Client Name on client authentication Required: No Default value: None", "title": "logClientNameOnClientAuthentication"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#logginglayout", "text": "Description: Logging layout used for Jans Authorization Server loggers Required: No Default value: None", "title": "loggingLayout"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#logginglevel", "text": "Description: Specify the logging level of loggers Required: No Default value: None", "title": "loggingLevel"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#lognotfoundentityaserror", "text": "Description: Boolean value specifying whether to log not_found entity exception as error or as trace. Default value is false (trace). Required: No Default value: None", "title": "logNotFoundEntityAsError"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#metricreporterinterval", "text": "Description: The interval for metric reporter in seconds Required: No Default value: None", "title": "metricReporterInterval"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#metricreporterkeepdatadays", "text": "Description: The days to keep metric reported data Required: No Default value: None", "title": "metricReporterKeepDataDays"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsauthorizationendpoint", "text": "Description: URL for Mutual TLS (mTLS) Client Authentication and Certificate-Bound Access Tokens (MTLS) Endpoint Required: No Default value: None", "title": "mtlsAuthorizationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlschecksessioniframe", "text": "Description: URL for Mutual TLS (mTLS) IFrame that supports cross-origin communications for session state information with the RP Client using the HTML5 postMessage API Required: No Default value: None", "title": "mtlsCheckSessionIFrame"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsclientinfoendpoint", "text": "Description: URL for Mutual TLS (mTLS) Client Info endpoint Required: No Default value: None", "title": "mtlsClientInfoEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsdeviceauthzendpoint", "text": "Description: Mutual TLS (mTLS) device authorization endpoint URL Required: No Default value: None", "title": "mtlsDeviceAuthzEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsendsessionendpoint", "text": "Description: URL for Mutual TLS (mTLS) to which an RP can perform a redirect to request that the end user be logged out at the OP Required: No Default value: None", "title": "mtlsEndSessionEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsidgenerationendpoint", "text": "Description: Mutual TLS (mTLS) ID generation endpoint URL Required: No Default value: None", "title": "mtlsIdGenerationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsintrospectionendpoint", "text": "Description: Mutual TLS (mTLS) introspection endpoint URL Required: No Default value: None", "title": "mtlsIntrospectionEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsjwksuri", "text": "Description: URL for Mutual TLS (mTLS) of the OP's JSON Web Key Set (JWK) document Required: No Default value: None", "title": "mtlsJwksUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsparendpoint", "text": "Description: Mutual TLS (mTLS) Pushed Authorization Requests(PAR) endpoint URL Required: No Default value: None", "title": "mtlsParEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsregistrationendpoint", "text": "Description: Mutual TLS (mTLS) registration endpoint URL Required: No Default value: None", "title": "mtlsRegistrationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlstokenendpoint", "text": "Description: URL for Mutual TLS (mTLS) Authorization token Endpoint Required: No Default value: None", "title": "mtlsTokenEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlstokenrevocationendpoint", "text": "Description: URL for Mutual TLS (mTLS) Authorization token revocation endpoint Required: No Default value: None", "title": "mtlsTokenRevocationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#mtlsuserinfoendpoint", "text": "Description: Mutual TLS (mTLS) user info endpoint URL Required: No Default value: None", "title": "mtlsUserInfoEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#openidconfigurationendpoint", "text": "Description: URL for the Open ID Connect Configuration Endpoint Required: No Default value: None", "title": "openIdConfigurationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#openiddiscoveryendpoint", "text": "Description: Discovery endpoint URL Required: No Default value: None", "title": "openIdDiscoveryEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#openidscopebackwardcompatibility", "text": "Description: Set to false to only allow token endpoint request for openid scope with grant type equals to authorization_code, restrict access to userinfo to scope openid and only return id_token if scope contains openid Required: No Default value: false", "title": "openidScopeBackwardCompatibility"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#openidsubattribute", "text": "Description: Specifies which LDAP attribute is used for the subject identifier claim Required: No Default value: None", "title": "openidSubAttribute"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#oppolicyuri", "text": "Description: URL that the OpenID Provider provides to the person registering the Client to read about the OP's requirements on how the Relying Party can use the data provided by the OP Required: No Default value: None", "title": "opPolicyUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#optosuri", "text": "Description: URL that the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service Required: No Default value: None", "title": "opTosUri"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#pairwisecalculationkey", "text": "Description: Key to calculate algorithmic pairwise IDs Required: No Default value: None", "title": "pairwiseCalculationKey"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#pairwisecalculationsalt", "text": "Description: Salt to calculate algorithmic pairwise IDs Required: No Default value: None", "title": "pairwiseCalculationSalt"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#pairwiseidtype", "text": "Description: the pairwise ID type Required: No Default value: None", "title": "pairwiseIdType"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#parendpoint", "text": "Description: URL for Pushed Authorisation Request (PAR) Endpoint Required: No Default value: None", "title": "parEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#persistidtoken", "text": "Description: Specifies whether to persist id_token (otherwise saves into cache) Required: No Default value: false", "title": "persistIdToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#persistrefreshtoken", "text": "Description: Specifies whether to persist refresh_token (otherwise saves into cache) Required: No Default value: true", "title": "persistRefreshToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#personcustomobjectclasslist", "text": "Description: This list details LDAP custom object classes for dynamic person enrollment Required: No Default value: None", "title": "personCustomObjectClassList"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#publicsubjectidentifierperclientenabled", "text": "Description: Specifies whether public subject identifier is allowed per client Required: No Default value: false", "title": "publicSubjectIdentifierPerClientEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#redirecturisregexenabled", "text": "Description: Enable/Disable redirect uris validation using regular expression Required: No Default value: false", "title": "redirectUrisRegexEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#refreshtokenextendlifetimeonrotation", "text": "Description: Boolean value specifying whether to extend refresh tokens on rotation Required: No Default value: false", "title": "refreshTokenExtendLifetimeOnRotation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#refreshtokenlifetime", "text": "Description: The lifetime of the Refresh Token Required: No Default value: None", "title": "refreshTokenLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#registrationendpoint", "text": "Description: Registration endpoint URL Required: No Default value: None", "title": "registrationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#rejectendsessionifidtokenexpired", "text": "Description: default value false. If true and id_token is not found in db, request is rejected Required: No Default value: false", "title": "rejectEndSessionIfIdTokenExpired"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#rejectjwtwithnonealg", "text": "Description: Boolean value specifying whether reject JWT requested or validated with algorithm None. Default value is true Required: No Default value: true", "title": "rejectJwtWithNoneAlg"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#removerefreshtokensforclientonlogout", "text": "Description: Boolean value specifying whether to remove Refresh Tokens on logout. Default value is true Required: No Default value: true", "title": "removeRefreshTokensForClientOnLogout"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requestobjectencryptionalgvaluessupported", "text": "Description: A list of the JWE encryption algorithms (alg values) supported by the OP for Request Objects Required: No Default value: None", "title": "requestObjectEncryptionAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requestobjectencryptionencvaluessupported", "text": "Description: A list of the JWE encryption algorithms (enc values) supported by the OP for Request Objects Required: No Default value: None", "title": "requestObjectEncryptionEncValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requestobjectsigningalgvaluessupported", "text": "Description: A list of the JWS signing algorithms (alg values) supported by the OP for Request Objects Required: No Default value: None", "title": "requestObjectSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requestparametersupported", "text": "Description: Boolean value specifying whether the OP supports use of the request parameter Required: No Default value: None", "title": "requestParameterSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requesturiblocklist", "text": "Description: Block list for requestUri that can come to Authorization Endpoint (e.g. localhost) Required: No Default value: None", "title": "requestUriBlockList"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requesturihashverificationenabled", "text": "Description: Boolean value specifying whether the OP supports use of the request_uri hash verification Required: No Default value: None", "title": "requestUriHashVerificationEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requesturiparametersupported", "text": "Description: Boolean value specifying whether the OP supports use of the request_uri parameter Required: No Default value: None", "title": "requestUriParameterSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requirepar", "text": "Description: Boolean value to indicate of Pushed Authorisation Request(PAR)is required Required: No Default value: false", "title": "requirePar"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requirepkce", "text": "Description: Boolean value true check for Proof Key for Code Exchange (PKCE) Required: No Default value: false", "title": "requirePkce"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requirerequestobjectencryption", "text": "Description: Boolean value true encrypts request object Required: No Default value: false", "title": "requireRequestObjectEncryption"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#requirerequesturiregistration", "text": "Description: Boolean value specifying whether the OP requires any request_uri values used to be pre-registered using the request_uris registration parameter Required: No Default value: None", "title": "requireRequestUriRegistration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#responsemodessupported", "text": "Description: This list details which OAuth 2.0 response modes are supported by this OP Required: No Default value: None", "title": "responseModesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#responsetypessupported", "text": "Description: This list details which OAuth 2.0 response_type values are supported by this OP. Required: No Default value: By default, every combination of code, token and id_token is supported.", "title": "responseTypesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#returnclientsecretonread", "text": "Description: Boolean value specifying whether a client_secret is returned on client GET or PUT. Set to true by default which means to return secret Required: No Default value: false", "title": "returnClientSecretOnRead"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#returndevicesecretfromauthzendpoint", "text": "Description: Required: No Default value: false", "title": "returnDeviceSecretFromAuthzEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#rotateclientregistrationaccesstokenonusage", "text": "Description: Boolean value specifying whether to rotate client registration access token after each usage Required: No Default value: false", "title": "rotateClientRegistrationAccessTokenOnUsage"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#rotatedevicesecret", "text": "Description: Required: No Default value: false", "title": "rotateDeviceSecret"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sectoridentifiercachelifetimeinminutes", "text": "Description: Sector Identifier cache lifetime in minutes Required: No Default value: 1440", "title": "sectorIdentifierCacheLifetimeInMinutes"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#serversessionidlifetime", "text": "Description: Dedicated property to control lifetime of the server side OP session object in seconds. Overrides sessionIdLifetime. By default value is 0, so object lifetime equals sessionIdLifetime (which sets both cookie and object expiration). It can be useful if goal is to keep different values for client cookie and server object Required: No Default value: None", "title": "serverSessionIdLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#servicedocumentation", "text": "Description: URL of a page containing human-readable information that developers might want or need to know when using the OpenID Provider Required: No Default value: None", "title": "serviceDocumentation"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidlifetime", "text": "Description: The lifetime of session id in seconds. If 0 or -1 then expiration is not set. session_id cookie expires when browser session ends Required: No Default value: None", "title": "sessionIdLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidpersistincache", "text": "Description: Boolean value specifying whether to persist session_id in cache Required: No Default value: false", "title": "sessionIdPersistInCache"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidpersistonpromptnone", "text": "Description: Boolean value specifying whether to persist session ID on prompt none Required: No Default value: None", "title": "sessionIdPersistOnPromptNone"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidrequestparameterenabled", "text": "Description: Boolean value specifying whether to enable session_id HTTP request parameter Required: No Default value: false", "title": "sessionIdRequestParameterEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidunauthenticatedunusedlifetime", "text": "Description: The lifetime for unused unauthenticated session states Required: No Default value: None", "title": "sessionIdUnauthenticatedUnusedLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sessionidunusedlifetime", "text": "Description: The lifetime for unused session states Required: No Default value: None", "title": "sessionIdUnusedLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#sharesubjectidbetweenclientswithsamesectorid", "text": "Description: When true, clients with the same Sector ID also share the same Subject ID Required: No Default value: false", "title": "shareSubjectIdBetweenClientsWithSameSectorId"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#skipauthenticationfilteroptionsmethod", "text": "Description: Force Authentication Filtker to process OPTIONS request Required: No Default value: true", "title": "skipAuthenticationFilterOptionsMethod"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#skipauthorizationforopenidscopeandpairwiseid", "text": "Description: Choose whether to skip authorization if a client has an OpenId scope and a pairwise ID Required: No Default value: false", "title": "skipAuthorizationForOpenIdScopeAndPairwiseId"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#skiprefreshtokenduringrefreshing", "text": "Description: Boolean value specifying whether to skip refreshing tokens on refreshing Required: No Default value: false", "title": "skipRefreshTokenDuringRefreshing"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#softwarestatementvalidationclaimname", "text": "Description: Validation claim name for software statement Required: No Default value: None", "title": "softwareStatementValidationClaimName"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#softwarestatementvalidationtype", "text": "Description: Validation type used for software statement Required: No Default value: None", "title": "softwareStatementValidationType"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#spontaneousscopelifetime", "text": "Description: The lifetime of spontaneous scope in seconds Required: No Default value: None", "title": "spontaneousScopeLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#ssaconfiguration", "text": "Description: SSA Configuration Required: No Default value: None", "title": "ssaConfiguration"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#statauthorizationscope", "text": "Description: Scope required for Statistical Authorization Required: No Default value: None", "title": "statAuthorizationScope"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#staticdecryptionkid", "text": "Description: Specifies static decryption Kid Required: No Default value: None", "title": "staticDecryptionKid"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#statickid", "text": "Description: Specifies static Kid Required: No Default value: None", "title": "staticKid"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#stattimerintervalinseconds", "text": "Description: Statistical data capture time interval Required: No Default value: None", "title": "statTimerIntervalInSeconds"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#subjectidentifiersperclientsupported", "text": "Description: A list of the subject identifiers supported per client Required: No Default value: None", "title": "subjectIdentifiersPerClientSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#subjecttypessupported", "text": "Description: This list details which Subject Identifier types that the OP supports. Valid types include pairwise and public. Required: No Default value: None", "title": "subjectTypesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#tokenendpoint", "text": "Description: The token endpoint URL Required: No Default value: None", "title": "tokenEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#tokenendpointauthmethodssupported", "text": "Description: A list of Client Authentication methods supported by this Token Endpoint Required: No Default value: None", "title": "tokenEndpointAuthMethodsSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#tokenendpointauthsigningalgvaluessupported", "text": "Description: A list of the JWS signing algorithms (alg values) supported by the Token Endpoint for the signature on the JWT used to authenticate the Client at the Token Endpoint for the private_key_jwt and client_secret_jwt authentication methods Required: No Default value: None", "title": "tokenEndpointAuthSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#tokenrevocationendpoint", "text": "Description: The URL for the access_token or refresh_token revocation endpoint Required: No Default value: None", "title": "tokenRevocationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#trustedclientenabled", "text": "Description: Boolean value specifying whether a client is trusted and no authorization is required Required: No Default value: None", "title": "trustedClientEnabled"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#trustedssaissuers", "text": "Description: List of trusted SSA issuers with configuration (e.g. automatically granted scopes). Required: No Default value: None", "title": "trustedSsaIssuers"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#uilocalessupported", "text": "Description: This list details the languages and scripts supported for the user interface Required: No Default value: None", "title": "uiLocalesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umaaddscopesautomatically", "text": "Description: Add UMA scopes automatically if it is not registered yet Required: No Default value: None", "title": "umaAddScopesAutomatically"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umaconfigurationendpoint", "text": "Description: UMA Configuration endpoint URL Required: No Default value: None", "title": "umaConfigurationEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umagrantaccessifnopolicies", "text": "Description: Specify whether to grant access to resources if there is no any policies associated with scopes Required: No Default value: false", "title": "umaGrantAccessIfNoPolicies"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umapctlifetime", "text": "Description: UMA PCT lifetime Required: No Default value: None", "title": "umaPctLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umaresourcelifetime", "text": "Description: UMA Resource lifetime Required: No Default value: None", "title": "umaResourceLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umarestrictresourcetoassociatedclient", "text": "Description: Restrict access to resource by associated client Required: No Default value: false", "title": "umaRestrictResourceToAssociatedClient"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umarptasjwt", "text": "Description: Issue RPT as JWT or as random string Required: No Default value: false", "title": "umaRptAsJwt"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umarptlifetime", "text": "Description: UMA RPT lifetime Required: No Default value: None", "title": "umaRptLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umaticketlifetime", "text": "Description: UMA ticket lifetime Required: No Default value: None", "title": "umaTicketLifetime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#umavalidateclaimtoken", "text": "Description: Validate claim_token as id_token assuming it is issued by local id Required: No Default value: false", "title": "umaValidateClaimToken"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#updateclientaccesstime", "text": "Description: Choose if application should update oxLastAccessTime/oxLastLogonTime attributes upon client authentication Required: No Default value: None", "title": "updateClientAccessTime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#updateuserlastlogontime", "text": "Description: Choose if application should update oxLastLogonTime attribute upon user authentication Required: No Default value: None", "title": "updateUserLastLogonTime"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#usehighestlevelscriptifacrscriptnotfound", "text": "Description: Enable/Disable usage of highest level script in case ACR script does not exist Required: No Default value: false", "title": "useHighestLevelScriptIfAcrScriptNotFound"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#uselocalcache", "text": "Description: Cache in local memory cache attributes, scopes, clients and organization entry with expiration 60 seconds Required: No Default value: false", "title": "useLocalCache"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#usenestedjwtduringencryption", "text": "Description: Boolean value specifying whether to use nested Jwt during encryption Required: No Default value: true", "title": "useNestedJwtDuringEncryption"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#userinfoencryptionalgvaluessupported", "text": "Description: This JSON Array lists which JWS encryption algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None", "title": "userInfoEncryptionAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#userinfoencryptionencvaluessupported", "text": "Description: This JSON Array lists which JWS encryption algorithms (enc values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None", "title": "userInfoEncryptionEncValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#userinfoendpoint", "text": "Description: The User Info endpoint URL Required: No Default value: None", "title": "userInfoEndpoint"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#userinfosigningalgvaluessupported", "text": "Description: This JSON Array lists which JWS signing algorithms (alg values) [JWA] can be used by for the UserInfo endpoint to encode the claims in a JWT Required: No Default value: None", "title": "userInfoSigningAlgValuesSupported"}, {"location": "janssen-server/reference/json/properties/janssenauthserver-properties/#webkeysstorage", "text": "Description: Web Key Storage Type Required: No Default value: None", "title": "webKeysStorage"}, {"location": "janssen-server/reference/json/properties/scim-properties/", "tags": ["administration", "reference", "json", "properties"], "text": "SCIM Configuration Properties # Property Name Description applicationUrl Application base URL Details baseDN Application config Base DN Details baseEndpoint SCIM base endpoint URL Details bulkMaxOperations Specifies maximum bulk operations Details bulkMaxPayloadSize Specifies maximum payload size of bulk operations Details disableJdkLogger Boolean value specifying whether to enable JDK Loggers Details externalLoggerConfiguration Path to external log4j2 logging configuration Details loggingLayout Logging layout used for Server loggers Details loggingLevel Logging level for scim logger Details maxCount Maximum number of results per page Details metricReporterEnabled Metric reported data enabled flag Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep metric reported data Details oxAuthIssuer Jans Auth - Issuer identifier Details personCustomObjectClass Person Object Class Details protectionMode SCIM Protection Mode Details useLocalCache Boolean value specifying whether to enable local in-memory cache Details userExtensionSchemaURI User Extension Schema URI Details applicationUrl # Description: Application base URL Required: No Default value: None baseDN # Description: Application config Base DN Required: No Default value: None baseEndpoint # Description: SCIM base endpoint URL Required: No Default value: None bulkMaxOperations # Description: Specifies maximum bulk operations Required: No Default value: None bulkMaxPayloadSize # Description: Specifies maximum payload size of bulk operations Required: No Default value: None disableJdkLogger # Description: Boolean value specifying whether to enable JDK Loggers Required: No Default value: None externalLoggerConfiguration # Description: Path to external log4j2 logging configuration Required: No Default value: None loggingLayout # Description: Logging layout used for Server loggers Required: No Default value: None loggingLevel # Description: Logging level for scim logger Required: No Default value: None maxCount # Description: Maximum number of results per page Required: No Default value: None metricReporterEnabled # Description: Metric reported data enabled flag Required: No Default value: None metricReporterInterval # Description: The interval for metric reporter in seconds Required: No Default value: None metricReporterKeepDataDays # Description: The days to keep metric reported data Required: No Default value: None oxAuthIssuer # Description: Jans Auth - Issuer identifier Required: No Default value: None personCustomObjectClass # Description: Person Object Class Required: No Default value: None protectionMode # Description: SCIM Protection Mode Required: No Default value: None useLocalCache # Description: Boolean value specifying whether to enable local in-memory cache Required: No Default value: None userExtensionSchemaURI # Description: User Extension Schema URI Required: No Default value: None", "title": "SCIM"}, {"location": "janssen-server/reference/json/properties/scim-properties/#scim-configuration-properties", "text": "Property Name Description applicationUrl Application base URL Details baseDN Application config Base DN Details baseEndpoint SCIM base endpoint URL Details bulkMaxOperations Specifies maximum bulk operations Details bulkMaxPayloadSize Specifies maximum payload size of bulk operations Details disableJdkLogger Boolean value specifying whether to enable JDK Loggers Details externalLoggerConfiguration Path to external log4j2 logging configuration Details loggingLayout Logging layout used for Server loggers Details loggingLevel Logging level for scim logger Details maxCount Maximum number of results per page Details metricReporterEnabled Metric reported data enabled flag Details metricReporterInterval The interval for metric reporter in seconds Details metricReporterKeepDataDays The days to keep metric reported data Details oxAuthIssuer Jans Auth - Issuer identifier Details personCustomObjectClass Person Object Class Details protectionMode SCIM Protection Mode Details useLocalCache Boolean value specifying whether to enable local in-memory cache Details userExtensionSchemaURI User Extension Schema URI Details", "title": "SCIM Configuration Properties"}, {"location": "janssen-server/reference/json/properties/scim-properties/#applicationurl", "text": "Description: Application base URL Required: No Default value: None", "title": "applicationUrl"}, {"location": "janssen-server/reference/json/properties/scim-properties/#basedn", "text": "Description: Application config Base DN Required: No Default value: None", "title": "baseDN"}, {"location": "janssen-server/reference/json/properties/scim-properties/#baseendpoint", "text": "Description: SCIM base endpoint URL Required: No Default value: None", "title": "baseEndpoint"}, {"location": "janssen-server/reference/json/properties/scim-properties/#bulkmaxoperations", "text": "Description: Specifies maximum bulk operations Required: No Default value: None", "title": "bulkMaxOperations"}, {"location": "janssen-server/reference/json/properties/scim-properties/#bulkmaxpayloadsize", "text": "Description: Specifies maximum payload size of bulk operations Required: No Default value: None", "title": "bulkMaxPayloadSize"}, {"location": "janssen-server/reference/json/properties/scim-properties/#disablejdklogger", "text": "Description: Boolean value specifying whether to enable JDK Loggers Required: No Default value: None", "title": "disableJdkLogger"}, {"location": "janssen-server/reference/json/properties/scim-properties/#externalloggerconfiguration", "text": "Description: Path to external log4j2 logging configuration Required: No Default value: None", "title": "externalLoggerConfiguration"}, {"location": "janssen-server/reference/json/properties/scim-properties/#logginglayout", "text": "Description: Logging layout used for Server loggers Required: No Default value: None", "title": "loggingLayout"}, {"location": "janssen-server/reference/json/properties/scim-properties/#logginglevel", "text": "Description: Logging level for scim logger Required: No Default value: None", "title": "loggingLevel"}, {"location": "janssen-server/reference/json/properties/scim-properties/#maxcount", "text": "Description: Maximum number of results per page Required: No Default value: None", "title": "maxCount"}, {"location": "janssen-server/reference/json/properties/scim-properties/#metricreporterenabled", "text": "Description: Metric reported data enabled flag Required: No Default value: None", "title": "metricReporterEnabled"}, {"location": "janssen-server/reference/json/properties/scim-properties/#metricreporterinterval", "text": "Description: The interval for metric reporter in seconds Required: No Default value: None", "title": "metricReporterInterval"}, {"location": "janssen-server/reference/json/properties/scim-properties/#metricreporterkeepdatadays", "text": "Description: The days to keep metric reported data Required: No Default value: None", "title": "metricReporterKeepDataDays"}, {"location": "janssen-server/reference/json/properties/scim-properties/#oxauthissuer", "text": "Description: Jans Auth - Issuer identifier Required: No Default value: None", "title": "oxAuthIssuer"}, {"location": "janssen-server/reference/json/properties/scim-properties/#personcustomobjectclass", "text": "Description: Person Object Class Required: No Default value: None", "title": "personCustomObjectClass"}, {"location": "janssen-server/reference/json/properties/scim-properties/#protectionmode", "text": "Description: SCIM Protection Mode Required: No Default value: None", "title": "protectionMode"}, {"location": "janssen-server/reference/json/properties/scim-properties/#uselocalcache", "text": "Description: Boolean value specifying whether to enable local in-memory cache Required: No Default value: None", "title": "useLocalCache"}, {"location": "janssen-server/reference/json/properties/scim-properties/#userextensionschemauri", "text": "Description: User Extension Schema URI Required: No Default value: None", "title": "userExtensionSchemaURI"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/", "tags": ["administration", "reference", "kubernetes", "configmap", "secret"], "text": "Overview # The config job creates a set of configurations (contains secrets and configmaps ) used by all Janssen services. Note We assume Janssen is installed in a namespace called jans Configmaps # The configmaps store non-sensitive data as key-value pairs. To check the values of the configmaps on the current deployment run: kubectl get configmap -n jans -o yaml Note that each key in configmaps is based on the schema below: { \"city\" : { \"type\" : \"string\" , \"description\" : \"Locality name (e.g. city)\" , \"example\" : \"Austin\" }, \"country_code\" : { \"type\" : \"string\" , \"minLength\" : 2 , \"maxLength\" : 2 , \"description\" : \"Country name (2 letter code)\" , \"example\" : \"US\" }, \"admin_email\" : { \"type\" : \"string\" , \"format\" : \"email\" , \"description\" : \"Email address\" , \"example\" : \"support@jans.io\" }, \"hostname\" : { \"type\" : \"string\" , \"description\" : \"Fully qualified domain name (FQDN)\" , \"example\" : \"demoexample.jans.io\" }, \"orgName\" : { \"type\" : \"string\" , \"description\" : \"Organization name\" , \"example\" : \"Janssen\" }, \"state\" : { \"type\" : \"string\" , \"description\" : \"State or Province Name\" , \"example\" : \"TX\" }, \"optional_scopes\" : { \"type\" : \"string\" , \"default\" : \"[]\" , \"description\" : \"List of optional scopes of components as string\" , \"example\" : \"[\\\"redis\\\", \\\"sql\\\"]\" }, \"auth_sig_keys\" : { \"type\" : \"string\" , \"default\" : \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" , \"description\" : \"Signature keys to generate\" , \"example\" : \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" }, \"auth_enc_keys\" : { \"type\" : \"string\" , \"default\" : \"RSA1_5 RSA-OAEP ECDH-ES\" , \"description\" : \"Encryption keys to generate\" , \"example\" : \"RSA1_5 RSA-OAEP ECDH-ES\" }, \"init_keys_exp\" : { \"type\" : \"integer\" , \"default\" : 48 , \"minimum\" : 1 , \"description\" : \"Initial expiration time (in hours) for generated keys\" , \"example\" : 24 }, \"admin_inum\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Inum for admin user\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"admin_ui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of admin-ui app\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"casa_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-casa app\" , \"example\" : \"1902.66bc89a1-075f-4a18-9349-a2908c1040e6\" }, \"jans_idp_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-idp app\" , \"example\" : \"jans-f13013e3-e4a7-4709-8b50-df459f489cd3\" }, \"jca_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-config-api app\" , \"example\" : \"1800.ca41fad2-6ab6-46b1-b4a9-3387992a8cb0\" }, \"scim_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-scim app\" , \"example\" : \"1201.dd7e7733-b548-45ee-aed1-74e7b4065801\" }, \"tui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-tui app\" , \"example\" : \"2000.4a67fad3-24cd-4d56-b5a3-7cfb2e9fbb05\" }, \"test_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of test app\" , \"example\" : \"174143d2-f7f6-4bda-baa0-a6a8fd01b77a\" }, \"kc_master_auth_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak master auth app\" , \"example\" : \"2103.22abf39d-f78f-4fb0-871e-dcb80bc1e43c\" }, \"kc_saml_openid_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak SAML OpenID app\" , \"example\" : \"2101.70394974-82ec-481e-9493-e96d3cf8072f\" }, \"kc_scheduler_api_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak scheduler API app\" , \"example\" : \"2102.d424af33-2069-4803-8426-4787af5fd933\" }, \"token_server_admin_ui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of token server app\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"auth_key_rotated_at\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Timestamp of last auth keys regeneration\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"auth_legacyIdTokenClaims\" : { \"type\" : \"string\" , \"default\" : \"false\" , \"enum\" : [ \"false\" , \"true\" ], \"description\" : \"Enable legacy ID token claim\" , \"example\" : \"false\" }, \"auth_openidScopeBackwardCompatibility\" : { \"type\" : \"string\" , \"default\" : \"false\" , \"enum\" : [ \"false\" , \"true\" ], \"description\" : \"Enable backward-compat OpenID scope\" , \"example\" : \"false\" }, \"auth_openid_jks_fn\" : { \"type\" : \"string\" , \"default\" : \"/etc/certs/auth-keys.jks\" , \"description\" : \"Path to keystore file contains private keys for jans-auth\" }, \"auth_openid_jwks_fn\" : { \"type\" : \"string\" , \"default\" : \"/etc/certs/auth-keys.json\" , \"description\" : \"Path to JSON file contains public keys for jans-auth\" }, \"default_openid_jks_dn_name\" : { \"type\" : \"string\" , \"default\" : \"CN=Janssen Auth CA Certificates\" , \"description\" : \"CommonName for jans-auth CA certificate\" }, \"kc_admin_username\" : { \"type\" : \"string\" , \"default\" : \"admin\" , \"description\" : \"Admin username of Keycloak\" , \"example\" : \"admin\" }, \"smtp_alias\" : { \"type\" : \"string\" , \"default\" : \"smtp_sig_ec256\" , \"description\" : \"Alias for SMTP entry in truststore\" , \"example\" : \"smtp_sig_ec256\" }, \"smtp_signing_alg\" : { \"type\" : \"string\" , \"default\" : \"SHA256withECDSA\" , \"description\" : \"SMTP signing algorithm\" , \"example\" : \"SHA256withECDSA\" } } Secrets # The secrets store sensitive data as key-value pairs. To check the values of the secrets on the current deployment run : kubectl get secret -n jans -o yaml Note that each key in secrets is based on the schema below: { \"admin_password\" : { \"type\" : \"string\" , \"description\" : \"Password for admin user\" }, \"sql_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for SQL (RDBMS) user\" }, \"encoded_salt\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Salt for encoding/decoding sensitive secret\" , \"example\" : \"hR8kBUtTxB25pDPCSHVRktAz\" }, \"google_credentials\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains Google application credentials\" , \"example\" : \"{\\n \\\"type\\\": \\\"service_account\\\",\\n \\\"project_id\\\": \\\"testing-project\\\"\\n}\\n\" }, \"aws_credentials\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS shared credentials\" , \"example\" : \"[default]\\naws_access_key_id = FAKE_ACCESS_KEY_ID\\naws_secret_access_key = FAKE_SECRET_ACCESS_KEY\\n\" }, \"aws_config\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS config\" , \"example\" : \"[default]\\nregion = us-west-1\\n\" }, \"aws_replica_regions\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS replica regions config\" , \"example\" : \"[{\\\"Region\\\": \\\"us-west-1\\\"}, {\\\"Region\\\": \\\"us-west-2\\\"}]\\n\" }, \"vault_role_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Vault RoleID\" }, \"vault_secret_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Vault SecretID\" }, \"kc_db_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for Keycloak RDBMS user\" }, \"admin_ui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for admin-ui client\" , \"x-encoding\" : \"3DES\" }, \"admin_ui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for admin-ui client\" }, \"auth_jks_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Private keys (keystore) of jans-auth\" }, \"auth_openid_jks_pass\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password of jans-auth keystore\" }, \"auth_openid_key_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Public keys (JWKS) of jans-auth\" }, \"casa_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-casa client\" , \"x-encoding\" : \"3DES\" }, \"casa_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-casa client\" }, \"encoded_admin_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password of admin\" , \"x-encoding\" : \"ldap_encode\" }, \"jans_idp_client_secret\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of jans-idp app\" }, \"jans_idp_user_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"User password for jans-idp\" }, \"jca_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-config-api client\" , \"x-encoding\" : \"3DES\" }, \"jca_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-config-api client\" }, \"kc_admin_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Admin password of Keycloak\" }, \"kc_master_auth_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak master auth app\" , \"x-encoding\" : \"3DES\" }, \"kc_master_auth_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak master auth app\" }, \"kc_saml_openid_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak SAML app\" , \"x-encoding\" : \"3DES\" }, \"kc_saml_openid_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak SAML app\" }, \"kc_scheduler_api_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak scheduler API app\" , \"x-encoding\" : \"3DES\" }, \"kc_scheduler_api_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak scheduler API app\" }, \"otp_configuration\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"OTP configuration string\" }, \"pairwiseCalculationKey\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Pairwise calculation key\" }, \"pairwiseCalculationSalt\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Pairwise calculation salt\" }, \"scim_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-scim client\" , \"x-encoding\" : \"3DES\" }, \"scim_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-scim client\" }, \"smtp_jks_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Private keys (keystore) of SMTP\" }, \"smtp_jks_pass\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password of SMTP keystore\" }, \"smtp_jks_pass_enc\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password of SMTP keystore\" }, \"ssl_ca_cert\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate for CA\" }, \"ssl_ca_key\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL key for CA\" }, \"ssl_cert\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate for the FQDN\" }, \"ssl_csr\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate signing request for the FQDN\" }, \"ssl_key\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL key for the FQDN\" }, \"super_gluu_creds\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SuperGluu credentials string\" }, \"test_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for test client\" , \"x-encoding\" : \"3DES\" }, \"test_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for test client\" }, \"token_server_admin_ui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for token server client\" , \"x-encoding\" : \"3DES\" }, \"token_server_admin_ui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for token server client\" }, \"tui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for TUI client\" , \"x-encoding\" : \"3DES\" }, \"tui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for TUI client\" }, \"redis_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for Redis user\" } } Example decoding secrets # Opening base64-decoded secrets # Get the tls-certificate from the backend secret kubectl get secret tls-certificate -n jans -o yaml Copy the value of the key you want to decode. For example: data: tls.crt: <encodedValue> Base64 decode the value echo <encodedValue> | base64 -d #replace encodedValue with the value from the previous command Using Configuration Schema # As mentioned earlier, the config job creates a set of configurations. This happens by using a Kubernetes secret named <janssen-release-name>-configuration-file that gets created during the helm chart installation. It contains a JSON schema with the necessary secrets and configmaps to install Janssen services. This secret is then mounted by the config job. Default configuration # apiVersion : v1 kind : Secret metadata : name : janssen-configuration-file namespace : jans labels : APP_NAME : configurator type : Opaque stringData : configuration.json : |- { \"_configmap\": { \"hostname\": \"demoexample.jans.io\", \"country_code\": \"US\", \"state\": \"TX\", \"city\": \"Austin\", \"admin_email\": \"support@jans.io\", \"orgName\": \"Janssen\", \"auth_sig_keys\": \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\", \"auth_enc_keys\": \"RSA1_5 RSA-OAEP ECDH-ES\", \"optional_scopes\": \"[\\\"redis\\\", \\\"sql\\\"]\", \"init_keys_exp\": 48 }, \"_secret\": { \"admin_password\": \"Test1234#\", \"sql_password\": \"Test1234#\", \"encoded_salt\": \"hR8kBUtTxB25pDPCSHVRktAz\" } } Note that _secret may contain other keys depending on the persistence used, the backend of the secrets/configmaps, etc. For example: Secrets/configmaps backend is set to google : \"_secret\" : { \"google_credentials\" : \"{\\n \\\"type\\\": \\\"service_account\\\",\\n \\\"project_id\\\": \\\"testing-project\\\"\\n}\" } Secrets backend is set to vault : \"_secret\" : { \"vault_role_id\" : \"c41a15f4-abcd-1234-abcd-d306bf9f3eb6\" , \"vault_secret_id\" : \"a7ae191c-abcd-1234-abcd-3733dc6b0813\" } Secrets/configmaps backend is set to aws : \"_secret\" : { \"aws_config\" : \"[default]\\nregion = us-west-1\\n\" , \"aws_credentials\" : \"[default]\\naws_access_key_id = FAKE_ACCESS_KEY_ID\\naws_secret_access_key = FAKE_SECRET_ACCESS_KEY\\n\" , \"aws_replica_regions\" : \"[{\\\"Region\\\": \\\"us-west-1\\\"}, {\\\"Region\\\": \\\"us-west-2\\\"}]\\n\" } Custom configuration # The default configuration schema is sufficient for most of the time. However, if there's a requirement to use a custom configuration or reusing an existing configuration, you can create a Kubernetes secret with the custom configuration schema. Warning The custom configuration schema is a BETA feature. Prepare the YAML file containing the custom configuration schema. We will name it custom-configuration-schema.yaml : apiVersion : v1 kind : Secret metadata : name : custom-configuration-schema namespace : jans type : Opaque stringData : configuration.json : |- { \"_configmap\": { \"hostname\": \"demoexample.jans.io\", \"country_code\": \"US\", \"state\": \"TX\", \"city\": \"Houston\", \"admin_email\": \"custom@example.com\", \"orgName\": \"custom-org\", \"optional_scopes\": \"[\\\"sql\\\"]\" }, \"_secret\": { \"admin_password\": \"Custom1234#\", \"sql_password\": \"Custom1234#\" } } Create the Kubernetes secret: kubectl -n jans apply -f custom-configuration-schema.yaml Specify the secret in values.yaml : global : cnConfiguratorCustomSchema : secretName : custom-configuration-schema Install the Janssen helm chart. Encrypting Configuration Schema # The encryption uses Helm-specific implementation of AES-256 CBC mode. Default configuration # The default configuration schema can be encrypted by specifying 32 alphanumeric characters to cnConfiguratorKey attribute (the default value is an empty string). global : cnConfiguratorKey : \"VMtVyFha8CfppdDGQSw8zEnfKXRvksAD\" The following example is what an encrypted default configuration looks like: apiVersion : v1 kind : Secret metadata : name : janssen-configuration-file namespace : jans stringData : configuration.json : |- sxySo+redacted+generated+by+helm/TNpE5PoUR2+JxXiHiLq8X5ibexJcfjAN0fKlqRvU= Custom configuration # If you are using a custom configuration schema, you will need to generate the string using sprig-aes CLI and paste it into a YAML manifest. # custom-configuration-schema.yaml apiVersion : v1 kind : Secret metadata : name : custom-configuration-schema namespace : jans type : Opaque stringData : configuration.json : |- sxySo+redacted+generated+by+sprigaes+JxXiHiLq8X5ibexJcfjAN0fKlqRvU= Add the key used when encrypting using sprig-aes. global : cnConfiguratorKey : \"VMtVyFha8CfppdDGQSw8zEnfKXRvksAD\"", "title": "Configuration Keys"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#overview", "text": "The config job creates a set of configurations (contains secrets and configmaps ) used by all Janssen services. Note We assume Janssen is installed in a namespace called jans", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#configmaps", "text": "The configmaps store non-sensitive data as key-value pairs. To check the values of the configmaps on the current deployment run: kubectl get configmap -n jans -o yaml Note that each key in configmaps is based on the schema below: { \"city\" : { \"type\" : \"string\" , \"description\" : \"Locality name (e.g. city)\" , \"example\" : \"Austin\" }, \"country_code\" : { \"type\" : \"string\" , \"minLength\" : 2 , \"maxLength\" : 2 , \"description\" : \"Country name (2 letter code)\" , \"example\" : \"US\" }, \"admin_email\" : { \"type\" : \"string\" , \"format\" : \"email\" , \"description\" : \"Email address\" , \"example\" : \"support@jans.io\" }, \"hostname\" : { \"type\" : \"string\" , \"description\" : \"Fully qualified domain name (FQDN)\" , \"example\" : \"demoexample.jans.io\" }, \"orgName\" : { \"type\" : \"string\" , \"description\" : \"Organization name\" , \"example\" : \"Janssen\" }, \"state\" : { \"type\" : \"string\" , \"description\" : \"State or Province Name\" , \"example\" : \"TX\" }, \"optional_scopes\" : { \"type\" : \"string\" , \"default\" : \"[]\" , \"description\" : \"List of optional scopes of components as string\" , \"example\" : \"[\\\"redis\\\", \\\"sql\\\"]\" }, \"auth_sig_keys\" : { \"type\" : \"string\" , \"default\" : \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" , \"description\" : \"Signature keys to generate\" , \"example\" : \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" }, \"auth_enc_keys\" : { \"type\" : \"string\" , \"default\" : \"RSA1_5 RSA-OAEP ECDH-ES\" , \"description\" : \"Encryption keys to generate\" , \"example\" : \"RSA1_5 RSA-OAEP ECDH-ES\" }, \"init_keys_exp\" : { \"type\" : \"integer\" , \"default\" : 48 , \"minimum\" : 1 , \"description\" : \"Initial expiration time (in hours) for generated keys\" , \"example\" : 24 }, \"admin_inum\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Inum for admin user\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"admin_ui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of admin-ui app\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"casa_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-casa app\" , \"example\" : \"1902.66bc89a1-075f-4a18-9349-a2908c1040e6\" }, \"jans_idp_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-idp app\" , \"example\" : \"jans-f13013e3-e4a7-4709-8b50-df459f489cd3\" }, \"jca_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-config-api app\" , \"example\" : \"1800.ca41fad2-6ab6-46b1-b4a9-3387992a8cb0\" }, \"scim_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-scim app\" , \"example\" : \"1201.dd7e7733-b548-45ee-aed1-74e7b4065801\" }, \"tui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of jans-tui app\" , \"example\" : \"2000.4a67fad3-24cd-4d56-b5a3-7cfb2e9fbb05\" }, \"test_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of test app\" , \"example\" : \"174143d2-f7f6-4bda-baa0-a6a8fd01b77a\" }, \"kc_master_auth_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak master auth app\" , \"example\" : \"2103.22abf39d-f78f-4fb0-871e-dcb80bc1e43c\" }, \"kc_saml_openid_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak SAML OpenID app\" , \"example\" : \"2101.70394974-82ec-481e-9493-e96d3cf8072f\" }, \"kc_scheduler_api_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of Keycloak scheduler API app\" , \"example\" : \"2102.d424af33-2069-4803-8426-4787af5fd933\" }, \"token_server_admin_ui_client_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client ID of token server app\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"auth_key_rotated_at\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Timestamp of last auth keys regeneration\" , \"example\" : \"631e2b84-1d3d-4f28-9a9a-026a25febf44\" }, \"auth_legacyIdTokenClaims\" : { \"type\" : \"string\" , \"default\" : \"false\" , \"enum\" : [ \"false\" , \"true\" ], \"description\" : \"Enable legacy ID token claim\" , \"example\" : \"false\" }, \"auth_openidScopeBackwardCompatibility\" : { \"type\" : \"string\" , \"default\" : \"false\" , \"enum\" : [ \"false\" , \"true\" ], \"description\" : \"Enable backward-compat OpenID scope\" , \"example\" : \"false\" }, \"auth_openid_jks_fn\" : { \"type\" : \"string\" , \"default\" : \"/etc/certs/auth-keys.jks\" , \"description\" : \"Path to keystore file contains private keys for jans-auth\" }, \"auth_openid_jwks_fn\" : { \"type\" : \"string\" , \"default\" : \"/etc/certs/auth-keys.json\" , \"description\" : \"Path to JSON file contains public keys for jans-auth\" }, \"default_openid_jks_dn_name\" : { \"type\" : \"string\" , \"default\" : \"CN=Janssen Auth CA Certificates\" , \"description\" : \"CommonName for jans-auth CA certificate\" }, \"kc_admin_username\" : { \"type\" : \"string\" , \"default\" : \"admin\" , \"description\" : \"Admin username of Keycloak\" , \"example\" : \"admin\" }, \"smtp_alias\" : { \"type\" : \"string\" , \"default\" : \"smtp_sig_ec256\" , \"description\" : \"Alias for SMTP entry in truststore\" , \"example\" : \"smtp_sig_ec256\" }, \"smtp_signing_alg\" : { \"type\" : \"string\" , \"default\" : \"SHA256withECDSA\" , \"description\" : \"SMTP signing algorithm\" , \"example\" : \"SHA256withECDSA\" } }", "title": "Configmaps"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#secrets", "text": "The secrets store sensitive data as key-value pairs. To check the values of the secrets on the current deployment run : kubectl get secret -n jans -o yaml Note that each key in secrets is based on the schema below: { \"admin_password\" : { \"type\" : \"string\" , \"description\" : \"Password for admin user\" }, \"sql_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for SQL (RDBMS) user\" }, \"encoded_salt\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Salt for encoding/decoding sensitive secret\" , \"example\" : \"hR8kBUtTxB25pDPCSHVRktAz\" }, \"google_credentials\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains Google application credentials\" , \"example\" : \"{\\n \\\"type\\\": \\\"service_account\\\",\\n \\\"project_id\\\": \\\"testing-project\\\"\\n}\\n\" }, \"aws_credentials\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS shared credentials\" , \"example\" : \"[default]\\naws_access_key_id = FAKE_ACCESS_KEY_ID\\naws_secret_access_key = FAKE_SECRET_ACCESS_KEY\\n\" }, \"aws_config\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS config\" , \"example\" : \"[default]\\nregion = us-west-1\\n\" }, \"aws_replica_regions\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"String contains AWS replica regions config\" , \"example\" : \"[{\\\"Region\\\": \\\"us-west-1\\\"}, {\\\"Region\\\": \\\"us-west-2\\\"}]\\n\" }, \"vault_role_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Vault RoleID\" }, \"vault_secret_id\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Vault SecretID\" }, \"kc_db_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for Keycloak RDBMS user\" }, \"admin_ui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for admin-ui client\" , \"x-encoding\" : \"3DES\" }, \"admin_ui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for admin-ui client\" }, \"auth_jks_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Private keys (keystore) of jans-auth\" }, \"auth_openid_jks_pass\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password of jans-auth keystore\" }, \"auth_openid_key_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Public keys (JWKS) of jans-auth\" }, \"casa_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-casa client\" , \"x-encoding\" : \"3DES\" }, \"casa_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-casa client\" }, \"encoded_admin_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password of admin\" , \"x-encoding\" : \"ldap_encode\" }, \"jans_idp_client_secret\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of jans-idp app\" }, \"jans_idp_user_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"User password for jans-idp\" }, \"jca_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-config-api client\" , \"x-encoding\" : \"3DES\" }, \"jca_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-config-api client\" }, \"kc_admin_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Admin password of Keycloak\" }, \"kc_master_auth_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak master auth app\" , \"x-encoding\" : \"3DES\" }, \"kc_master_auth_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak master auth app\" }, \"kc_saml_openid_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak SAML app\" , \"x-encoding\" : \"3DES\" }, \"kc_saml_openid_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak SAML app\" }, \"kc_scheduler_api_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client encoded secret of Keycloak scheduler API app\" , \"x-encoding\" : \"3DES\" }, \"kc_scheduler_api_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Client secret of Keycloak scheduler API app\" }, \"otp_configuration\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"OTP configuration string\" }, \"pairwiseCalculationKey\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Pairwise calculation key\" }, \"pairwiseCalculationSalt\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Pairwise calculation salt\" }, \"scim_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for jans-scim client\" , \"x-encoding\" : \"3DES\" }, \"scim_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for jans-scim client\" }, \"smtp_jks_base64\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Private keys (keystore) of SMTP\" }, \"smtp_jks_pass\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password of SMTP keystore\" }, \"smtp_jks_pass_enc\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password of SMTP keystore\" }, \"ssl_ca_cert\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate for CA\" }, \"ssl_ca_key\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL key for CA\" }, \"ssl_cert\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate for the FQDN\" }, \"ssl_csr\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL certificate signing request for the FQDN\" }, \"ssl_key\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SSL key for the FQDN\" }, \"super_gluu_creds\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"SuperGluu credentials string\" }, \"test_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for test client\" , \"x-encoding\" : \"3DES\" }, \"test_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for test client\" }, \"token_server_admin_ui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for token server client\" , \"x-encoding\" : \"3DES\" }, \"token_server_admin_ui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for token server client\" }, \"tui_client_encoded_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Encoded password for TUI client\" , \"x-encoding\" : \"3DES\" }, \"tui_client_pw\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for TUI client\" }, \"redis_password\" : { \"type\" : \"string\" , \"default\" : \"\" , \"description\" : \"Password for Redis user\" } }", "title": "Secrets"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#example-decoding-secrets", "text": "", "title": "Example decoding secrets"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#opening-base64-decoded-secrets", "text": "Get the tls-certificate from the backend secret kubectl get secret tls-certificate -n jans -o yaml Copy the value of the key you want to decode. For example: data: tls.crt: <encodedValue> Base64 decode the value echo <encodedValue> | base64 -d #replace encodedValue with the value from the previous command", "title": "Opening base64-decoded secrets"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#using-configuration-schema", "text": "As mentioned earlier, the config job creates a set of configurations. This happens by using a Kubernetes secret named <janssen-release-name>-configuration-file that gets created during the helm chart installation. It contains a JSON schema with the necessary secrets and configmaps to install Janssen services. This secret is then mounted by the config job.", "title": "Using Configuration Schema"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#default-configuration", "text": "apiVersion : v1 kind : Secret metadata : name : janssen-configuration-file namespace : jans labels : APP_NAME : configurator type : Opaque stringData : configuration.json : |- { \"_configmap\": { \"hostname\": \"demoexample.jans.io\", \"country_code\": \"US\", \"state\": \"TX\", \"city\": \"Austin\", \"admin_email\": \"support@jans.io\", \"orgName\": \"Janssen\", \"auth_sig_keys\": \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\", \"auth_enc_keys\": \"RSA1_5 RSA-OAEP ECDH-ES\", \"optional_scopes\": \"[\\\"redis\\\", \\\"sql\\\"]\", \"init_keys_exp\": 48 }, \"_secret\": { \"admin_password\": \"Test1234#\", \"sql_password\": \"Test1234#\", \"encoded_salt\": \"hR8kBUtTxB25pDPCSHVRktAz\" } } Note that _secret may contain other keys depending on the persistence used, the backend of the secrets/configmaps, etc. For example: Secrets/configmaps backend is set to google : \"_secret\" : { \"google_credentials\" : \"{\\n \\\"type\\\": \\\"service_account\\\",\\n \\\"project_id\\\": \\\"testing-project\\\"\\n}\" } Secrets backend is set to vault : \"_secret\" : { \"vault_role_id\" : \"c41a15f4-abcd-1234-abcd-d306bf9f3eb6\" , \"vault_secret_id\" : \"a7ae191c-abcd-1234-abcd-3733dc6b0813\" } Secrets/configmaps backend is set to aws : \"_secret\" : { \"aws_config\" : \"[default]\\nregion = us-west-1\\n\" , \"aws_credentials\" : \"[default]\\naws_access_key_id = FAKE_ACCESS_KEY_ID\\naws_secret_access_key = FAKE_SECRET_ACCESS_KEY\\n\" , \"aws_replica_regions\" : \"[{\\\"Region\\\": \\\"us-west-1\\\"}, {\\\"Region\\\": \\\"us-west-2\\\"}]\\n\" }", "title": "Default configuration"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#custom-configuration", "text": "The default configuration schema is sufficient for most of the time. However, if there's a requirement to use a custom configuration or reusing an existing configuration, you can create a Kubernetes secret with the custom configuration schema. Warning The custom configuration schema is a BETA feature. Prepare the YAML file containing the custom configuration schema. We will name it custom-configuration-schema.yaml : apiVersion : v1 kind : Secret metadata : name : custom-configuration-schema namespace : jans type : Opaque stringData : configuration.json : |- { \"_configmap\": { \"hostname\": \"demoexample.jans.io\", \"country_code\": \"US\", \"state\": \"TX\", \"city\": \"Houston\", \"admin_email\": \"custom@example.com\", \"orgName\": \"custom-org\", \"optional_scopes\": \"[\\\"sql\\\"]\" }, \"_secret\": { \"admin_password\": \"Custom1234#\", \"sql_password\": \"Custom1234#\" } } Create the Kubernetes secret: kubectl -n jans apply -f custom-configuration-schema.yaml Specify the secret in values.yaml : global : cnConfiguratorCustomSchema : secretName : custom-configuration-schema Install the Janssen helm chart.", "title": "Custom configuration"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#encrypting-configuration-schema", "text": "The encryption uses Helm-specific implementation of AES-256 CBC mode.", "title": "Encrypting Configuration Schema"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#default-configuration_1", "text": "The default configuration schema can be encrypted by specifying 32 alphanumeric characters to cnConfiguratorKey attribute (the default value is an empty string). global : cnConfiguratorKey : \"VMtVyFha8CfppdDGQSw8zEnfKXRvksAD\" The following example is what an encrypted default configuration looks like: apiVersion : v1 kind : Secret metadata : name : janssen-configuration-file namespace : jans stringData : configuration.json : |- sxySo+redacted+generated+by+helm/TNpE5PoUR2+JxXiHiLq8X5ibexJcfjAN0fKlqRvU=", "title": "Default configuration"}, {"location": "janssen-server/reference/kubernetes/config-secret-keys/#custom-configuration_1", "text": "If you are using a custom configuration schema, you will need to generate the string using sprig-aes CLI and paste it into a YAML manifest. # custom-configuration-schema.yaml apiVersion : v1 kind : Secret metadata : name : custom-configuration-schema namespace : jans type : Opaque stringData : configuration.json : |- sxySo+redacted+generated+by+sprigaes+JxXiHiLq8X5ibexJcfjAN0fKlqRvU= Add the key used when encrypting using sprig-aes. global : cnConfiguratorKey : \"VMtVyFha8CfppdDGQSw8zEnfKXRvksAD\"", "title": "Custom configuration"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Docker image packaging for Janssen Authorization Server. Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_DEBUG_PORT : port of remote debugging (if omitted, remote debugging will be disabled). CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_AUTH_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_SYNC_INTERVAL : Interval between files sync (default to 300 seconds). CN_JACKRABBIT_ADMIN_ID : Admin username (default to admin ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/jans/conf/jackrabbit_admin_password ). CN_SYNC_JKS_ENABLED : Whether to enable JKS sync (default to false ). Enable this flag if using gluufederation/key-rotation:4.1.1_02 and below (for key-regeneration). CN_SYNC_JKS_INTERVAL : Interval of JKS sync in seconds (if needed); obsolete. GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_JETTY_REQUEST_HEADER_SIZE : Maximum size of request header accepted by Jetty (default to 8192 ). CN_AUTH_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_LOCK_ENABLED : Enable jans-lock as part of jans-auth . CN_OPA_URL : URL to OPA server (default to http://localhost:8181/v1 ). CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file. Configure app loggers # App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"auth_log_target\" : \"STDOUT\" , \"auth_log_level\" : \"INFO\" , \"http_log_target\" : \"FILE\" , \"http_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" , \"audit_log_target\" : \"FILE\" , \"audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"auth_log_target\":\"STDOUT\",\"script_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Configure plugin loggers # Plugin loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"lock_log_target\" : \"STDOUT\" , \"lock_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"lock_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", } Exposing metrics # As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterward, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Auth Server"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#overview", "text": "Docker image packaging for Janssen Authorization Server.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_DEBUG_PORT : port of remote debugging (if omitted, remote debugging will be disabled). CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_AUTH_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_SYNC_INTERVAL : Interval between files sync (default to 300 seconds). CN_JACKRABBIT_ADMIN_ID : Admin username (default to admin ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/jans/conf/jackrabbit_admin_password ). CN_SYNC_JKS_ENABLED : Whether to enable JKS sync (default to false ). Enable this flag if using gluufederation/key-rotation:4.1.1_02 and below (for key-regeneration). CN_SYNC_JKS_INTERVAL : Interval of JKS sync in seconds (if needed); obsolete. GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_JETTY_REQUEST_HEADER_SIZE : Maximum size of request header accepted by Jetty (default to 8192 ). CN_AUTH_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_LOCK_ENABLED : Enable jans-lock as part of jans-auth . CN_OPA_URL : URL to OPA server (default to http://localhost:8181/v1 ). CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#configure-app-loggers", "text": "App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"auth_log_target\" : \"STDOUT\" , \"auth_log_level\" : \"INFO\" , \"http_log_target\" : \"FILE\" , \"http_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" , \"audit_log_target\" : \"FILE\" , \"audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"auth_log_target\":\"STDOUT\",\"script_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure app loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#configure-plugin-loggers", "text": "Plugin loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"lock_log_target\" : \"STDOUT\" , \"lock_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"lock_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure plugin loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-auth-server/#exposing-metrics", "text": "As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterward, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Exposing metrics"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/", "text": "Overview # Docker assets for Casa Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault or kubernetes . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_CONFIGMAP : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_SYNC_INTERVAL : Interval between files sync (default to 300 seconds). CN_JACKRABBIT_ADMIN_ID : Admin username (default to admin ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/jans/conf/jackrabbit_admin_password ). CN_SQL_DB_DIALECT : Dialect name of SQL backend (one of mysql , pgsql ; default to mysql ). CN_SQL_DB_HOST : Host of SQL backend (default to localhost ). CN_SQL_DB_PORT : Port of SQL backend (default to 3306 ). CN_SQL_DB_NAME : Database name (default to jans ) CN_SQL_DB_USER : Username to interact with SQL backend (default to jans ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CASA_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_CASA_ADMIN_LOCK_FILE : Path to lock file to enable/disable administration feature (default to /opt/jans/jetty/jans-casa/.administrable ). If file is not exist, the feature is disabled. CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_CASA_JWKS_SIZE_LIMIT : Default HTTP size limit (in bytes) when retrieving remote JWKS (default to 100000 ). CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file. Configure app loggers # App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: OFF FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"casa_log_target\" : \"STDOUT\" , \"casa_log_level\" : \"INFO\" , \"timer_log_target\" : \"FILE\" , \"timer_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"casa_log_target\":\"STDOUT\",\"timer_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Exposing metrics # As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container. Hybrid mapping # Hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Casa"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#overview", "text": "Docker assets for Casa", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault or kubernetes . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_CONFIGMAP : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_SYNC_INTERVAL : Interval between files sync (default to 300 seconds). CN_JACKRABBIT_ADMIN_ID : Admin username (default to admin ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/jans/conf/jackrabbit_admin_password ). CN_SQL_DB_DIALECT : Dialect name of SQL backend (one of mysql , pgsql ; default to mysql ). CN_SQL_DB_HOST : Host of SQL backend (default to localhost ). CN_SQL_DB_PORT : Port of SQL backend (default to 3306 ). CN_SQL_DB_NAME : Database name (default to jans ) CN_SQL_DB_USER : Username to interact with SQL backend (default to jans ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CASA_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_CASA_ADMIN_LOCK_FILE : Path to lock file to enable/disable administration feature (default to /opt/jans/jetty/jans-casa/.administrable ). If file is not exist, the feature is disabled. CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_CASA_JWKS_SIZE_LIMIT : Default HTTP size limit (in bytes) when retrieving remote JWKS (default to 100000 ). CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#configure-app-loggers", "text": "App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: OFF FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"casa_log_target\" : \"STDOUT\" , \"casa_log_level\" : \"INFO\" , \"timer_log_target\" : \"FILE\" , \"timer_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"casa_log_target\":\"STDOUT\",\"timer_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure app loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#exposing-metrics", "text": "As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Exposing metrics"}, {"location": "janssen-server/reference/kubernetes/docker-jans-casa/#hybrid-mapping", "text": "Hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Container image to manage X.509 certificates and crypto keys in Janssen Server. The container is designed to run as a one-time command (or Job in Kubernetes world). Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_GOOGLE_SECRET_VERSION_ID : Google Secret Manager version ID (default to latest ). CN_SECRET_GOOGLE_SECRET_NAME_PREFIX : Prefix for Google Secret Manager name (default to jans ). CN_SECRET_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Google Secret Manager (default to secret ). CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_CONTAINER_METADATA : The name of scheduler to pull container metadata (one of docker or kubernetes ; default to docker ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. Usage # Commands # The following commands are supported by the container: patch prune patch # Updates X.509 certificates and/or crypto keys related to the service. Usage: certmanager patch [OPTIONS] SERVICE Patch cert and/or crypto keys for the targeted service. Options: --dry-run Enable dryrun mode. --opts KEY:VALUE Options for targeted service (can be set multiple times). -h, --help Show this message and exit. Global options: --dry-run --opts : service-dependent options, example: --opts interval:48 Supported services: web (nginx container or ingress) Load from existing or re-generate: /etc/certs/jans_https.crt /etc/certs/jans_https.key . Options: source : from-files or empty string valid-to : Validity length in days (default to 365 ) auth Re-generate: /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Options: interval : crypto keys expiration time (in hours) push-to-container : whether to push auth-keys.jks and auth-keys.json to auth-server containers (default to true ) key-strategy : key selection strategy (choose one of OLDER , NEWER , FIRST ; default to NEWER ) privkey-push-delay : delay time in seconds before pushing auth-keys.jks to auth containers (default to 0 ) privkey-push-strategy : key selection strategy after auth-keys.jks is pushed to auth containers (choose one of OLDER , NEWER , FIRST ; default to NEWER ) sig-keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) enc-keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) prune # Delete expired crypto keys (if any) related to the service. Usage: certmanager prune [OPTIONS] SERVICE Cleanup expired crypto keys for the targeted service. Options: --dry-run Enable dryrun mode. --opts KEY:VALUE Options for targeted service (can be set multiple times). -h, --help Show this message and exit. Global options: --dry-run --opts : service-dependent options, example: --opts interval:48 Supported services: auth Delete expired keys (if any) from the following files: /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Options: push-to-container : whether to push auth-keys.jks and auth-keys.json to auth containers (default to true ) sig-keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) enc-keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) Examples # Kubernetes CronJob example: kind : CronJob apiVersion : batch/v1beta1 metadata : name : auth-key-rotation spec : schedule : \"0 */48 * * *\" concurrencyPolicy : Forbid jobTemplate : spec : template : spec : containers : - name : auth-key-rotation image : ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly resources : requests : memory : \"300Mi\" cpu : \"300m\" limits : memory : \"300Mi\" cpu : \"300m\" envFrom : - configMapRef : name : jans-config-cm args : [ \"patch\" , \"auth\" , \"--opts\" , \"interval:48\" ] restartPolicy : Never Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Cert Manager"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#overview", "text": "Container image to manage X.509 certificates and crypto keys in Janssen Server. The container is designed to run as a one-time command (or Job in Kubernetes world).", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_GOOGLE_SECRET_VERSION_ID : Google Secret Manager version ID (default to latest ). CN_SECRET_GOOGLE_SECRET_NAME_PREFIX : Prefix for Google Secret Manager name (default to jans ). CN_SECRET_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Google Secret Manager (default to secret ). CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_CONTAINER_METADATA : The name of scheduler to pull container metadata (one of docker or kubernetes ; default to docker ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#usage", "text": "", "title": "Usage"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#commands", "text": "The following commands are supported by the container: patch prune", "title": "Commands"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#patch", "text": "Updates X.509 certificates and/or crypto keys related to the service. Usage: certmanager patch [OPTIONS] SERVICE Patch cert and/or crypto keys for the targeted service. Options: --dry-run Enable dryrun mode. --opts KEY:VALUE Options for targeted service (can be set multiple times). -h, --help Show this message and exit. Global options: --dry-run --opts : service-dependent options, example: --opts interval:48 Supported services: web (nginx container or ingress) Load from existing or re-generate: /etc/certs/jans_https.crt /etc/certs/jans_https.key . Options: source : from-files or empty string valid-to : Validity length in days (default to 365 ) auth Re-generate: /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Options: interval : crypto keys expiration time (in hours) push-to-container : whether to push auth-keys.jks and auth-keys.json to auth-server containers (default to true ) key-strategy : key selection strategy (choose one of OLDER , NEWER , FIRST ; default to NEWER ) privkey-push-delay : delay time in seconds before pushing auth-keys.jks to auth containers (default to 0 ) privkey-push-strategy : key selection strategy after auth-keys.jks is pushed to auth containers (choose one of OLDER , NEWER , FIRST ; default to NEWER ) sig-keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) enc-keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP )", "title": "patch"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#prune", "text": "Delete expired crypto keys (if any) related to the service. Usage: certmanager prune [OPTIONS] SERVICE Cleanup expired crypto keys for the targeted service. Options: --dry-run Enable dryrun mode. --opts KEY:VALUE Options for targeted service (can be set multiple times). -h, --help Show this message and exit. Global options: --dry-run --opts : service-dependent options, example: --opts interval:48 Supported services: auth Delete expired keys (if any) from the following files: /etc/certs/auth-keys.json /etc/certs/auth-keys.jks Options: push-to-container : whether to push auth-keys.jks and auth-keys.json to auth containers (default to true ) sig-keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) enc-keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP )", "title": "prune"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#examples", "text": "Kubernetes CronJob example: kind : CronJob apiVersion : batch/v1beta1 metadata : name : auth-key-rotation spec : schedule : \"0 */48 * * *\" concurrencyPolicy : Forbid jobTemplate : spec : template : spec : containers : - name : auth-key-rotation image : ghcr.io/janssenproject/jans/certmanager:0.0.0-nightly resources : requests : memory : \"300Mi\" cpu : \"300m\" limits : memory : \"300Mi\" cpu : \"300m\" envFrom : - configMapRef : name : jans-config-cm args : [ \"patch\" , \"auth\" , \"--opts\" , \"interval:48\" ] restartPolicy : Never", "title": "Examples"}, {"location": "janssen-server/reference/kubernetes/docker-jans-certmanager/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Docker image packaging for config-api. Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault , kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_CONFIG_API_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_CONFIG_API_LOG_LEVEL : Log level for config api. Options include OFF , FATAL , ERROR , WARN , INFO , DEBUG , TRACE . and ALL . This defaults to INFO CN_AUTH_SERVER_URL : Base URL of Janssen Auth server, i.e. auth-server:8080 (default to empty string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CONFIG_API_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_CONFIG_API_PLUGINS : Comma-separated plugin names that should be enabled (available plugins are admin-ui , scim , fido2 , user-mgt , jans-link , kc-saml , kc-link , lock ). Note that unknown plugin name will be ignored. CN_TOKEN_SERVER_BASE_URL : Base URL of token server (default to empty). CN_TOKEN_SERVER_CERT_FILE : Path to token server certificate (default to /etc/certs/token_server.crt ). CN_ADMIN_UI_PLUGIN_LOGGERS : Custom logging configuration for AdminUI plugin in JSON-string format with hash type (see Configure plugin loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file. Configure app loggers # App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"config_api_log_target\" : \"STDOUT\" , \"config_api_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" , \"audit_log_target\" : \"FILE\" , \"audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"config_api_log_target\":\"STDOUT\",\"script_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Configure plugin loggers # Plugin loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"admin_ui_log_target\" : \"FILE\" , \"admin_ui_log_level\" : \"INFO\" , \"admin_ui_audit_log_target\" : \"FILE\" , \"admin_ui_audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"admin_ui_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", } Exposing metrics # As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Config API"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#overview", "text": "Docker image packaging for config-api.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault , kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_CONFIG_API_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). CN_CONFIG_API_LOG_LEVEL : Log level for config api. Options include OFF , FATAL , ERROR , WARN , INFO , DEBUG , TRACE . and ALL . This defaults to INFO CN_AUTH_SERVER_URL : Base URL of Janssen Auth server, i.e. auth-server:8080 (default to empty string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CONFIG_API_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_CONFIG_API_PLUGINS : Comma-separated plugin names that should be enabled (available plugins are admin-ui , scim , fido2 , user-mgt , jans-link , kc-saml , kc-link , lock ). Note that unknown plugin name will be ignored. CN_TOKEN_SERVER_BASE_URL : Base URL of token server (default to empty). CN_TOKEN_SERVER_CERT_FILE : Path to token server certificate (default to /etc/certs/token_server.crt ). CN_ADMIN_UI_PLUGIN_LOGGERS : Custom logging configuration for AdminUI plugin in JSON-string format with hash type (see Configure plugin loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#configure-app-loggers", "text": "App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"config_api_log_target\" : \"STDOUT\" , \"config_api_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" , \"audit_log_target\" : \"FILE\" , \"audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"config_api_log_target\":\"STDOUT\",\"script_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure app loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#configure-plugin-loggers", "text": "Plugin loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"admin_ui_log_target\" : \"FILE\" , \"admin_ui_log_level\" : \"INFO\" , \"admin_ui_audit_log_target\" : \"FILE\" , \"admin_ui_audit_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"admin_ui_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure plugin loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-config-api/#exposing-metrics", "text": "As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Exposing metrics"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Configurator is a tool to load (generate/restore) and/or dump (backup) the configuration (consists of configmaps and secrets). Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CONFIGURATION_SKIP_INITIALIZED : skip initialization if backend already initialized (default to false ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_DOMAIN : Validate certificate is downloaded from given domain. If set to true (default to false ), raise an error if cert is not downloaded. Note that the flag is ignored if mounted SSL cert and key files exist. Commands # The following commands are supported by the container: load dump load # The load command can be used either to generate/restore configmaps and secrets for the cluster. For fresh installation, generate the initial configuration by creating /path/to/host/volume/configuration.json similar to example below: { \"_configmap\" : { \"hostname\" : \"demoexample.jans.io\" , \"country_code\" : \"US\" , \"state\" : \"TX\" , \"city\" : \"Austin\" , \"admin_email\" : \"s@jans.io\" , \"orgName\" : \"Gluu Inc.\" }, \"_secret\" : { \"admin_password\" : \"S3cr3t+pass\" } } NOTE : configuration.json has optional attributes as seen below. _configmap : auth_sig_keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) auth_enc_keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) optional_scopes : list of optional scopes (as JSON string) that will be used (supported scopes are redis , sql ; default to empty list) init_keys_exp : the initial keys expiration time in hours (default to 48 ; extra 1 hour will be added for hard limit) _secret : sql_password : user's password to access SQL database (only used if optional_scopes list contains sql scope) encoded_salt : user-defined salt (24 characters length); if omitted, salt will be generated automatically Example of generating encoded_salt value: # using shell script cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 24 | head -n 1 # output: NFAG5g4R0NSkAZXHL8t2DScL # using python oneliner python -c 'import random, string; print(\"\".join(random.choices(string.ascii_letters + string.digits, k=24)))' # ouput: HsPzqiPkRzNySWlOVui8Ilmw To generate initial configmaps and secrets: Create config map config-generate-params to store the contents of configuration.json kubectl create cm config-generate-params --from-file = configuration.json Mount the configmap into container and apply the yaml: apiVersion : batch/v1 kind : Job metadata : name : configurator-load-job spec : template : spec : restartPolicy : Never volumes : - name : config-generate-params configMap : name : config-generate-params containers : - name : configurator-load image : ghcr.io/janssenproject/jans/configurator:$VERSION volumeMounts : - mountPath : /app/db/configuration.json name : config-generate-params subPath : configuration.json envFrom : - configMapRef : name : config-cm args : [ \"load\" ] A successful load command will dump the pre-populated configuration into /app/db/configuration.out.json . To restore configuration from configuration.out.json file: Create config map config-dump-params : kubectl create cm config-dump-params --from-file = configuration.out.json Mount the configmap into container and apply the yaml: apiVersion : batch/v1 kind : Job metadata : name : configurator-load-job spec : template : spec : restartPolicy : Never volumes : - name : config-dump-params configMap : name : config-dump-params containers : - name : configurator-load image : ghcr.io/janssenproject/jans/configurator:$VERSION volumeMounts : - mountPath : /app/db/configuration.out.json name : config-dump-params subPath : configuration.out.json envFrom : - configMapRef : name : config-cm args : [ \"load\" ] dump # The dump command will dump all configuration from the backends saved into the /app/db/configuration.out.json file. apiVersion : batch/v1 kind : Job metadata : name : configurator-dump-job spec : template : spec : restartPolicy : Never containers : - name : configurator-dump-job image : ghcr.io/janssenproject/jans/configurator:$VERSION command : - /bin/sh - -c - | /app/scripts/entrypoint.sh dump sleep 300 envFrom : - configMapRef : name : config-cm Copy over the files to host kubectl cp configurator-dump-job:/app/db .", "title": "Configurator"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#overview", "text": "Configurator is a tool to load (generate/restore) and/or dump (backup) the configuration (consists of configmaps and secrets).", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default), kubernetes , google , or aws . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , google , or aws . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_CONFIGURATION_SKIP_INITIALIZED : skip initialization if backend already initialized (default to false ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_DOMAIN : Validate certificate is downloaded from given domain. If set to true (default to false ), raise an error if cert is not downloaded. Note that the flag is ignored if mounted SSL cert and key files exist.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#commands", "text": "The following commands are supported by the container: load dump", "title": "Commands"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#load", "text": "The load command can be used either to generate/restore configmaps and secrets for the cluster. For fresh installation, generate the initial configuration by creating /path/to/host/volume/configuration.json similar to example below: { \"_configmap\" : { \"hostname\" : \"demoexample.jans.io\" , \"country_code\" : \"US\" , \"state\" : \"TX\" , \"city\" : \"Austin\" , \"admin_email\" : \"s@jans.io\" , \"orgName\" : \"Gluu Inc.\" }, \"_secret\" : { \"admin_password\" : \"S3cr3t+pass\" } } NOTE : configuration.json has optional attributes as seen below. _configmap : auth_sig_keys : space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) auth_enc_keys : space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) optional_scopes : list of optional scopes (as JSON string) that will be used (supported scopes are redis , sql ; default to empty list) init_keys_exp : the initial keys expiration time in hours (default to 48 ; extra 1 hour will be added for hard limit) _secret : sql_password : user's password to access SQL database (only used if optional_scopes list contains sql scope) encoded_salt : user-defined salt (24 characters length); if omitted, salt will be generated automatically Example of generating encoded_salt value: # using shell script cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 24 | head -n 1 # output: NFAG5g4R0NSkAZXHL8t2DScL # using python oneliner python -c 'import random, string; print(\"\".join(random.choices(string.ascii_letters + string.digits, k=24)))' # ouput: HsPzqiPkRzNySWlOVui8Ilmw To generate initial configmaps and secrets: Create config map config-generate-params to store the contents of configuration.json kubectl create cm config-generate-params --from-file = configuration.json Mount the configmap into container and apply the yaml: apiVersion : batch/v1 kind : Job metadata : name : configurator-load-job spec : template : spec : restartPolicy : Never volumes : - name : config-generate-params configMap : name : config-generate-params containers : - name : configurator-load image : ghcr.io/janssenproject/jans/configurator:$VERSION volumeMounts : - mountPath : /app/db/configuration.json name : config-generate-params subPath : configuration.json envFrom : - configMapRef : name : config-cm args : [ \"load\" ] A successful load command will dump the pre-populated configuration into /app/db/configuration.out.json . To restore configuration from configuration.out.json file: Create config map config-dump-params : kubectl create cm config-dump-params --from-file = configuration.out.json Mount the configmap into container and apply the yaml: apiVersion : batch/v1 kind : Job metadata : name : configurator-load-job spec : template : spec : restartPolicy : Never volumes : - name : config-dump-params configMap : name : config-dump-params containers : - name : configurator-load image : ghcr.io/janssenproject/jans/configurator:$VERSION volumeMounts : - mountPath : /app/db/configuration.out.json name : config-dump-params subPath : configuration.out.json envFrom : - configMapRef : name : config-cm args : [ \"load\" ]", "title": "load"}, {"location": "janssen-server/reference/kubernetes/docker-jans-configurator/#dump", "text": "The dump command will dump all configuration from the backends saved into the /app/db/configuration.out.json file. apiVersion : batch/v1 kind : Job metadata : name : configurator-dump-job spec : template : spec : restartPolicy : Never containers : - name : configurator-dump-job image : ghcr.io/janssenproject/jans/configurator:$VERSION command : - /bin/sh - -c - | /app/scripts/entrypoint.sh dump sleep 300 envFrom : - configMapRef : name : config-cm Copy over the files to host kubectl cp configurator-dump-job:/app/db .", "title": "dump"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Docker image packaging for Fido2. Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_FIDO2_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_FIDO2_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file. Configure app loggers # App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"fido2_log_target\" : \"STDOUT\" , \"fido2_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"fido2_log_target\":\"STDOUT\",\"persistence_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", } Exposing metrics # As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "FIDO2"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#overview", "text": "Docker image packaging for Fido2.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_FIDO2_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_FIDO2_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#configure-app-loggers", "text": "App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"fido2_log_target\" : \"STDOUT\" , \"fido2_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"fido2_log_target\":\"STDOUT\",\"persistence_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure app loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-fido2/#exposing-metrics", "text": "As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Exposing metrics"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/", "tags": ["administration", "installation", "quick-start", "docker compose", "docker image"], "text": "Warning This image is for testing and development purposes only. Use Janssen helm charts for production setups. Overview # Docker monolith image packaging for Janssen. This image packs janssen services including the auth-server, config-api, fido2, and scim. Pre-requisites # Docker Docker compose Environment Variables # Installation depends on the set of environment variables shown below. These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. ENV Description Default CN_HOSTNAME Hostname to install janssen with. demoexample.jans.io CN_ADMIN_PASS Password of the admin user. 1t5Fin3#security CN_ORG_NAME Organization name. Used for ssl cert generation. Janssen CN_EMAIL Email. Used for ssl cert generation. support@jans.io CN_CITY City. Used for ssl cert generation. Austin CN_STATE State. Used for ssl cert generation TX CN_COUNTRY Country. Used for ssl cert generation. US CN_INSTALL_MYSQL Install jans with mysql as the backend false CN_INSTALL_PGSQL Install jans with Postgres as the backend false CN_INSTALL_CONFIG_API Installs the Config API service. true CN_INSTALL_SCIM Installs the SCIM API service. true CN_INSTALL_FIDO2 Installs the FIDO2 API service. true RDBMS_DATABASE RDBMS jans database for MySQL or Postgres. jans RDBMS_USER RDBMS database user for MySQL or Postgres. jans RDBMS_PASSWORD RDBMS database user password for MySQL or Postgres. 1t5Fin3#security RDBMS_HOST RDBMS host for MySQL or Postgres. mysql which is the docker compose service name TEST_CLIENT_ID ID of test client in UUID which has all available scopes to access any jans API 9876baac-de39-4c23-8a78-674b59df8c09 TEST_CLIENT_SECRET Secret for test client 1t5Fin3#security TEST_CLIENT_TRUSTED Trust test client true TEST_CLIENT_REDIRECT_URI Not Implemented yet Redirect URI for test client. Multiple uri's with comma may be provided, if not provided redirect uris will be same as the config-api-client `` How to run # Download the compose file of your chosen persistence from mysql or postgres wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-mysql-compose.yml wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-postgres-compose.yml Download the script files wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/up.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/down.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/clean.sh Give execute permission to the scripts chmod u+x up.sh down.sh clean.sh This docker compose file runs two containers, the janssen monolith container and mysql container. To start the containers. ./up.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. To view the containers running docker compose -f jans-mysql-compose.yml ps To stop the containers. ./down.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. Configure Janssen Server # Access the Docker container shell using: docker compose -f jans-mysql-compose.yml exec jans /bin/bash #This opens a bash terminal in the running container You can grab client_id and client_pw (secret) pairs and other values from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Gluu flex as needed. For example you can run the TUI : python3 /opt/jans/jans-cli/config-cli-tui.py Access endpoints externally # Add to your /etc/hosts file the ip domain record which should be the ip of the instance docker is installed at and the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record you can hit endpoints such as https://demoexample.jans.io/.well-known/openid-configuration Clean up # Remove setup and volumes ./clean.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "Monolith"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#overview", "text": "Docker monolith image packaging for Janssen. This image packs janssen services including the auth-server, config-api, fido2, and scim.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#pre-requisites", "text": "Docker Docker compose", "title": "Pre-requisites"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#environment-variables", "text": "Installation depends on the set of environment variables shown below. These environment variables can be set to customize installation as per the need. If not set, the installer uses default values. ENV Description Default CN_HOSTNAME Hostname to install janssen with. demoexample.jans.io CN_ADMIN_PASS Password of the admin user. 1t5Fin3#security CN_ORG_NAME Organization name. Used for ssl cert generation. Janssen CN_EMAIL Email. Used for ssl cert generation. support@jans.io CN_CITY City. Used for ssl cert generation. Austin CN_STATE State. Used for ssl cert generation TX CN_COUNTRY Country. Used for ssl cert generation. US CN_INSTALL_MYSQL Install jans with mysql as the backend false CN_INSTALL_PGSQL Install jans with Postgres as the backend false CN_INSTALL_CONFIG_API Installs the Config API service. true CN_INSTALL_SCIM Installs the SCIM API service. true CN_INSTALL_FIDO2 Installs the FIDO2 API service. true RDBMS_DATABASE RDBMS jans database for MySQL or Postgres. jans RDBMS_USER RDBMS database user for MySQL or Postgres. jans RDBMS_PASSWORD RDBMS database user password for MySQL or Postgres. 1t5Fin3#security RDBMS_HOST RDBMS host for MySQL or Postgres. mysql which is the docker compose service name TEST_CLIENT_ID ID of test client in UUID which has all available scopes to access any jans API 9876baac-de39-4c23-8a78-674b59df8c09 TEST_CLIENT_SECRET Secret for test client 1t5Fin3#security TEST_CLIENT_TRUSTED Trust test client true TEST_CLIENT_REDIRECT_URI Not Implemented yet Redirect URI for test client. Multiple uri's with comma may be provided, if not provided redirect uris will be same as the config-api-client ``", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#how-to-run", "text": "Download the compose file of your chosen persistence from mysql or postgres wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-mysql-compose.yml wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/jans-postgres-compose.yml Download the script files wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/up.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/down.sh wget https://raw.githubusercontent.com/JanssenProject/jans/main/docker-jans-monolith/clean.sh Give execute permission to the scripts chmod u+x up.sh down.sh clean.sh This docker compose file runs two containers, the janssen monolith container and mysql container. To start the containers. ./up.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql. To view the containers running docker compose -f jans-mysql-compose.yml ps To stop the containers. ./down.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "How to run"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#configure-janssen-server", "text": "Access the Docker container shell using: docker compose -f jans-mysql-compose.yml exec jans /bin/bash #This opens a bash terminal in the running container You can grab client_id and client_pw (secret) pairs and other values from setup.properties or /opt/jans/jans-setup/setup.properties.last Use the CLI tools located under /opt/jans/jans-cli/ to configure Gluu flex as needed. For example you can run the TUI : python3 /opt/jans/jans-cli/config-cli-tui.py", "title": "Configure Janssen Server"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#access-endpoints-externally", "text": "Add to your /etc/hosts file the ip domain record which should be the ip of the instance docker is installed at and the domain used in the env above CN_HOSTNAME . # For-example 172 .22.0.3 demoexample.jans.io After adding the record you can hit endpoints such as https://demoexample.jans.io/.well-known/openid-configuration", "title": "Access endpoints externally"}, {"location": "janssen-server/reference/kubernetes/docker-jans-monolith/#clean-up", "text": "Remove setup and volumes ./clean.sh #You can pass mysql|postgres as an argument to the script. If you don't pass any, it will default to mysql.", "title": "Clean up"}, {"location": "janssen-server/reference/kubernetes/docker-jans-persistence-loader/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Persistence is a special container to load initial data for supported persistence. Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_OXTRUST_CONFIG_GENERATION : Whether to generate oxShibboleth configuration or not (default to true ). CN_CACHE_TYPE : Supported values are IN_MEMORY , REDIS , MEMCACHED , and NATIVE_PERSISTENCE (default to NATIVE_PERSISTENCE ). CN_EXT_SIGNING_JWKS_URI : URI of external signing JWKS (default is \"\"). CN_REDIS_URL : URL of Redis server, format is host:port (optional; default to localhost:6379 ). CN_REDIS_TYPE : Redis service type, either STANDALONE or CLUSTER (optional; default to STANDALONE ). CN_MEMCACHED_URL : URL of Memcache server, format is host:port (optional; default to localhost:11211 ). CN_PERSISTENCE_TYPE : Persistence backend being used ( sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_PERSISTENCE_SKIP_INITIALIZED : skip initialization if backend already initialized (default to false ). CN_PERSISTENCE_UPDATE_AUTH_DYNAMIC_CONFIG : Whether to allow automatic updates of jans-auth configuration (default to true ). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_ADMIN_ID_FILE : Absolute path to file contains ID for admin user (default to /etc/jans/conf/jackrabbit_admin_id ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/gluu/conf/jackrabbit_admin_password ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_MESSAGE_TYPE : Message provider type (one of DISABLED , POSTGRES , and REDIS ; default to DISABLED ). Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Persistence"}, {"location": "janssen-server/reference/kubernetes/docker-jans-persistence-loader/#overview", "text": "Persistence is a special container to load initial data for supported persistence.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-persistence-loader/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-persistence-loader/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_OXTRUST_CONFIG_GENERATION : Whether to generate oxShibboleth configuration or not (default to true ). CN_CACHE_TYPE : Supported values are IN_MEMORY , REDIS , MEMCACHED , and NATIVE_PERSISTENCE (default to NATIVE_PERSISTENCE ). CN_EXT_SIGNING_JWKS_URI : URI of external signing JWKS (default is \"\"). CN_REDIS_URL : URL of Redis server, format is host:port (optional; default to localhost:6379 ). CN_REDIS_TYPE : Redis service type, either STANDALONE or CLUSTER (optional; default to STANDALONE ). CN_MEMCACHED_URL : URL of Memcache server, format is host:port (optional; default to localhost:11211 ). CN_PERSISTENCE_TYPE : Persistence backend being used ( sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_PERSISTENCE_SKIP_INITIALIZED : skip initialization if backend already initialized (default to false ). CN_PERSISTENCE_UPDATE_AUTH_DYNAMIC_CONFIG : Whether to allow automatic updates of jans-auth configuration (default to true ). CN_DOCUMENT_STORE_TYPE : Document store type (one of LOCAL or DB ; default to DB ). CN_JACKRABBIT_URL : URL to remote repository (default to http://localhost:8080 ). CN_JACKRABBIT_ADMIN_ID_FILE : Absolute path to file contains ID for admin user (default to /etc/jans/conf/jackrabbit_admin_id ). CN_JACKRABBIT_ADMIN_PASSWORD_FILE : Absolute path to file contains password for admin user (default to /etc/gluu/conf/jackrabbit_admin_password ). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_MESSAGE_TYPE : Message provider type (one of DISABLED , POSTGRES , and REDIS ; default to DISABLED ).", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-persistence-loader/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/", "tags": ["administration", "reference", "kubernetes", "docker image"], "text": "Overview # Docker image packaging for SCIM. Versions # See Packages for available versions. Environment Variables # The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_SCIM_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SCIM_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file. Configure app loggers # App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"scim_log_target\" : \"STDOUT\" , \"scim_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"scim_log_target\":\"STDOUT\",\"persistence_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true} Hybrid mapping # As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", } Exposing metrics # As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "SCIM"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#overview", "text": "Docker image packaging for SCIM.", "title": "Overview"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#versions", "text": "See Packages for available versions.", "title": "Versions"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#environment-variables", "text": "The following environment variables are supported by the container: CN_CONFIG_ADAPTER : The config backend adapter, can be consul (default) or kubernetes . CN_CONFIG_CONSUL_HOST : hostname or IP of Consul (default to localhost ). CN_CONFIG_CONSUL_PORT : port of Consul (default to 8500 ). CN_CONFIG_CONSUL_CONSISTENCY : Consul consistency mode (choose one of default , consistent , or stale ). Default to stale mode. CN_CONFIG_CONSUL_SCHEME : supported Consul scheme ( http or https ). CN_CONFIG_CONSUL_VERIFY : whether to verify cert or not (default to false ). CN_CONFIG_CONSUL_CACERT_FILE : path to Consul CA cert file (default to /etc/certs/consul_ca.crt ). This file will be used if it exists and CN_CONFIG_CONSUL_VERIFY set to true . CN_CONFIG_CONSUL_CERT_FILE : path to Consul cert file (default to /etc/certs/consul_client.crt ). CN_CONFIG_CONSUL_KEY_FILE : path to Consul key file (default to /etc/certs/consul_client.key ). CN_CONFIG_CONSUL_TOKEN_FILE : path to file contains ACL token (default to /etc/certs/consul_token ). CN_CONFIG_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_CONFIG_KUBERNETES_CONFIGMAP : Kubernetes configmaps name (default to jans ). CN_CONFIG_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_SECRET_ADAPTER : The secrets' adapter, can be vault (default), kubernetes , or google . CN_SECRET_VAULT_VERIFY : whether to verify cert or not (default to false ). CN_SECRET_VAULT_ROLE_ID_FILE : path to file contains Vault AppRole role ID (default to /etc/certs/vault_role_id ). CN_SECRET_VAULT_SECRET_ID_FILE : path to file contains Vault AppRole secret ID (default to /etc/certs/vault_secret_id ). CN_SECRET_VAULT_CERT_FILE : path to Vault cert file (default to /etc/certs/vault_client.crt ). CN_SECRET_VAULT_KEY_FILE : path to Vault key file (default to /etc/certs/vault_client.key ). CN_SECRET_VAULT_CACERT_FILE : path to Vault CA cert file (default to /etc/certs/vault_ca.crt ). This file will be used if it exists and CN_SECRET_VAULT_VERIFY set to true . CN_SECRET_VAULT_ADDR : URL of Vault (default to http://localhost:8200 ). CN_SECRET_VAULT_NAMESPACE : Namespace used to access secrets (default to empty string). CN_SECRET_VAULT_KV_PATH : Path to KV secrets engine (default to secret ). CN_SECRET_VAULT_PREFIX : Base prefix name used to build secret path (default to jans ). CN_SECRET_VAULT_APPROLE_PATH : Path to AppRole (default to approle ). CN_SECRET_KUBERNETES_NAMESPACE : Kubernetes namespace (default to default ). CN_SECRET_KUBERNETES_SECRET : Kubernetes secrets name (default to jans ). CN_SECRET_KUBERNETES_USE_KUBE_CONFIG : Load credentials from $HOME/.kube/config , only useful for non-container environment (default to false ). CN_WAIT_MAX_TIME : How long the startup \"health checks\" should run (default to 300 seconds). CN_WAIT_SLEEP_DURATION : Delay between startup \"health checks\" (default to 10 seconds). CN_MAX_RAM_PERCENTAGE : Value passed to Java option -XX:MaxRAMPercentage . CN_PERSISTENCE_TYPE : Persistence backend being used (one of sql or hybrid ; default to sql ). CN_HYBRID_MAPPING : Specify data mapping for each persistence (default to \"{}\" ). Note this environment only takes effect when CN_PERSISTENCE_TYPE is set to hybrid . See hybrid mapping section for details. CN_SCIM_JAVA_OPTIONS : Java options passed to entrypoint, i.e. -Xmx1024m (default to empty-string). GOOGLE_APPLICATION_CREDENTIALS : Optional JSON file (contains Google credentials) that can be injected into container for authentication. Refer to https://cloud.google.com/docs/authentication/provide-credentials-adc#how-to for supported credentials. GOOGLE_PROJECT_ID : ID of Google project. CN_GOOGLE_SECRET_VERSION_ID : Janssen secret version ID in Google Secret Manager. Defaults to latest , which is recommended. CN_GOOGLE_SECRET_NAME_PREFIX : Prefix for Janssen secret in Google Secret Manager. Defaults to jans . If left jans-secret secret will be created. CN_GOOGLE_SECRET_MANAGER_PASSPHRASE : Passphrase for Janssen secret in Google Secret Manager. This is recommended to be changed and defaults to secret . CN_SCIM_APP_LOGGERS : Custom logging configuration in JSON-string format with hash type (see Configure app loggers section for details). CN_PROMETHEUS_PORT : Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. See Exposing metrics for details. CN_SQL_DB_HOST : Hostname of the SQL database (default to localhost ). CN_SQL_DB_PORT : Port of the SQL database (default to 3306 for MySQL). CN_SQL_DB_NAME : SQL database name (default to jans ). CN_SQL_DB_USER : User name to access the SQL database (default to jans ). CN_SQL_DB_DIALECT : Dialect name of the SQL ( mysql for MySQL or pgsql for PostgreSQL; default to mysql ). CN_SQL_DB_TIMEZONE : Timezone used by the SQL database (default to UTC ). CN_SQL_DB_SCHEMA : Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). CN_AWS_SECRETS_ENDPOINT_URL : The URL of AWS secretsmanager service (if omitted, will use the one in specified region). CN_AWS_SECRETS_PREFIX : The prefix name of the secrets (default to jans ). CN_AWS_SECRETS_REPLICA_FILE : The location of file contains replica regions definition (if any). This file is mostly used in primary region. Example of contents of the file: [{\"Region\": \"us-west-1\"}] . AWS_DEFAULT_REGION : The default AWS Region to use, for example, us-west-1 or us-west-2 . AWS_SHARED_CREDENTIALS_FILE : The location of the shared credentials file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_CONFIG_FILE : The location of the config file used by the client (see https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). AWS_PROFILE : The default profile to use, if any. CN_SSL_CERT_FROM_SECRETS : Determine whether to get SSL cert from secrets backend (default to true ). Note that the flag will take effect only if there's no mounted /etc/certs/web_https.crt file.", "title": "Environment Variables"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#configure-app-loggers", "text": "App loggers can be configured to define where the logs will be redirected and what is the level the logs should be displayed. Supported redirect target: STDOUT FILE Supported level: FATAL ERROR WARN INFO DEBUG TRACE The following key-value pairs are the defaults: { \"scim_log_target\" : \"STDOUT\" , \"scim_log_level\" : \"INFO\" , \"persistence_log_target\" : \"FILE\" , \"persistence_log_level\" : \"INFO\" , \"persistence_duration_log_target\" : \"FILE\" , \"persistence_duration_log_level\" : \"INFO\" , \"script_log_target\" : \"FILE\" , \"script_log_level\" : \"INFO\" } To enable prefix on STDOUT logging, set the enable_stdout_log_prefix key. Example: {\"scim_log_target\":\"STDOUT\",\"persistence_log_target\":\"STDOUT\",\"enable_stdout_log_prefix\":true}", "title": "Configure app loggers"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#hybrid-mapping", "text": "As per v1.0.1, hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below: Set CN_PERSISTENCE_TYPE environment variable to hybrid Set CN_HYBRID_MAPPING with the following format: { \"default\": \"<sql>\", \"user\": \"<sql>\", \"site\": \"<sql>\", \"cache\": \"<sql>\", \"token\": \"<sql>\", \"session\": \"<sql>\", } Example: { \"default\": \"sql\", \"user\": \"sql\", \"site\": \"sql\", \"cache\": \"sql\", \"token\": \"sql\", \"session\": \"sql\", }", "title": "Hybrid mapping"}, {"location": "janssen-server/reference/kubernetes/docker-jans-scim/#exposing-metrics", "text": "As per v1.0.1, certain metrics can be exposed via Prometheus JMX exporter. To expose the metrics, set the CN_PROMETHEUS_PORT environment variable, i.e. CN_PROMETHEUS_PORT=9093 . Afterwards, metrics can be scraped by Prometheus or accessed manually by making request to /metrics URL, i.e. http://container:9093/metrics . Note that Prometheus JMX exporter uses pre-defined config file (see conf/prometheus-config.yaml ). To customize the config, mount custom config file to /opt/prometheus/prometheus-config.yaml inside the container.", "title": "Exposing metrics"}, {"location": "janssen-server/reference/kubernetes/helm-chart/", "tags": ["administration", "reference", "kubernetes"], "text": "janssen # Janssen Access and Identity Management Microservices Chart. This chart deploys each janssen microservice as a separate deployment. Homepage: https://jans.io Maintainers # Name Email Url moabu support@jans.io Source Code # https://jans.io https://github.com/JanssenProject/jans/charts/janssen Requirements # Kubernetes: >=v1.22.0-0 Repository Name Version auth-server 0.0.0-nightly auth-server-key-rotation 0.0.0-nightly casa 0.0.0-nightly cn-istio-ingress 0.0.0-nightly config 0.0.0-nightly config-api 0.0.0-nightly fido2 0.0.0-nightly kc-scheduler 0.0.0-nightly link 0.0.0-nightly nginx-ingress 0.0.0-nightly persistence 0.0.0-nightly saml 0.0.0-nightly scim 0.0.0-nightly Values # Key Type Default Description auth-server object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/auth-server\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"},\"requests\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} OAuth Authorization Server, the OpenID Connect Provider, the UMA Authorization Server--this is the main Internet facing component of Janssen. It's the service that returns tokens, JWT's and identity assertions. This service must be Internet facing. auth-server-key-rotation object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/certmanager\",\"tag\":\"0.0.0-nightly\"},\"keysLife\":48,\"keysPushDelay\":0,\"keysPushStrategy\":\"NEWER\",\"keysStrategy\":\"NEWER\",\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Responsible for regenerating auth-keys per x hours auth-server-key-rotation.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of auth-server-key-rotation.additionalLabels object {} Additional labels that will be added across the gateway in the format of auth-server-key-rotation.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. auth-server-key-rotation.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh auth-server-key-rotation.dnsConfig object {} Add custom dns config auth-server-key-rotation.dnsPolicy string \"\" Add custom dns policy auth-server-key-rotation.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. auth-server-key-rotation.image.pullSecrets list [] Image Pull Secrets auth-server-key-rotation.image.repository string \"ghcr.io/janssenproject/jans/certmanager\" Image to use for deploying. auth-server-key-rotation.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. auth-server-key-rotation.keysLife int 48 Auth server key rotation keys life in hours auth-server-key-rotation.keysPushDelay int 0 Delay (in seconds) before pushing private keys to Auth server auth-server-key-rotation.keysPushStrategy string \"NEWER\" Set key selection strategy after pushing private keys to Auth server (only takes effect when keysPushDelay value is greater than 0) auth-server-key-rotation.keysStrategy string \"NEWER\" Set key selection strategy used by Auth server auth-server-key-rotation.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. auth-server-key-rotation.resources.limits.cpu string \"300m\" CPU limit. auth-server-key-rotation.resources.limits.memory string \"300Mi\" Memory limit. auth-server-key-rotation.resources.requests.cpu string \"300m\" CPU request. auth-server-key-rotation.resources.requests.memory string \"300Mi\" Memory request. auth-server-key-rotation.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service auth-server-key-rotation.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 auth-server-key-rotation.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 auth-server-key-rotation.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers auth-server-key-rotation.volumes list [] Configure any additional volumes that need to be attached to the pod auth-server.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of auth-server.additionalLabels object {} Additional labels that will be added across the gateway in the format of auth-server.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. auth-server.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh auth-server.dnsConfig object {} Add custom dns config auth-server.dnsPolicy string \"\" Add custom dns policy auth-server.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler auth-server.hpa.behavior object {} Scaling Policies auth-server.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set auth-server.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. auth-server.image.pullSecrets list [] Image Pull Secrets auth-server.image.repository string \"ghcr.io/janssenproject/jans/auth-server\" Image to use for deploying. auth-server.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. auth-server.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. auth-server.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} Executes the python3 healthcheck. https://github.com/JanssenProject/docker-jans-auth-server/blob/master/scripts/healthcheck.py auth-server.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget auth-server.readinessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the readiness healthcheck for the auth server if needed. https://github.com/JanssenProject/docker-jans-auth-server/blob/master/scripts/healthcheck.py auth-server.replicas int 1 Service replica number. auth-server.resources object {\"limits\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"},\"requests\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"}} Resource specs. auth-server.resources.limits.cpu string \"2500m\" CPU limit. auth-server.resources.limits.memory string \"2500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. auth-server.resources.requests.cpu string \"2500m\" CPU request. auth-server.resources.requests.memory string \"2500Mi\" Memory request. auth-server.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ auth-server.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service auth-server.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 auth-server.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 auth-server.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers auth-server.volumes list [] Configure any additional volumes that need to be attached to the pod casa object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/casa\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Janssen Casa (\"Casa\") is a self-service web portal for end-users to manage authentication and authorization preferences for their account in a Janssen Auth Server. casa.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of casa.additionalLabels object {} Additional labels that will be added across the gateway in the format of casa.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. casa.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh casa.dnsConfig object {} Add custom dns config casa.dnsPolicy string \"\" Add custom dns policy casa.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler casa.hpa.behavior object {} Scaling Policies casa.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set casa.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. casa.image.pullSecrets list [] Image Pull Secrets casa.image.repository string \"ghcr.io/janssenproject/jans/casa\" Image to use for deploying. casa.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. casa.livenessProbe object {\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the liveness healthcheck for casa if needed. casa.livenessProbe.httpGet.path string \"/jans-casa/health-check\" http liveness probe endpoint casa.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget casa.readinessProbe object {\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the readiness healthcheck for the casa if needed. casa.readinessProbe.httpGet.path string \"/jans-casa/health-check\" http readiness probe endpoint casa.replicas int 1 Service replica number. casa.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}} Resource specs. casa.resources.limits.cpu string \"500m\" CPU limit. casa.resources.limits.memory string \"500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. casa.resources.requests.cpu string \"500m\" CPU request. casa.resources.requests.memory string \"500Mi\" Memory request. casa.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ casa.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service casa.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 casa.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 casa.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers casa.volumes list [] Configure any additional volumes that need to be attached to the pod config object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"adminPassword\":\"Test1234#\",\"city\":\"Austin\",\"configmap\":{\"cnAwsAccessKeyId\":\"\",\"cnAwsDefaultRegion\":\"us-west-1\",\"cnAwsProfile\":\"janssen\",\"cnAwsSecretAccessKey\":\"\",\"cnAwsSecretsEndpointUrl\":\"\",\"cnAwsSecretsNamePrefix\":\"janssen\",\"cnAwsSecretsReplicaRegions\":[],\"cnCacheType\":\"NATIVE_PERSISTENCE\",\"cnConfigKubernetesConfigMap\":\"cn\",\"cnGoogleProjectId\":\"google-project-to-save-config-and-secrets-to\",\"cnGoogleSecretManagerServiceAccount\":\"SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo=\",\"cnGoogleSecretNamePrefix\":\"janssen\",\"cnGoogleSecretVersionId\":\"latest\",\"cnJettyRequestHeaderSize\":8192,\"cnMaxRamPercent\":\"75.0\",\"cnMessageType\":\"DISABLED\",\"cnOpaUrl\":\"http://opa.opa.svc.cluster.cluster.local:8181/v1\",\"cnPersistenceHybridMapping\":\"{}\",\"cnRedisSentinelGroup\":\"\",\"cnRedisSslTruststore\":\"\",\"cnRedisType\":\"STANDALONE\",\"cnRedisUrl\":\"redis.redis.svc.cluster.local:6379\",\"cnRedisUseSsl\":false,\"cnScimProtectionMode\":\"OAUTH\",\"cnSecretKubernetesSecret\":\"cn\",\"cnSqlDbDialect\":\"mysql\",\"cnSqlDbHost\":\"my-release-mysql.default.svc.cluster.local\",\"cnSqlDbName\":\"jans\",\"cnSqlDbPort\":3306,\"cnSqlDbSchema\":\"\",\"cnSqlDbTimezone\":\"UTC\",\"cnSqlDbUser\":\"jans\",\"cnSqldbUserPassword\":\"Test1234#\",\"cnVaultAddr\":\"http://localhost:8200\",\"cnVaultAppRolePath\":\"approle\",\"cnVaultKvPath\":\"secret\",\"cnVaultNamespace\":\"\",\"cnVaultPrefix\":\"jans\",\"cnVaultRoleId\":\"\",\"cnVaultRoleIdFile\":\"/etc/certs/vault_role_id\",\"cnVaultSecretId\":\"\",\"cnVaultSecretIdFile\":\"/etc/certs/vault_secret_id\",\"cnVaultVerify\":false,\"kcAdminPassword\":\"Test1234#\",\"kcAdminUsername\":\"admin\",\"kcDbPassword\":\"Test1234#\",\"kcDbSchema\":\"keycloak\",\"kcDbUrlDatabase\":\"keycloak\",\"kcDbUrlHost\":\"mysql.kc.svc.cluster.local\",\"kcDbUrlPort\":3306,\"kcDbUrlProperties\":\"?useUnicode=true&characterEncoding=UTF-8&character_set_server=utf8mb4\",\"kcDbUsername\":\"keycloak\",\"kcDbVendor\":\"mysql\",\"kcLogLevel\":\"INFO\",\"lbAddr\":\"\",\"quarkusTransactionEnableRecovery\":true},\"countryCode\":\"US\",\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"email\":\"support@jans.io\",\"image\":{\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/configurator\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"orgName\":\"Janssen\",\"redisPassword\":\"P@assw0rd\",\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"salt\":\"\",\"state\":\"TX\",\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Configuration parameters for setup and initial configuration secret and config layers used by Janssen services. config-api object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/config-api\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"jans-config-api/api/v1/health/ready\",\"port\":8074},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Config Api endpoints can be used to configure the auth-server, which is an open-source OpenID Connect Provider (OP) and UMA Authorization Server (AS). config-api.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of config-api.additionalLabels object {} Additional labels that will be added across the gateway in the format of config-api.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. config-api.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh config-api.dnsConfig object {} Add custom dns config config-api.dnsPolicy string \"\" Add custom dns policy config-api.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler config-api.hpa.behavior object {} Scaling Policies config-api.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set config-api.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. config-api.image.pullSecrets list [] Image Pull Secrets config-api.image.repository string \"ghcr.io/janssenproject/jans/config-api\" Image to use for deploying. config-api.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. config-api.livenessProbe object {\"httpGet\":{\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. config-api.livenessProbe.httpGet object {\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074} http liveness probe endpoint config-api.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget config-api.readinessProbe.httpGet object {\"path\":\"jans-config-api/api/v1/health/ready\",\"port\":8074} http readiness probe endpoint config-api.replicas int 1 Service replica number. config-api.resources object {\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}} Resource specs. config-api.resources.limits.cpu string \"1000m\" CPU limit. config-api.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. config-api.resources.requests.cpu string \"1000m\" CPU request. config-api.resources.requests.memory string \"1200Mi\" Memory request. config-api.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ config-api.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service config-api.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 config-api.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 config-api.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers config-api.volumes list [] Configure any additional volumes that need to be attached to the pod config.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of config.adminPassword string \"Test1234#\" Admin password to log in to the UI. config.city string \"Austin\" City. Used for certificate creation. config.configmap.cnCacheType string \"NATIVE_PERSISTENCE\" Cache type. NATIVE_PERSISTENCE , REDIS . or IN_MEMORY . Defaults to NATIVE_PERSISTENCE . config.configmap.cnConfigKubernetesConfigMap string \"cn\" The name of the Kubernetes ConfigMap that will hold the configuration layer config.configmap.cnGoogleProjectId string \"google-project-to-save-config-and-secrets-to\" Project id of the Google project the secret manager belongs to. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretManagerServiceAccount string \"SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo=\" Service account with roles roles/secretmanager.admin base64 encoded string. This is used often inside the services to reach the configuration layer. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretNamePrefix string \"janssen\" Prefix for Janssen secret in Google Secret Manager. Defaults to janssen. If left janssen-secret secret will be created. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretVersionId string \"latest\" Secret version to be used for secret configuration. Defaults to latest and should normally always stay that way. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnJettyRequestHeaderSize int 8192 Jetty header size in bytes in the auth server config.configmap.cnMaxRamPercent string \"75.0\" Value passed to Java option -XX:MaxRAMPercentage config.configmap.cnMessageType string \"DISABLED\" Message type (one of POSTGRES, REDIS, or DISABLED) config.configmap.cnOpaUrl string \"http://opa.opa.svc.cluster.cluster.local:8181/v1\" URL of OPA API config.configmap.cnPersistenceHybridMapping string \"{}\" Specify data that should be saved in persistence (one of default, user, cache, site, token, or session; default to default). Note this environment only takes effect when global.cnPersistenceType is set to hybrid . config.configmap.cnRedisSentinelGroup string \"\" Redis Sentinel Group. Often set when config.configmap.cnRedisType is set to SENTINEL . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisSslTruststore string \"\" Redis SSL truststore. Optional. Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisType string \"STANDALONE\" Redis service type. STANDALONE or CLUSTER . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisUrl string \"redis.redis.svc.cluster.local:6379\" Redis URL and port number : . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisUseSsl bool false Boolean to use SSL in Redis. Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnScimProtectionMode string \"OAUTH\" SCIM protection mode OAUTH config.configmap.cnSecretKubernetesSecret string \"cn\" Kubernetes secret name holding configuration keys. Used when global.configSecretAdapter is set to kubernetes which is the default. config.configmap.cnSqlDbDialect string \"mysql\" SQL database dialect. mysql or pgsql config.configmap.cnSqlDbHost string \"my-release-mysql.default.svc.cluster.local\" SQL database host uri. config.configmap.cnSqlDbName string \"jans\" SQL database name. config.configmap.cnSqlDbPort int 3306 SQL database port. config.configmap.cnSqlDbSchema string \"\" Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). config.configmap.cnSqlDbTimezone string \"UTC\" SQL database timezone. config.configmap.cnSqlDbUser string \"jans\" SQL database username. config.configmap.cnSqldbUserPassword string \"Test1234#\" SQL password injected the secrets . config.configmap.cnVaultAddr string \"http://localhost:8200\" Base URL of Vault. config.configmap.cnVaultAppRolePath string \"approle\" Path to Vault AppRole. config.configmap.cnVaultKvPath string \"secret\" Path to Vault KV secrets engine. config.configmap.cnVaultNamespace string \"\" Vault namespace used to access the secrets. config.configmap.cnVaultPrefix string \"jans\" Base prefix name used to access secrets. config.configmap.cnVaultRoleId string \"\" Vault AppRole RoleID. config.configmap.cnVaultRoleIdFile string \"/etc/certs/vault_role_id\" Path to file contains Vault AppRole role ID. config.configmap.cnVaultSecretId string \"\" Vault AppRole SecretID. config.configmap.cnVaultSecretIdFile string \"/etc/certs/vault_secret_id\" Path to file contains Vault AppRole secret ID. config.configmap.cnVaultVerify bool false Verify connection to Vault. config.configmap.kcAdminPassword string \"Test1234#\" Keycloak admin UI password config.configmap.kcAdminUsername string \"admin\" Keycloak admin UI username config.configmap.kcDbPassword string \"Test1234#\" Password for Keycloak database access config.configmap.kcDbSchema string \"keycloak\" Keycloak database schema name (note that PostgreSQL may be using \"public\" schema). config.configmap.kcDbUrlDatabase string \"keycloak\" Keycloak database name. config.configmap.kcDbUrlHost string \"mysql.kc.svc.cluster.local\" Keycloak database host uri config.configmap.kcDbUrlPort int 3306 Keycloak database port (default to port 3306 for mysql). config.configmap.kcDbUrlProperties string \"?useUnicode=true&characterEncoding=UTF-8&character_set_server=utf8mb4\" Keycloak database connection properties. If using postgresql, the value can be set to empty string. config.configmap.kcDbUsername string \"keycloak\" Keycloak database username config.configmap.kcDbVendor string \"mysql\" Keycloak database vendor name (default to MySQL server). To use PostgreSQL server, change the value to postgres. config.configmap.kcLogLevel string \"INFO\" Keycloak logging level config.configmap.lbAddr string \"\" Load balancer address for AWS if the FQDN is not registered. config.configmap.quarkusTransactionEnableRecovery bool true Quarkus transaction recovery. When using MySQL, there could be issue regarding XA_RECOVER_ADMIN; refer to https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_xa-recover-admin for details. config.countryCode string \"US\" Country code. Used for certificate creation. config.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. config.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh config.dnsConfig object {} Add custom dns config config.dnsPolicy string \"\" Add custom dns policy config.email string \"support@jans.io\" Email address of the administrator usually. Used for certificate creation. config.image.pullSecrets list [] Image Pull Secrets config.image.repository string \"ghcr.io/janssenproject/jans/configurator\" Image to use for deploying. config.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. config.orgName string \"Janssen\" Organization name. Used for certificate creation. config.redisPassword string \"P@assw0rd\" Redis admin password if config.configmap.cnCacheType is set to REDIS . config.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. config.resources.limits.cpu string \"300m\" CPU limit. config.resources.limits.memory string \"300Mi\" Memory limit. config.resources.requests.cpu string \"300m\" CPU request. config.resources.requests.memory string \"300Mi\" Memory request. config.salt string \"\" Salt. Used for encoding/decoding sensitive data. If omitted or set to empty string, the value will be self-generated. Otherwise, a 24 alphanumeric characters are allowed as its value. config.state string \"TX\" State code. Used for certificate creation. config.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service. config.usrEnvs.normal object {} Add custom normal envs to the service. variable1: value1 config.usrEnvs.secret object {} Add custom secret envs to the service. variable1: value1 config.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers config.volumes list [] Configure any additional volumes that need to be attached to the pod fido2 object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/fido2\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}},\"service\":{\"name\":\"http-fido2\",\"port\":8080},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} FIDO 2.0 (FIDO2) is an open authentication standard that enables leveraging common devices to authenticate to online services in both mobile and desktop environments. fido2.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of fido2.additionalLabels object {} Additional labels that will be added across the gateway in the format of fido2.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. fido2.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh fido2.dnsConfig object {} Add custom dns config fido2.dnsPolicy string \"\" Add custom dns policy fido2.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler fido2.hpa.behavior object {} Scaling Policies fido2.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set fido2.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. fido2.image.pullSecrets list [] Image Pull Secrets fido2.image.repository string \"ghcr.io/janssenproject/jans/fido2\" Image to use for deploying. fido2.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. fido2.livenessProbe object {\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the liveness healthcheck for the fido2 if needed. fido2.livenessProbe.httpGet object {\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"} http liveness probe endpoint fido2.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget fido2.readinessProbe object {\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the readiness healthcheck for the fido2 if needed. fido2.replicas int 1 Service replica number. fido2.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}} Resource specs. fido2.resources.limits.cpu string \"500m\" CPU limit. fido2.resources.limits.memory string \"500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. fido2.resources.requests.cpu string \"500m\" CPU request. fido2.resources.requests.memory string \"500Mi\" Memory request. fido2.service.name string \"http-fido2\" The name of the fido2 port within the fido2 service. Please keep it as default. fido2.service.port int 8080 Port of the fido2 service. Please keep it as default. fido2.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ fido2.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service fido2.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 fido2.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 fido2.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers fido2.volumes list [] Configure any additional volumes that need to be attached to the pod global object {\"alb\":{\"ingress\":false},\"auth-server\":{\"appLoggers\":{\"auditStatsLogLevel\":\"INFO\",\"auditStatsLogTarget\":\"FILE\",\"authLogLevel\":\"INFO\",\"authLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"httpLogLevel\":\"INFO\",\"httpLogTarget\":\"FILE\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"authEncKeys\":\"RSA1_5 RSA-OAEP\",\"authServerServiceName\":\"auth-server\",\"authSigKeys\":\"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\",\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"authServerAdditionalAnnotations\":{},\"authServerEnabled\":true,\"authServerLabels\":{},\"deviceCodeAdditionalAnnotations\":{},\"deviceCodeEnabled\":true,\"deviceCodeLabels\":{},\"firebaseMessagingAdditionalAnnotations\":{},\"firebaseMessagingEnabled\":true,\"firebaseMessagingLabels\":{},\"lockAdditionalAnnotations\":{},\"lockConfigAdditionalAnnotations\":{},\"lockConfigEnabled\":false,\"lockConfigLabels\":{},\"lockEnabled\":false,\"lockLabels\":{},\"openidAdditionalAnnotations\":{},\"openidConfigEnabled\":true,\"openidConfigLabels\":{},\"u2fAdditionalAnnotations\":{},\"u2fConfigEnabled\":true,\"u2fConfigLabels\":{},\"uma2AdditionalAnnotations\":{},\"uma2ConfigEnabled\":true,\"uma2ConfigLabels\":{},\"webdiscoveryAdditionalAnnotations\":{},\"webdiscoveryEnabled\":true,\"webdiscoveryLabels\":{},\"webfingerAdditionalAnnotations\":{},\"webfingerEnabled\":true,\"webfingerLabels\":{}},\"lockEnabled\":false},\"auth-server-key-rotation\":{\"customAnnotations\":{\"cronjob\":{},\"secret\":{},\"service\":{}},\"enabled\":true,\"initKeysLife\":48},\"awsStorageType\":\"io1\",\"azureStorageAccountType\":\"Standard_LRS\",\"azureStorageKind\":\"Managed\",\"casa\":{\"appLoggers\":{\"casaLogLevel\":\"INFO\",\"casaLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"timerLogLevel\":\"INFO\",\"timerLogTarget\":\"FILE\"},\"casaServiceName\":\"casa\",\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"casaAdditionalAnnotations\":{},\"casaEnabled\":false,\"casaLabels\":{}}},\"cloud\":{\"testEnviroment\":false},\"cnAwsConfigFile\":\"/etc/jans/conf/aws_config_file\",\"cnAwsSecretsReplicaRegionsFile\":\"/etc/jans/conf/aws_secrets_replica_regions\",\"cnAwsSharedCredentialsFile\":\"/etc/jans/conf/aws_shared_credential_file\",\"cnConfiguratorConfigurationFile\":\"/etc/jans/conf/configuration.json\",\"cnConfiguratorCustomSchema\":{\"secretName\":\"\"},\"cnConfiguratorDumpFile\":\"/etc/jans/conf/configuration.out.json\",\"cnDocumentStoreType\":\"DB\",\"cnGoogleApplicationCredentials\":\"/etc/jans/conf/google-credentials.json\",\"cnPersistenceType\":\"sql\",\"cnPrometheusPort\":\"\",\"cnSqlPasswordFile\":\"/etc/jans/conf/sql_password\",\"config\":{\"customAnnotations\":{\"clusterRoleBinding\":{},\"configMap\":{},\"job\":{},\"role\":{},\"roleBinding\":{},\"secret\":{},\"service\":{},\"serviceAccount\":{}},\"enabled\":true},\"config-api\":{\"appLoggers\":{\"configApiLogLevel\":\"INFO\",\"configApiLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"configApiServerServiceName\":\"config-api\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"configApiAdditionalAnnotations\":{},\"configApiEnabled\":true,\"configApiLabels\":{}},\"plugins\":\"fido2,scim,user-mgt\"},\"configAdapterName\":\"kubernetes\",\"configSecretAdapter\":\"kubernetes\",\"fido2\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"fido2LogLevel\":\"INFO\",\"fido2LogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"fido2ServiceName\":\"fido2\",\"ingress\":{\"fido2AdditionalAnnotations\":{},\"fido2ConfigAdditionalAnnotations\":{},\"fido2ConfigEnabled\":false,\"fido2ConfigLabels\":{},\"fido2Enabled\":false,\"fido2Labels\":{}}},\"fqdn\":\"demoexample.jans.io\",\"gcePdStorageType\":\"pd-standard\",\"isFqdnRegistered\":false,\"istio\":{\"additionalAnnotations\":{},\"additionalLabels\":{},\"enabled\":false,\"gateways\":[],\"ingress\":false,\"namespace\":\"istio-system\"},\"jobTtlSecondsAfterFinished\":300,\"kc-scheduler\":{\"enabled\":false},\"lbIp\":\"22.22.22.22\",\"link\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"linkLogLevel\":\"INFO\",\"linkLogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"service\":{},\"virtualService\":{}},\"enabled\":false,\"ingress\":{\"linkEnabled\":true},\"linkServiceName\":\"link\"},\"nginx-ingress\":{\"enabled\":true},\"persistence\":{\"customAnnotations\":{\"job\":{},\"secret\":{},\"service\":{}},\"enabled\":true},\"saml\":{\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":false,\"ingress\":{\"samlAdditionalAnnotations\":{},\"samlEnabled\":false,\"samlLabels\":{}},\"samlServiceName\":\"saml\"},\"scim\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scimLogLevel\":\"INFO\",\"scimLogTarget\":\"STDOUT\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"scimAdditionalAnnotations\":{},\"scimConfigAdditionalAnnotations\":{},\"scimConfigEnabled\":false,\"scimConfigLabels\":{},\"scimEnabled\":false,\"scimLabels\":{}},\"scimServiceName\":\"scim\"},\"serviceAccountName\":\"default\",\"storageClass\":{\"allowVolumeExpansion\":true,\"allowedTopologies\":[],\"mountOptions\":[\"debug\"],\"parameters\":{},\"provisioner\":\"microk8s.io/hostpath\",\"reclaimPolicy\":\"Retain\",\"volumeBindingMode\":\"WaitForFirstConsumer\"},\"usrEnvs\":{\"normal\":{},\"secret\":{}}} Parameters used globally across all services helm charts. global.alb.ingress bool false Activates ALB ingress global.auth-server-key-rotation.enabled bool true Boolean flag to enable/disable the auth-server-key rotation cronjob chart. global.auth-server-key-rotation.initKeysLife int 48 The initial auth server key rotation keys life in hours global.auth-server.appLoggers object {\"auditStatsLogLevel\":\"INFO\",\"auditStatsLogTarget\":\"FILE\",\"authLogLevel\":\"INFO\",\"authLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"httpLogLevel\":\"INFO\",\"httpLogTarget\":\"FILE\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.auth-server.appLoggers.auditStatsLogLevel string \"INFO\" jans-auth_audit.log level global.auth-server.appLoggers.auditStatsLogTarget string \"FILE\" jans-auth_script.log target global.auth-server.appLoggers.authLogLevel string \"INFO\" jans-auth.log level global.auth-server.appLoggers.authLogTarget string \"STDOUT\" jans-auth.log target global.auth-server.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e auth-server-script ===> 2022-12-20 17:49:55,744 INFO global.auth-server.appLoggers.httpLogLevel string \"INFO\" http_request_response.log level global.auth-server.appLoggers.httpLogTarget string \"FILE\" http_request_response.log target global.auth-server.appLoggers.persistenceDurationLogLevel string \"INFO\" jans-auth_persistence_duration.log level global.auth-server.appLoggers.persistenceDurationLogTarget string \"FILE\" jans-auth_persistence_duration.log target global.auth-server.appLoggers.persistenceLogLevel string \"INFO\" jans-auth_persistence.log level global.auth-server.appLoggers.persistenceLogTarget string \"FILE\" jans-auth_persistence.log target global.auth-server.appLoggers.scriptLogLevel string \"INFO\" jans-auth_script.log level global.auth-server.appLoggers.scriptLogTarget string \"FILE\" jans-auth_script.log target global.auth-server.authEncKeys string \"RSA1_5 RSA-OAEP\" space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) global.auth-server.authServerServiceName string \"auth-server\" Name of the auth-server service. Please keep it as default. global.auth-server.authSigKeys string \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) global.auth-server.cnCustomJavaOptions string \"\" passing custom java options to auth-server. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.auth-server.enabled bool true Boolean flag to enable/disable auth-server chart. You should never set this to false. global.auth-server.ingress object {\"authServerAdditionalAnnotations\":{},\"authServerEnabled\":true,\"authServerLabels\":{},\"deviceCodeAdditionalAnnotations\":{},\"deviceCodeEnabled\":true,\"deviceCodeLabels\":{},\"firebaseMessagingAdditionalAnnotations\":{},\"firebaseMessagingEnabled\":true,\"firebaseMessagingLabels\":{},\"lockAdditionalAnnotations\":{},\"lockConfigAdditionalAnnotations\":{},\"lockConfigEnabled\":false,\"lockConfigLabels\":{},\"lockEnabled\":false,\"lockLabels\":{},\"openidAdditionalAnnotations\":{},\"openidConfigEnabled\":true,\"openidConfigLabels\":{},\"u2fAdditionalAnnotations\":{},\"u2fConfigEnabled\":true,\"u2fConfigLabels\":{},\"uma2AdditionalAnnotations\":{},\"uma2ConfigEnabled\":true,\"uma2ConfigLabels\":{},\"webdiscoveryAdditionalAnnotations\":{},\"webdiscoveryEnabled\":true,\"webdiscoveryLabels\":{},\"webfingerAdditionalAnnotations\":{},\"webfingerEnabled\":true,\"webfingerLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.auth-server.ingress.authServerAdditionalAnnotations object {} Auth server ingress resource additional annotations. global.auth-server.ingress.authServerEnabled bool true Enable Auth server endpoints /jans-auth global.auth-server.ingress.authServerLabels object {} Auth server ingress resource labels. key app is taken global.auth-server.ingress.deviceCodeAdditionalAnnotations object {} device-code ingress resource additional annotations. global.auth-server.ingress.deviceCodeEnabled bool true Enable endpoint /device-code global.auth-server.ingress.deviceCodeLabels object {} device-code ingress resource labels. key app is taken global.auth-server.ingress.firebaseMessagingAdditionalAnnotations object {} Firebase Messaging ingress resource additional annotations. global.auth-server.ingress.firebaseMessagingEnabled bool true Enable endpoint /firebase-messaging-sw.js global.auth-server.ingress.firebaseMessagingLabels object {} Firebase Messaging ingress resource labels. key app is taken global.auth-server.ingress.lockAdditionalAnnotations object {} Lock ingress resource additional annotations. global.auth-server.ingress.lockConfigAdditionalAnnotations object {} Lock config ingress resource additional annotations. global.auth-server.ingress.lockConfigEnabled bool false Enable endpoint /.well-known/lock-server-configuration global.auth-server.ingress.lockConfigLabels object {} Lock config ingress resource labels. key app is taken global.auth-server.ingress.lockEnabled bool false Enable endpoint /jans-lock global.auth-server.ingress.lockLabels object {} Lock ingress resource labels. key app is taken global.auth-server.ingress.openidAdditionalAnnotations object {} openid-configuration ingress resource additional annotations. global.auth-server.ingress.openidConfigEnabled bool true Enable endpoint /.well-known/openid-configuration global.auth-server.ingress.openidConfigLabels object {} openid-configuration ingress resource labels. key app is taken global.auth-server.ingress.u2fAdditionalAnnotations object {} u2f config ingress resource additional annotations. global.auth-server.ingress.u2fConfigEnabled bool true Enable endpoint /.well-known/fido-configuration global.auth-server.ingress.u2fConfigLabels object {} u2f config ingress resource labels. key app is taken global.auth-server.ingress.uma2AdditionalAnnotations object {} uma2 config ingress resource additional annotations. global.auth-server.ingress.uma2ConfigEnabled bool true Enable endpoint /.well-known/uma2-configuration global.auth-server.ingress.uma2ConfigLabels object {} uma2 config ingress resource labels. key app is taken global.auth-server.ingress.webdiscoveryAdditionalAnnotations object {} webdiscovery ingress resource additional annotations. global.auth-server.ingress.webdiscoveryEnabled bool true Enable endpoint /.well-known/simple-web-discovery global.auth-server.ingress.webdiscoveryLabels object {} webdiscovery ingress resource labels. key app is taken global.auth-server.ingress.webfingerAdditionalAnnotations object {} webfinger ingress resource additional annotations. global.auth-server.ingress.webfingerEnabled bool true Enable endpoint /.well-known/webfinger global.auth-server.ingress.webfingerLabels object {} webfinger ingress resource labels. key app is taken global.auth-server.lockEnabled bool false Enable jans-lock as service running inside auth-server global.awsStorageType string \"io1\" Volume storage type if using AWS volumes. global.azureStorageAccountType string \"Standard_LRS\" Volume storage type if using Azure disks. global.azureStorageKind string \"Managed\" Azure storage kind if using Azure disks global.casa.appLoggers object {\"casaLogLevel\":\"INFO\",\"casaLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"timerLogLevel\":\"INFO\",\"timerLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.casa.appLoggers.casaLogLevel string \"INFO\" casa.log level global.casa.appLoggers.casaLogTarget string \"STDOUT\" casa.log target global.casa.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e casa ===> 2022-12-20 17:49:55,744 INFO global.casa.appLoggers.timerLogLevel string \"INFO\" casa timer log level global.casa.appLoggers.timerLogTarget string \"FILE\" casa timer log target global.casa.casaServiceName string \"casa\" Name of the casa service. Please keep it as default. global.casa.cnCustomJavaOptions string \"\" passing custom java options to casa. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.casa.enabled bool true Boolean flag to enable/disable the casa chart. global.casa.ingress object {\"casaAdditionalAnnotations\":{},\"casaEnabled\":false,\"casaLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.casa.ingress.casaAdditionalAnnotations object {} Casa ingress resource additional annotations. global.casa.ingress.casaEnabled bool false Enable casa endpoints /casa global.casa.ingress.casaLabels object {} Casa ingress resource labels. key app is taken global.cloud.testEnviroment bool false Boolean flag if enabled will strip resources requests and limits from all services. global.cnConfiguratorConfigurationFile string \"/etc/jans/conf/configuration.json\" Path to configuration schema file global.cnConfiguratorCustomSchema object {\"secretName\":\"\"} Use custom configuration schema in existing secrets. Note, the secrets has to contain the key configuration.json or any basename as specified in cnConfiguratorConfigurationFile. global.cnConfiguratorCustomSchema.secretName string \"\" The name of the secrets used for storing custom configuration schema. global.cnConfiguratorDumpFile string \"/etc/jans/conf/configuration.out.json\" Path to dumped configuration schema file global.cnDocumentStoreType string \"DB\" Document store type to use for shibboleth files DB. global.cnGoogleApplicationCredentials string \"/etc/jans/conf/google-credentials.json\" Base64 encoded service account. The sa must have roles/secretmanager.admin to use Google secrets. Leave as this is a sensible default. global.cnPersistenceType string \"sql\" Persistence backend to run Janssen with hybrid global.cnPrometheusPort string \"\" Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. global.cnSqlPasswordFile string \"/etc/jans/conf/sql_password\" Path to SQL password file global.config-api.appLoggers object {\"configApiLogLevel\":\"INFO\",\"configApiLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.config-api.appLoggers.configApiLogLevel string \"INFO\" configapi.log level global.config-api.appLoggers.configApiLogTarget string \"STDOUT\" configapi.log target global.config-api.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e config-api_persistence ===> 2022-12-20 17:49:55,744 INFO global.config-api.appLoggers.persistenceDurationLogLevel string \"INFO\" config-api_persistence_duration.log level global.config-api.appLoggers.persistenceDurationLogTarget string \"FILE\" config-api_persistence_duration.log target global.config-api.appLoggers.persistenceLogLevel string \"INFO\" config-api_persistence.log level global.config-api.appLoggers.persistenceLogTarget string \"FILE\" config-api_persistence.log target global.config-api.appLoggers.scriptLogLevel string \"INFO\" config-api_script.log level global.config-api.appLoggers.scriptLogTarget string \"FILE\" config-api_script.log target global.config-api.cnCustomJavaOptions string \"\" passing custom java options to config-api. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.config-api.configApiServerServiceName string \"config-api\" Name of the config-api service. Please keep it as default. global.config-api.enabled bool true Boolean flag to enable/disable the config-api chart. global.config-api.ingress object {\"configApiAdditionalAnnotations\":{},\"configApiEnabled\":true,\"configApiLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.config-api.ingress.configApiAdditionalAnnotations object {} ConfigAPI ingress resource additional annotations. global.config-api.ingress.configApiLabels object {} configAPI ingress resource labels. key app is taken global.config-api.plugins string \"fido2,scim,user-mgt\" Comma-separated values of enabled plugins (supported plugins are \"admin-ui\",\"fido2\",\"scim\",\"user-mgt\",\"jans-link\",\"kc-saml\") global.config.enabled bool true Boolean flag to enable/disable the configuration chart. This normally should never be false global.configAdapterName string \"kubernetes\" The config backend adapter that will hold Janssen configuration layer. aws global.configSecretAdapter string \"kubernetes\" The config backend adapter that will hold Janssen secret layer. vault global.fido2.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"fido2LogLevel\":\"INFO\",\"fido2LogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.fido2.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e fido2 ===> 2022-12-20 17:49:55,744 INFO global.fido2.appLoggers.fido2LogLevel string \"INFO\" fido2.log level global.fido2.appLoggers.fido2LogTarget string \"STDOUT\" fido2.log target global.fido2.appLoggers.persistenceDurationLogLevel string \"INFO\" fido2_persistence_duration.log level global.fido2.appLoggers.persistenceDurationLogTarget string \"FILE\" fido2_persistence_duration.log target global.fido2.appLoggers.persistenceLogLevel string \"INFO\" fido2_persistence.log level global.fido2.appLoggers.persistenceLogTarget string \"FILE\" fido2_persistence.log target global.fido2.appLoggers.scriptLogLevel string \"INFO\" fido2_script.log level global.fido2.appLoggers.scriptLogTarget string \"FILE\" fido2_script.log target global.fido2.cnCustomJavaOptions string \"\" passing custom java options to fido2. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.fido2.enabled bool true Boolean flag to enable/disable the fido2 chart. global.fido2.fido2ServiceName string \"fido2\" Name of the fido2 service. Please keep it as default. global.fido2.ingress object {\"fido2AdditionalAnnotations\":{},\"fido2ConfigAdditionalAnnotations\":{},\"fido2ConfigEnabled\":false,\"fido2ConfigLabels\":{},\"fido2Enabled\":false,\"fido2Labels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.fido2.ingress.fido2AdditionalAnnotations object {} fido2 ingress resource additional annotations. global.fido2.ingress.fido2ConfigAdditionalAnnotations object {} fido2 config ingress resource additional annotations. global.fido2.ingress.fido2ConfigEnabled bool false Enable endpoint /.well-known/fido2-configuration global.fido2.ingress.fido2ConfigLabels object {} fido2 config ingress resource labels. key app is taken global.fido2.ingress.fido2Enabled bool false Enable endpoint /jans-fido2 global.fido2.ingress.fido2Labels object {} fido2 ingress resource labels. key app is taken global.fqdn string \"demoexample.jans.io\" Fully qualified domain name to be used for Janssen installation. This address will be used to reach Janssen services. global.gcePdStorageType string \"pd-standard\" GCE storage kind if using Google disks global.isFqdnRegistered bool false Boolean flag to enable mapping global.lbIp to global.fqdn inside pods on clouds that provide static ip for load balancers. On cloud that provide only addresses to the LB this flag will enable a script to actively scan config.configmap.lbAddr and update the hosts file inside the pods automatically. global.istio.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of global.istio.additionalLabels object {} Additional labels that will be added across the gateway in the format of global.istio.enabled bool false Boolean flag that enables using istio side-cars with Janssen services. global.istio.gateways list [] Override the gateway that can be created by default. This is used when istio ingress has already been setup and the gateway exists. global.istio.ingress bool false Boolean flag that enables using istio gateway for Janssen. This assumes istio ingress is installed and hence the LB is available. global.istio.namespace string \"istio-system\" The namespace istio is deployed in. The is normally istio-system. global.jobTtlSecondsAfterFinished int 300 https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/ global.kc-scheduler.enabled bool false Boolean flag to enable/disable the kc-scheduler cronjob chart. global.lbIp string \"22.22.22.22\" The Loadbalancer IP created by nginx or istio on clouds that provide static IPs. This is not needed if global.fqdn is globally resolvable. global.link.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"linkLogLevel\":\"INFO\",\"linkLogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.link.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e link-persistence ===> 2022-12-20 17:49:55,744 INFO global.link.appLoggers.linkLogLevel string \"INFO\" cacherefresh.log level global.link.appLoggers.linkLogTarget string \"STDOUT\" cacherefresh.log target global.link.appLoggers.persistenceDurationLogLevel string \"INFO\" cacherefresh_persistence_duration.log level global.link.appLoggers.persistenceDurationLogTarget string \"FILE\" cacherefresh_persistence_duration.log target global.link.appLoggers.persistenceLogLevel string \"INFO\" cacherefresh_persistence.log level global.link.appLoggers.persistenceLogTarget string \"FILE\" cacherefresh_persistence.log target global.link.appLoggers.scriptLogLevel string \"INFO\" cacherefresh_script.log level global.link.appLoggers.scriptLogTarget string \"FILE\" cacherefresh_script.log target global.link.cnCustomJavaOptions string \"\" passing custom java options to link. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.link.enabled bool false Boolean flag to enable/disable the link chart. global.link.ingress object {\"linkEnabled\":true} Enable endpoints in either istio or nginx ingress depending on users choice global.link.linkServiceName string \"link\" Name of the link service. Please keep it as default. global.nginx-ingress.enabled bool true Boolean flag to enable/disable the nginx-ingress definitions chart. global.persistence.enabled bool true Boolean flag to enable/disable the persistence chart. global.saml.cnCustomJavaOptions string \"\" passing custom java options to saml. DO NOT PASS JAVA_OPTIONS in envs. global.saml.enabled bool false Boolean flag to enable/disable the saml chart. global.saml.ingress object {\"samlAdditionalAnnotations\":{},\"samlEnabled\":false,\"samlLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.saml.ingress.samlAdditionalAnnotations object {} SAML ingress resource additional annotations. global.saml.ingress.samlLabels object {} SAML config ingress resource labels. key app is taken global.saml.samlServiceName string \"saml\" Name of the saml service. Please keep it as default. global.scim.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scimLogLevel\":\"INFO\",\"scimLogTarget\":\"STDOUT\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.scim.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e jans-scim ===> 2022-12-20 17:49:55,744 INFO global.scim.appLoggers.persistenceDurationLogLevel string \"INFO\" jans-scim_persistence_duration.log level global.scim.appLoggers.persistenceDurationLogTarget string \"FILE\" jans-scim_persistence_duration.log target global.scim.appLoggers.persistenceLogLevel string \"INFO\" jans-scim_persistence.log level global.scim.appLoggers.persistenceLogTarget string \"FILE\" jans-scim_persistence.log target global.scim.appLoggers.scimLogLevel string \"INFO\" jans-scim.log level global.scim.appLoggers.scimLogTarget string \"STDOUT\" jans-scim.log target global.scim.appLoggers.scriptLogLevel string \"INFO\" jans-scim_script.log level global.scim.appLoggers.scriptLogTarget string \"FILE\" jans-scim_script.log target global.scim.cnCustomJavaOptions string \"\" passing custom java options to scim. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.scim.enabled bool true Boolean flag to enable/disable the SCIM chart. global.scim.ingress object {\"scimAdditionalAnnotations\":{},\"scimConfigAdditionalAnnotations\":{},\"scimConfigEnabled\":false,\"scimConfigLabels\":{},\"scimEnabled\":false,\"scimLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.scim.ingress.scimAdditionalAnnotations object {} SCIM ingress resource additional annotations. global.scim.ingress.scimConfigAdditionalAnnotations object {} SCIM config ingress resource additional annotations. global.scim.ingress.scimConfigEnabled bool false Enable endpoint /.well-known/scim-configuration global.scim.ingress.scimConfigLabels object {} SCIM config ingress resource labels. key app is taken global.scim.ingress.scimEnabled bool false Enable SCIM endpoints /jans-scim global.scim.ingress.scimLabels object {} SCIM config ingress resource labels. key app is taken global.scim.scimServiceName string \"scim\" Name of the scim service. Please keep it as default. global.serviceAccountName string \"default\" service account used by Kubernetes resources global.storageClass object {\"allowVolumeExpansion\":true,\"allowedTopologies\":[],\"mountOptions\":[\"debug\"],\"parameters\":{},\"provisioner\":\"microk8s.io/hostpath\",\"reclaimPolicy\":\"Retain\",\"volumeBindingMode\":\"WaitForFirstConsumer\"} StorageClass section. This is not currently used by the openbanking distribution. You may specify custom parameters as needed. global.storageClass.parameters object {} parameters: fsType: \"\" kind: \"\" pool: \"\" storageAccountType: \"\" type: \"\" global.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service. Envs defined in global.userEnvs will be globally available to all services global.usrEnvs.normal object {} Add custom normal envs to the service. variable1: value1 global.usrEnvs.secret object {} Add custom secret envs to the service. variable1: value1 kc-scheduler object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/kc-scheduler\",\"tag\":\"0.0.0-nightly\"},\"interval\":10,\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Responsible for synchronizing Keycloak SAML clients kc-scheduler.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of kc-scheduler.additionalLabels object {} Additional labels that will be added across the gateway in the format of kc-scheduler.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. kc-scheduler.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh kc-scheduler.dnsConfig object {} Add custom dns config kc-scheduler.dnsPolicy string \"\" Add custom dns policy kc-scheduler.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. kc-scheduler.image.pullSecrets list [] Image Pull Secrets kc-scheduler.image.repository string \"ghcr.io/janssenproject/jans/kc-scheduler\" Image to use for deploying. kc-scheduler.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. kc-scheduler.interval int 10 Interval of running the scheduler (in minutes) kc-scheduler.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. kc-scheduler.resources.limits.cpu string \"300m\" CPU limit. kc-scheduler.resources.limits.memory string \"300Mi\" Memory limit. kc-scheduler.resources.requests.cpu string \"300m\" CPU request. kc-scheduler.resources.requests.memory string \"300Mi\" Memory request. kc-scheduler.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service kc-scheduler.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 kc-scheduler.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 kc-scheduler.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers kc-scheduler.volumes list [] Configure any additional volumes that need to be attached to the pod link object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/link\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Link. link.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of link.additionalLabels object {} Additional labels that will be added across the gateway in the format of link.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. link.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh link.dnsConfig object {} Add custom dns config link.dnsPolicy string \"\" Add custom dns policy link.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler link.hpa.behavior object {} Scaling Policies link.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set link.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. link.image.pullSecrets list [] Image Pull Secrets link.image.repository string \"ghcr.io/janssenproject/jans/link\" Image to use for deploying. link.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. link.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. link.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http liveness probe endpoint link.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget link.readinessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http readiness probe endpoint link.replicas int 1 Service replica number. link.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}} Resource specs. link.resources.limits.cpu string \"500m\" CPU limit. link.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. link.resources.requests.cpu string \"500m\" CPU request. link.resources.requests.memory string \"1200Mi\" Memory request. link.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ link.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service link.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 link.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 link.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers link.volumes list [] Configure any additional volumes that need to be attached to the pod nginx-ingress object {\"ingress\":{\"additionalAnnotations\":{},\"additionalLabels\":{},\"hosts\":[\"demoexample.jans.io\"],\"ingressClassName\":\"nginx\",\"path\":\"/\",\"tls\":[{\"hosts\":[\"demoexample.jans.io\"],\"secretName\":\"tls-certificate\"}]}} Nginx ingress definitions chart nginx-ingress.ingress.additionalAnnotations object {} Additional annotations that will be added across all ingress definitions in the format of {cert-manager.io/issuer: \"letsencrypt-prod\"} Enable client certificate authentication nginx.ingress.kubernetes.io/auth-tls-verify-client: \"optional\" Create the secret containing the trusted ca certificates nginx.ingress.kubernetes.io/auth-tls-secret: \"janssen/tls-certificate\" Specify the verification depth in the client certificates chain nginx.ingress.kubernetes.io/auth-tls-verify-depth: \"1\" Specify if certificates are passed to upstream server nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: \"true\" nginx-ingress.ingress.additionalLabels object {} Additional labels that will be added across all ingress definitions in the format of nginx-ingress.ingress.tls list [{\"hosts\":[\"demoexample.jans.io\"],\"secretName\":\"tls-certificate\"}] Secrets holding HTTPS CA cert and key. persistence object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/persistence-loader\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Job to generate data and initial config for Janssen Server persistence layer. persistence.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of persistence.additionalLabels object {} Additional labels that will be added across the gateway in the format of persistence.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. persistence.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh persistence.dnsConfig object {} Add custom dns config persistence.dnsPolicy string \"\" Add custom dns policy persistence.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. persistence.image.pullSecrets list [] Image Pull Secrets persistence.image.repository string \"ghcr.io/janssenproject/jans/persistence-loader\" Image to use for deploying. persistence.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. persistence.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. persistence.resources.limits.cpu string \"300m\" CPU limit persistence.resources.limits.memory string \"300Mi\" Memory limit. persistence.resources.requests.cpu string \"300m\" CPU request. persistence.resources.requests.memory string \"300Mi\" Memory request. persistence.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service persistence.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 persistence.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 persistence.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers persistence.volumes list [] Configure any additional volumes that need to be attached to the pod saml object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/saml\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} SAML. saml.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of saml.additionalLabels object {} Additional labels that will be added across the gateway in the format of saml.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. saml.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh saml.dnsConfig object {} Add custom dns config saml.dnsPolicy string \"\" Add custom dns policy saml.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler saml.hpa.behavior object {} Scaling Policies saml.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set saml.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. saml.image.pullSecrets list [] Image Pull Secrets saml.image.repository string \"ghcr.io/janssenproject/jans/saml\" Image to use for deploying. saml.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. saml.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. saml.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http liveness probe endpoint saml.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget saml.readinessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http readiness probe endpoint saml.replicas int 1 Service replica number. saml.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}} Resource specs. saml.resources.limits.cpu string \"500m\" CPU limit. saml.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. saml.resources.requests.cpu string \"500m\" CPU request. saml.resources.requests.memory string \"1200Mi\" Memory request. saml.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ saml.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service saml.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 saml.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 saml.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers saml.volumes list [] Configure any additional volumes that need to be attached to the pod scim object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/scim\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}},\"service\":{\"name\":\"http-scim\",\"port\":8080},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} System for Cross-domain Identity Management (SCIM) version 2.0 scim.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of scim.additionalLabels object {} Additional labels that will be added across the gateway in the format of scim.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. scim.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh scim.dnsConfig object {} Add custom dns config scim.dnsPolicy string \"\" Add custom dns policy scim.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler scim.hpa.behavior object {} Scaling Policies scim.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set scim.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. scim.image.pullSecrets list [] Image Pull Secrets scim.image.repository string \"ghcr.io/janssenproject/jans/scim\" Image to use for deploying. scim.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. scim.livenessProbe object {\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for SCIM if needed. scim.livenessProbe.httpGet.path string \"/jans-scim/sys/health-check\" http liveness probe endpoint scim.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget scim.readinessProbe object {\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the readiness healthcheck for the SCIM if needed. scim.readinessProbe.httpGet.path string \"/jans-scim/sys/health-check\" http readiness probe endpoint scim.replicas int 1 Service replica number. scim.resources.limits.cpu string \"1000m\" CPU limit. scim.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. scim.resources.requests.cpu string \"1000m\" CPU request. scim.resources.requests.memory string \"1200Mi\" Memory request. scim.service.name string \"http-scim\" The name of the scim port within the scim service. Please keep it as default. scim.service.port int 8080 Port of the scim service. Please keep it as default. scim.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ scim.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service scim.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 scim.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 scim.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers scim.volumes list [] Configure any additional volumes that need to be attached to the pod Autogenerated from chart metadata using helm-docs v1.14.2", "title": "Helm Chart"}, {"location": "janssen-server/reference/kubernetes/helm-chart/#janssen", "text": "Janssen Access and Identity Management Microservices Chart. This chart deploys each janssen microservice as a separate deployment. Homepage: https://jans.io", "title": "janssen"}, {"location": "janssen-server/reference/kubernetes/helm-chart/#maintainers", "text": "Name Email Url moabu support@jans.io", "title": "Maintainers"}, {"location": "janssen-server/reference/kubernetes/helm-chart/#source-code", "text": "https://jans.io https://github.com/JanssenProject/jans/charts/janssen", "title": "Source Code"}, {"location": "janssen-server/reference/kubernetes/helm-chart/#requirements", "text": "Kubernetes: >=v1.22.0-0 Repository Name Version auth-server 0.0.0-nightly auth-server-key-rotation 0.0.0-nightly casa 0.0.0-nightly cn-istio-ingress 0.0.0-nightly config 0.0.0-nightly config-api 0.0.0-nightly fido2 0.0.0-nightly kc-scheduler 0.0.0-nightly link 0.0.0-nightly nginx-ingress 0.0.0-nightly persistence 0.0.0-nightly saml 0.0.0-nightly scim 0.0.0-nightly", "title": "Requirements"}, {"location": "janssen-server/reference/kubernetes/helm-chart/#values", "text": "Key Type Default Description auth-server object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/auth-server\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"},\"requests\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} OAuth Authorization Server, the OpenID Connect Provider, the UMA Authorization Server--this is the main Internet facing component of Janssen. It's the service that returns tokens, JWT's and identity assertions. This service must be Internet facing. auth-server-key-rotation object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/certmanager\",\"tag\":\"0.0.0-nightly\"},\"keysLife\":48,\"keysPushDelay\":0,\"keysPushStrategy\":\"NEWER\",\"keysStrategy\":\"NEWER\",\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Responsible for regenerating auth-keys per x hours auth-server-key-rotation.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of auth-server-key-rotation.additionalLabels object {} Additional labels that will be added across the gateway in the format of auth-server-key-rotation.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. auth-server-key-rotation.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh auth-server-key-rotation.dnsConfig object {} Add custom dns config auth-server-key-rotation.dnsPolicy string \"\" Add custom dns policy auth-server-key-rotation.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. auth-server-key-rotation.image.pullSecrets list [] Image Pull Secrets auth-server-key-rotation.image.repository string \"ghcr.io/janssenproject/jans/certmanager\" Image to use for deploying. auth-server-key-rotation.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. auth-server-key-rotation.keysLife int 48 Auth server key rotation keys life in hours auth-server-key-rotation.keysPushDelay int 0 Delay (in seconds) before pushing private keys to Auth server auth-server-key-rotation.keysPushStrategy string \"NEWER\" Set key selection strategy after pushing private keys to Auth server (only takes effect when keysPushDelay value is greater than 0) auth-server-key-rotation.keysStrategy string \"NEWER\" Set key selection strategy used by Auth server auth-server-key-rotation.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. auth-server-key-rotation.resources.limits.cpu string \"300m\" CPU limit. auth-server-key-rotation.resources.limits.memory string \"300Mi\" Memory limit. auth-server-key-rotation.resources.requests.cpu string \"300m\" CPU request. auth-server-key-rotation.resources.requests.memory string \"300Mi\" Memory request. auth-server-key-rotation.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service auth-server-key-rotation.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 auth-server-key-rotation.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 auth-server-key-rotation.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers auth-server-key-rotation.volumes list [] Configure any additional volumes that need to be attached to the pod auth-server.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of auth-server.additionalLabels object {} Additional labels that will be added across the gateway in the format of auth-server.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. auth-server.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh auth-server.dnsConfig object {} Add custom dns config auth-server.dnsPolicy string \"\" Add custom dns policy auth-server.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler auth-server.hpa.behavior object {} Scaling Policies auth-server.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set auth-server.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. auth-server.image.pullSecrets list [] Image Pull Secrets auth-server.image.repository string \"ghcr.io/janssenproject/jans/auth-server\" Image to use for deploying. auth-server.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. auth-server.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. auth-server.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} Executes the python3 healthcheck. https://github.com/JanssenProject/docker-jans-auth-server/blob/master/scripts/healthcheck.py auth-server.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget auth-server.readinessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the readiness healthcheck for the auth server if needed. https://github.com/JanssenProject/docker-jans-auth-server/blob/master/scripts/healthcheck.py auth-server.replicas int 1 Service replica number. auth-server.resources object {\"limits\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"},\"requests\":{\"cpu\":\"2500m\",\"memory\":\"2500Mi\"}} Resource specs. auth-server.resources.limits.cpu string \"2500m\" CPU limit. auth-server.resources.limits.memory string \"2500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. auth-server.resources.requests.cpu string \"2500m\" CPU request. auth-server.resources.requests.memory string \"2500Mi\" Memory request. auth-server.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ auth-server.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service auth-server.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 auth-server.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 auth-server.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers auth-server.volumes list [] Configure any additional volumes that need to be attached to the pod casa object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/casa\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Janssen Casa (\"Casa\") is a self-service web portal for end-users to manage authentication and authorization preferences for their account in a Janssen Auth Server. casa.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of casa.additionalLabels object {} Additional labels that will be added across the gateway in the format of casa.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. casa.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh casa.dnsConfig object {} Add custom dns config casa.dnsPolicy string \"\" Add custom dns policy casa.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler casa.hpa.behavior object {} Scaling Policies casa.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set casa.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. casa.image.pullSecrets list [] Image Pull Secrets casa.image.repository string \"ghcr.io/janssenproject/jans/casa\" Image to use for deploying. casa.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. casa.livenessProbe object {\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the liveness healthcheck for casa if needed. casa.livenessProbe.httpGet.path string \"/jans-casa/health-check\" http liveness probe endpoint casa.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget casa.readinessProbe object {\"httpGet\":{\"path\":\"/jans-casa/health-check\",\"port\":\"http-casa\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the readiness healthcheck for the casa if needed. casa.readinessProbe.httpGet.path string \"/jans-casa/health-check\" http readiness probe endpoint casa.replicas int 1 Service replica number. casa.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}} Resource specs. casa.resources.limits.cpu string \"500m\" CPU limit. casa.resources.limits.memory string \"500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. casa.resources.requests.cpu string \"500m\" CPU request. casa.resources.requests.memory string \"500Mi\" Memory request. casa.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ casa.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service casa.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 casa.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 casa.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers casa.volumes list [] Configure any additional volumes that need to be attached to the pod config object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"adminPassword\":\"Test1234#\",\"city\":\"Austin\",\"configmap\":{\"cnAwsAccessKeyId\":\"\",\"cnAwsDefaultRegion\":\"us-west-1\",\"cnAwsProfile\":\"janssen\",\"cnAwsSecretAccessKey\":\"\",\"cnAwsSecretsEndpointUrl\":\"\",\"cnAwsSecretsNamePrefix\":\"janssen\",\"cnAwsSecretsReplicaRegions\":[],\"cnCacheType\":\"NATIVE_PERSISTENCE\",\"cnConfigKubernetesConfigMap\":\"cn\",\"cnGoogleProjectId\":\"google-project-to-save-config-and-secrets-to\",\"cnGoogleSecretManagerServiceAccount\":\"SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo=\",\"cnGoogleSecretNamePrefix\":\"janssen\",\"cnGoogleSecretVersionId\":\"latest\",\"cnJettyRequestHeaderSize\":8192,\"cnMaxRamPercent\":\"75.0\",\"cnMessageType\":\"DISABLED\",\"cnOpaUrl\":\"http://opa.opa.svc.cluster.cluster.local:8181/v1\",\"cnPersistenceHybridMapping\":\"{}\",\"cnRedisSentinelGroup\":\"\",\"cnRedisSslTruststore\":\"\",\"cnRedisType\":\"STANDALONE\",\"cnRedisUrl\":\"redis.redis.svc.cluster.local:6379\",\"cnRedisUseSsl\":false,\"cnScimProtectionMode\":\"OAUTH\",\"cnSecretKubernetesSecret\":\"cn\",\"cnSqlDbDialect\":\"mysql\",\"cnSqlDbHost\":\"my-release-mysql.default.svc.cluster.local\",\"cnSqlDbName\":\"jans\",\"cnSqlDbPort\":3306,\"cnSqlDbSchema\":\"\",\"cnSqlDbTimezone\":\"UTC\",\"cnSqlDbUser\":\"jans\",\"cnSqldbUserPassword\":\"Test1234#\",\"cnVaultAddr\":\"http://localhost:8200\",\"cnVaultAppRolePath\":\"approle\",\"cnVaultKvPath\":\"secret\",\"cnVaultNamespace\":\"\",\"cnVaultPrefix\":\"jans\",\"cnVaultRoleId\":\"\",\"cnVaultRoleIdFile\":\"/etc/certs/vault_role_id\",\"cnVaultSecretId\":\"\",\"cnVaultSecretIdFile\":\"/etc/certs/vault_secret_id\",\"cnVaultVerify\":false,\"kcAdminPassword\":\"Test1234#\",\"kcAdminUsername\":\"admin\",\"kcDbPassword\":\"Test1234#\",\"kcDbSchema\":\"keycloak\",\"kcDbUrlDatabase\":\"keycloak\",\"kcDbUrlHost\":\"mysql.kc.svc.cluster.local\",\"kcDbUrlPort\":3306,\"kcDbUrlProperties\":\"?useUnicode=true&characterEncoding=UTF-8&character_set_server=utf8mb4\",\"kcDbUsername\":\"keycloak\",\"kcDbVendor\":\"mysql\",\"kcLogLevel\":\"INFO\",\"lbAddr\":\"\",\"quarkusTransactionEnableRecovery\":true},\"countryCode\":\"US\",\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"email\":\"support@jans.io\",\"image\":{\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/configurator\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"orgName\":\"Janssen\",\"redisPassword\":\"P@assw0rd\",\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"salt\":\"\",\"state\":\"TX\",\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Configuration parameters for setup and initial configuration secret and config layers used by Janssen services. config-api object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/config-api\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"jans-config-api/api/v1/health/ready\",\"port\":8074},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Config Api endpoints can be used to configure the auth-server, which is an open-source OpenID Connect Provider (OP) and UMA Authorization Server (AS). config-api.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of config-api.additionalLabels object {} Additional labels that will be added across the gateway in the format of config-api.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. config-api.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh config-api.dnsConfig object {} Add custom dns config config-api.dnsPolicy string \"\" Add custom dns policy config-api.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler config-api.hpa.behavior object {} Scaling Policies config-api.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set config-api.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. config-api.image.pullSecrets list [] Image Pull Secrets config-api.image.repository string \"ghcr.io/janssenproject/jans/config-api\" Image to use for deploying. config-api.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. config-api.livenessProbe object {\"httpGet\":{\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. config-api.livenessProbe.httpGet object {\"path\":\"/jans-config-api/api/v1/health/live\",\"port\":8074} http liveness probe endpoint config-api.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget config-api.readinessProbe.httpGet object {\"path\":\"jans-config-api/api/v1/health/ready\",\"port\":8074} http readiness probe endpoint config-api.replicas int 1 Service replica number. config-api.resources object {\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}} Resource specs. config-api.resources.limits.cpu string \"1000m\" CPU limit. config-api.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. config-api.resources.requests.cpu string \"1000m\" CPU request. config-api.resources.requests.memory string \"1200Mi\" Memory request. config-api.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ config-api.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service config-api.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 config-api.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 config-api.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers config-api.volumes list [] Configure any additional volumes that need to be attached to the pod config.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of config.adminPassword string \"Test1234#\" Admin password to log in to the UI. config.city string \"Austin\" City. Used for certificate creation. config.configmap.cnCacheType string \"NATIVE_PERSISTENCE\" Cache type. NATIVE_PERSISTENCE , REDIS . or IN_MEMORY . Defaults to NATIVE_PERSISTENCE . config.configmap.cnConfigKubernetesConfigMap string \"cn\" The name of the Kubernetes ConfigMap that will hold the configuration layer config.configmap.cnGoogleProjectId string \"google-project-to-save-config-and-secrets-to\" Project id of the Google project the secret manager belongs to. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretManagerServiceAccount string \"SWFtTm90YVNlcnZpY2VBY2NvdW50Q2hhbmdlTWV0b09uZQo=\" Service account with roles roles/secretmanager.admin base64 encoded string. This is used often inside the services to reach the configuration layer. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretNamePrefix string \"janssen\" Prefix for Janssen secret in Google Secret Manager. Defaults to janssen. If left janssen-secret secret will be created. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnGoogleSecretVersionId string \"latest\" Secret version to be used for secret configuration. Defaults to latest and should normally always stay that way. Used only when global.configAdapterName and global.configSecretAdapter is set to google. config.configmap.cnJettyRequestHeaderSize int 8192 Jetty header size in bytes in the auth server config.configmap.cnMaxRamPercent string \"75.0\" Value passed to Java option -XX:MaxRAMPercentage config.configmap.cnMessageType string \"DISABLED\" Message type (one of POSTGRES, REDIS, or DISABLED) config.configmap.cnOpaUrl string \"http://opa.opa.svc.cluster.cluster.local:8181/v1\" URL of OPA API config.configmap.cnPersistenceHybridMapping string \"{}\" Specify data that should be saved in persistence (one of default, user, cache, site, token, or session; default to default). Note this environment only takes effect when global.cnPersistenceType is set to hybrid . config.configmap.cnRedisSentinelGroup string \"\" Redis Sentinel Group. Often set when config.configmap.cnRedisType is set to SENTINEL . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisSslTruststore string \"\" Redis SSL truststore. Optional. Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisType string \"STANDALONE\" Redis service type. STANDALONE or CLUSTER . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisUrl string \"redis.redis.svc.cluster.local:6379\" Redis URL and port number : . Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnRedisUseSsl bool false Boolean to use SSL in Redis. Can be used when config.configmap.cnCacheType is set to REDIS . config.configmap.cnScimProtectionMode string \"OAUTH\" SCIM protection mode OAUTH config.configmap.cnSecretKubernetesSecret string \"cn\" Kubernetes secret name holding configuration keys. Used when global.configSecretAdapter is set to kubernetes which is the default. config.configmap.cnSqlDbDialect string \"mysql\" SQL database dialect. mysql or pgsql config.configmap.cnSqlDbHost string \"my-release-mysql.default.svc.cluster.local\" SQL database host uri. config.configmap.cnSqlDbName string \"jans\" SQL database name. config.configmap.cnSqlDbPort int 3306 SQL database port. config.configmap.cnSqlDbSchema string \"\" Schema name used by SQL database (default to empty-string; if using MySQL, the schema name will be resolved as the database name, whereas in PostgreSQL the schema name will be resolved as \"public\" ). config.configmap.cnSqlDbTimezone string \"UTC\" SQL database timezone. config.configmap.cnSqlDbUser string \"jans\" SQL database username. config.configmap.cnSqldbUserPassword string \"Test1234#\" SQL password injected the secrets . config.configmap.cnVaultAddr string \"http://localhost:8200\" Base URL of Vault. config.configmap.cnVaultAppRolePath string \"approle\" Path to Vault AppRole. config.configmap.cnVaultKvPath string \"secret\" Path to Vault KV secrets engine. config.configmap.cnVaultNamespace string \"\" Vault namespace used to access the secrets. config.configmap.cnVaultPrefix string \"jans\" Base prefix name used to access secrets. config.configmap.cnVaultRoleId string \"\" Vault AppRole RoleID. config.configmap.cnVaultRoleIdFile string \"/etc/certs/vault_role_id\" Path to file contains Vault AppRole role ID. config.configmap.cnVaultSecretId string \"\" Vault AppRole SecretID. config.configmap.cnVaultSecretIdFile string \"/etc/certs/vault_secret_id\" Path to file contains Vault AppRole secret ID. config.configmap.cnVaultVerify bool false Verify connection to Vault. config.configmap.kcAdminPassword string \"Test1234#\" Keycloak admin UI password config.configmap.kcAdminUsername string \"admin\" Keycloak admin UI username config.configmap.kcDbPassword string \"Test1234#\" Password for Keycloak database access config.configmap.kcDbSchema string \"keycloak\" Keycloak database schema name (note that PostgreSQL may be using \"public\" schema). config.configmap.kcDbUrlDatabase string \"keycloak\" Keycloak database name. config.configmap.kcDbUrlHost string \"mysql.kc.svc.cluster.local\" Keycloak database host uri config.configmap.kcDbUrlPort int 3306 Keycloak database port (default to port 3306 for mysql). config.configmap.kcDbUrlProperties string \"?useUnicode=true&characterEncoding=UTF-8&character_set_server=utf8mb4\" Keycloak database connection properties. If using postgresql, the value can be set to empty string. config.configmap.kcDbUsername string \"keycloak\" Keycloak database username config.configmap.kcDbVendor string \"mysql\" Keycloak database vendor name (default to MySQL server). To use PostgreSQL server, change the value to postgres. config.configmap.kcLogLevel string \"INFO\" Keycloak logging level config.configmap.lbAddr string \"\" Load balancer address for AWS if the FQDN is not registered. config.configmap.quarkusTransactionEnableRecovery bool true Quarkus transaction recovery. When using MySQL, there could be issue regarding XA_RECOVER_ADMIN; refer to https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_xa-recover-admin for details. config.countryCode string \"US\" Country code. Used for certificate creation. config.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. config.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh config.dnsConfig object {} Add custom dns config config.dnsPolicy string \"\" Add custom dns policy config.email string \"support@jans.io\" Email address of the administrator usually. Used for certificate creation. config.image.pullSecrets list [] Image Pull Secrets config.image.repository string \"ghcr.io/janssenproject/jans/configurator\" Image to use for deploying. config.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. config.orgName string \"Janssen\" Organization name. Used for certificate creation. config.redisPassword string \"P@assw0rd\" Redis admin password if config.configmap.cnCacheType is set to REDIS . config.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. config.resources.limits.cpu string \"300m\" CPU limit. config.resources.limits.memory string \"300Mi\" Memory limit. config.resources.requests.cpu string \"300m\" CPU request. config.resources.requests.memory string \"300Mi\" Memory request. config.salt string \"\" Salt. Used for encoding/decoding sensitive data. If omitted or set to empty string, the value will be self-generated. Otherwise, a 24 alphanumeric characters are allowed as its value. config.state string \"TX\" State code. Used for certificate creation. config.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service. config.usrEnvs.normal object {} Add custom normal envs to the service. variable1: value1 config.usrEnvs.secret object {} Add custom secret envs to the service. variable1: value1 config.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers config.volumes list [] Configure any additional volumes that need to be attached to the pod fido2 object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/fido2\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}},\"service\":{\"name\":\"http-fido2\",\"port\":8080},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} FIDO 2.0 (FIDO2) is an open authentication standard that enables leveraging common devices to authenticate to online services in both mobile and desktop environments. fido2.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of fido2.additionalLabels object {} Additional labels that will be added across the gateway in the format of fido2.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. fido2.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh fido2.dnsConfig object {} Add custom dns config fido2.dnsPolicy string \"\" Add custom dns policy fido2.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler fido2.hpa.behavior object {} Scaling Policies fido2.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set fido2.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. fido2.image.pullSecrets list [] Image Pull Secrets fido2.image.repository string \"ghcr.io/janssenproject/jans/fido2\" Image to use for deploying. fido2.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. fido2.livenessProbe object {\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the liveness healthcheck for the fido2 if needed. fido2.livenessProbe.httpGet object {\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"} http liveness probe endpoint fido2.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget fido2.readinessProbe object {\"httpGet\":{\"path\":\"/jans-fido2/sys/health-check\",\"port\":\"http-fido2\"},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the readiness healthcheck for the fido2 if needed. fido2.replicas int 1 Service replica number. fido2.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"500Mi\"}} Resource specs. fido2.resources.limits.cpu string \"500m\" CPU limit. fido2.resources.limits.memory string \"500Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. fido2.resources.requests.cpu string \"500m\" CPU request. fido2.resources.requests.memory string \"500Mi\" Memory request. fido2.service.name string \"http-fido2\" The name of the fido2 port within the fido2 service. Please keep it as default. fido2.service.port int 8080 Port of the fido2 service. Please keep it as default. fido2.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ fido2.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service fido2.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 fido2.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 fido2.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers fido2.volumes list [] Configure any additional volumes that need to be attached to the pod global object {\"alb\":{\"ingress\":false},\"auth-server\":{\"appLoggers\":{\"auditStatsLogLevel\":\"INFO\",\"auditStatsLogTarget\":\"FILE\",\"authLogLevel\":\"INFO\",\"authLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"httpLogLevel\":\"INFO\",\"httpLogTarget\":\"FILE\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"authEncKeys\":\"RSA1_5 RSA-OAEP\",\"authServerServiceName\":\"auth-server\",\"authSigKeys\":\"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\",\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"authServerAdditionalAnnotations\":{},\"authServerEnabled\":true,\"authServerLabels\":{},\"deviceCodeAdditionalAnnotations\":{},\"deviceCodeEnabled\":true,\"deviceCodeLabels\":{},\"firebaseMessagingAdditionalAnnotations\":{},\"firebaseMessagingEnabled\":true,\"firebaseMessagingLabels\":{},\"lockAdditionalAnnotations\":{},\"lockConfigAdditionalAnnotations\":{},\"lockConfigEnabled\":false,\"lockConfigLabels\":{},\"lockEnabled\":false,\"lockLabels\":{},\"openidAdditionalAnnotations\":{},\"openidConfigEnabled\":true,\"openidConfigLabels\":{},\"u2fAdditionalAnnotations\":{},\"u2fConfigEnabled\":true,\"u2fConfigLabels\":{},\"uma2AdditionalAnnotations\":{},\"uma2ConfigEnabled\":true,\"uma2ConfigLabels\":{},\"webdiscoveryAdditionalAnnotations\":{},\"webdiscoveryEnabled\":true,\"webdiscoveryLabels\":{},\"webfingerAdditionalAnnotations\":{},\"webfingerEnabled\":true,\"webfingerLabels\":{}},\"lockEnabled\":false},\"auth-server-key-rotation\":{\"customAnnotations\":{\"cronjob\":{},\"secret\":{},\"service\":{}},\"enabled\":true,\"initKeysLife\":48},\"awsStorageType\":\"io1\",\"azureStorageAccountType\":\"Standard_LRS\",\"azureStorageKind\":\"Managed\",\"casa\":{\"appLoggers\":{\"casaLogLevel\":\"INFO\",\"casaLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"timerLogLevel\":\"INFO\",\"timerLogTarget\":\"FILE\"},\"casaServiceName\":\"casa\",\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"casaAdditionalAnnotations\":{},\"casaEnabled\":false,\"casaLabels\":{}}},\"cloud\":{\"testEnviroment\":false},\"cnAwsConfigFile\":\"/etc/jans/conf/aws_config_file\",\"cnAwsSecretsReplicaRegionsFile\":\"/etc/jans/conf/aws_secrets_replica_regions\",\"cnAwsSharedCredentialsFile\":\"/etc/jans/conf/aws_shared_credential_file\",\"cnConfiguratorConfigurationFile\":\"/etc/jans/conf/configuration.json\",\"cnConfiguratorCustomSchema\":{\"secretName\":\"\"},\"cnConfiguratorDumpFile\":\"/etc/jans/conf/configuration.out.json\",\"cnDocumentStoreType\":\"DB\",\"cnGoogleApplicationCredentials\":\"/etc/jans/conf/google-credentials.json\",\"cnPersistenceType\":\"sql\",\"cnPrometheusPort\":\"\",\"cnSqlPasswordFile\":\"/etc/jans/conf/sql_password\",\"config\":{\"customAnnotations\":{\"clusterRoleBinding\":{},\"configMap\":{},\"job\":{},\"role\":{},\"roleBinding\":{},\"secret\":{},\"service\":{},\"serviceAccount\":{}},\"enabled\":true},\"config-api\":{\"appLoggers\":{\"configApiLogLevel\":\"INFO\",\"configApiLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"configApiServerServiceName\":\"config-api\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"configApiAdditionalAnnotations\":{},\"configApiEnabled\":true,\"configApiLabels\":{}},\"plugins\":\"fido2,scim,user-mgt\"},\"configAdapterName\":\"kubernetes\",\"configSecretAdapter\":\"kubernetes\",\"fido2\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"fido2LogLevel\":\"INFO\",\"fido2LogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"fido2ServiceName\":\"fido2\",\"ingress\":{\"fido2AdditionalAnnotations\":{},\"fido2ConfigAdditionalAnnotations\":{},\"fido2ConfigEnabled\":false,\"fido2ConfigLabels\":{},\"fido2Enabled\":false,\"fido2Labels\":{}}},\"fqdn\":\"demoexample.jans.io\",\"gcePdStorageType\":\"pd-standard\",\"isFqdnRegistered\":false,\"istio\":{\"additionalAnnotations\":{},\"additionalLabels\":{},\"enabled\":false,\"gateways\":[],\"ingress\":false,\"namespace\":\"istio-system\"},\"jobTtlSecondsAfterFinished\":300,\"kc-scheduler\":{\"enabled\":false},\"lbIp\":\"22.22.22.22\",\"link\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"linkLogLevel\":\"INFO\",\"linkLogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"service\":{},\"virtualService\":{}},\"enabled\":false,\"ingress\":{\"linkEnabled\":true},\"linkServiceName\":\"link\"},\"nginx-ingress\":{\"enabled\":true},\"persistence\":{\"customAnnotations\":{\"job\":{},\"secret\":{},\"service\":{}},\"enabled\":true},\"saml\":{\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":false,\"ingress\":{\"samlAdditionalAnnotations\":{},\"samlEnabled\":false,\"samlLabels\":{}},\"samlServiceName\":\"saml\"},\"scim\":{\"appLoggers\":{\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scimLogLevel\":\"INFO\",\"scimLogTarget\":\"STDOUT\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"},\"cnCustomJavaOptions\":\"\",\"customAnnotations\":{\"deployment\":{},\"destinationRule\":{},\"horizontalPodAutoscaler\":{},\"pod\":{},\"podDisruptionBudget\":{},\"secret\":{},\"service\":{},\"virtualService\":{}},\"enabled\":true,\"ingress\":{\"scimAdditionalAnnotations\":{},\"scimConfigAdditionalAnnotations\":{},\"scimConfigEnabled\":false,\"scimConfigLabels\":{},\"scimEnabled\":false,\"scimLabels\":{}},\"scimServiceName\":\"scim\"},\"serviceAccountName\":\"default\",\"storageClass\":{\"allowVolumeExpansion\":true,\"allowedTopologies\":[],\"mountOptions\":[\"debug\"],\"parameters\":{},\"provisioner\":\"microk8s.io/hostpath\",\"reclaimPolicy\":\"Retain\",\"volumeBindingMode\":\"WaitForFirstConsumer\"},\"usrEnvs\":{\"normal\":{},\"secret\":{}}} Parameters used globally across all services helm charts. global.alb.ingress bool false Activates ALB ingress global.auth-server-key-rotation.enabled bool true Boolean flag to enable/disable the auth-server-key rotation cronjob chart. global.auth-server-key-rotation.initKeysLife int 48 The initial auth server key rotation keys life in hours global.auth-server.appLoggers object {\"auditStatsLogLevel\":\"INFO\",\"auditStatsLogTarget\":\"FILE\",\"authLogLevel\":\"INFO\",\"authLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"httpLogLevel\":\"INFO\",\"httpLogTarget\":\"FILE\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.auth-server.appLoggers.auditStatsLogLevel string \"INFO\" jans-auth_audit.log level global.auth-server.appLoggers.auditStatsLogTarget string \"FILE\" jans-auth_script.log target global.auth-server.appLoggers.authLogLevel string \"INFO\" jans-auth.log level global.auth-server.appLoggers.authLogTarget string \"STDOUT\" jans-auth.log target global.auth-server.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e auth-server-script ===> 2022-12-20 17:49:55,744 INFO global.auth-server.appLoggers.httpLogLevel string \"INFO\" http_request_response.log level global.auth-server.appLoggers.httpLogTarget string \"FILE\" http_request_response.log target global.auth-server.appLoggers.persistenceDurationLogLevel string \"INFO\" jans-auth_persistence_duration.log level global.auth-server.appLoggers.persistenceDurationLogTarget string \"FILE\" jans-auth_persistence_duration.log target global.auth-server.appLoggers.persistenceLogLevel string \"INFO\" jans-auth_persistence.log level global.auth-server.appLoggers.persistenceLogTarget string \"FILE\" jans-auth_persistence.log target global.auth-server.appLoggers.scriptLogLevel string \"INFO\" jans-auth_script.log level global.auth-server.appLoggers.scriptLogTarget string \"FILE\" jans-auth_script.log target global.auth-server.authEncKeys string \"RSA1_5 RSA-OAEP\" space-separated key algorithm for encryption (default to RSA1_5 RSA-OAEP ) global.auth-server.authServerServiceName string \"auth-server\" Name of the auth-server service. Please keep it as default. global.auth-server.authSigKeys string \"RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512\" space-separated key algorithm for signing (default to RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512 ) global.auth-server.cnCustomJavaOptions string \"\" passing custom java options to auth-server. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.auth-server.enabled bool true Boolean flag to enable/disable auth-server chart. You should never set this to false. global.auth-server.ingress object {\"authServerAdditionalAnnotations\":{},\"authServerEnabled\":true,\"authServerLabels\":{},\"deviceCodeAdditionalAnnotations\":{},\"deviceCodeEnabled\":true,\"deviceCodeLabels\":{},\"firebaseMessagingAdditionalAnnotations\":{},\"firebaseMessagingEnabled\":true,\"firebaseMessagingLabels\":{},\"lockAdditionalAnnotations\":{},\"lockConfigAdditionalAnnotations\":{},\"lockConfigEnabled\":false,\"lockConfigLabels\":{},\"lockEnabled\":false,\"lockLabels\":{},\"openidAdditionalAnnotations\":{},\"openidConfigEnabled\":true,\"openidConfigLabels\":{},\"u2fAdditionalAnnotations\":{},\"u2fConfigEnabled\":true,\"u2fConfigLabels\":{},\"uma2AdditionalAnnotations\":{},\"uma2ConfigEnabled\":true,\"uma2ConfigLabels\":{},\"webdiscoveryAdditionalAnnotations\":{},\"webdiscoveryEnabled\":true,\"webdiscoveryLabels\":{},\"webfingerAdditionalAnnotations\":{},\"webfingerEnabled\":true,\"webfingerLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.auth-server.ingress.authServerAdditionalAnnotations object {} Auth server ingress resource additional annotations. global.auth-server.ingress.authServerEnabled bool true Enable Auth server endpoints /jans-auth global.auth-server.ingress.authServerLabels object {} Auth server ingress resource labels. key app is taken global.auth-server.ingress.deviceCodeAdditionalAnnotations object {} device-code ingress resource additional annotations. global.auth-server.ingress.deviceCodeEnabled bool true Enable endpoint /device-code global.auth-server.ingress.deviceCodeLabels object {} device-code ingress resource labels. key app is taken global.auth-server.ingress.firebaseMessagingAdditionalAnnotations object {} Firebase Messaging ingress resource additional annotations. global.auth-server.ingress.firebaseMessagingEnabled bool true Enable endpoint /firebase-messaging-sw.js global.auth-server.ingress.firebaseMessagingLabels object {} Firebase Messaging ingress resource labels. key app is taken global.auth-server.ingress.lockAdditionalAnnotations object {} Lock ingress resource additional annotations. global.auth-server.ingress.lockConfigAdditionalAnnotations object {} Lock config ingress resource additional annotations. global.auth-server.ingress.lockConfigEnabled bool false Enable endpoint /.well-known/lock-server-configuration global.auth-server.ingress.lockConfigLabels object {} Lock config ingress resource labels. key app is taken global.auth-server.ingress.lockEnabled bool false Enable endpoint /jans-lock global.auth-server.ingress.lockLabels object {} Lock ingress resource labels. key app is taken global.auth-server.ingress.openidAdditionalAnnotations object {} openid-configuration ingress resource additional annotations. global.auth-server.ingress.openidConfigEnabled bool true Enable endpoint /.well-known/openid-configuration global.auth-server.ingress.openidConfigLabels object {} openid-configuration ingress resource labels. key app is taken global.auth-server.ingress.u2fAdditionalAnnotations object {} u2f config ingress resource additional annotations. global.auth-server.ingress.u2fConfigEnabled bool true Enable endpoint /.well-known/fido-configuration global.auth-server.ingress.u2fConfigLabels object {} u2f config ingress resource labels. key app is taken global.auth-server.ingress.uma2AdditionalAnnotations object {} uma2 config ingress resource additional annotations. global.auth-server.ingress.uma2ConfigEnabled bool true Enable endpoint /.well-known/uma2-configuration global.auth-server.ingress.uma2ConfigLabels object {} uma2 config ingress resource labels. key app is taken global.auth-server.ingress.webdiscoveryAdditionalAnnotations object {} webdiscovery ingress resource additional annotations. global.auth-server.ingress.webdiscoveryEnabled bool true Enable endpoint /.well-known/simple-web-discovery global.auth-server.ingress.webdiscoveryLabels object {} webdiscovery ingress resource labels. key app is taken global.auth-server.ingress.webfingerAdditionalAnnotations object {} webfinger ingress resource additional annotations. global.auth-server.ingress.webfingerEnabled bool true Enable endpoint /.well-known/webfinger global.auth-server.ingress.webfingerLabels object {} webfinger ingress resource labels. key app is taken global.auth-server.lockEnabled bool false Enable jans-lock as service running inside auth-server global.awsStorageType string \"io1\" Volume storage type if using AWS volumes. global.azureStorageAccountType string \"Standard_LRS\" Volume storage type if using Azure disks. global.azureStorageKind string \"Managed\" Azure storage kind if using Azure disks global.casa.appLoggers object {\"casaLogLevel\":\"INFO\",\"casaLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"timerLogLevel\":\"INFO\",\"timerLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.casa.appLoggers.casaLogLevel string \"INFO\" casa.log level global.casa.appLoggers.casaLogTarget string \"STDOUT\" casa.log target global.casa.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e casa ===> 2022-12-20 17:49:55,744 INFO global.casa.appLoggers.timerLogLevel string \"INFO\" casa timer log level global.casa.appLoggers.timerLogTarget string \"FILE\" casa timer log target global.casa.casaServiceName string \"casa\" Name of the casa service. Please keep it as default. global.casa.cnCustomJavaOptions string \"\" passing custom java options to casa. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.casa.enabled bool true Boolean flag to enable/disable the casa chart. global.casa.ingress object {\"casaAdditionalAnnotations\":{},\"casaEnabled\":false,\"casaLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.casa.ingress.casaAdditionalAnnotations object {} Casa ingress resource additional annotations. global.casa.ingress.casaEnabled bool false Enable casa endpoints /casa global.casa.ingress.casaLabels object {} Casa ingress resource labels. key app is taken global.cloud.testEnviroment bool false Boolean flag if enabled will strip resources requests and limits from all services. global.cnConfiguratorConfigurationFile string \"/etc/jans/conf/configuration.json\" Path to configuration schema file global.cnConfiguratorCustomSchema object {\"secretName\":\"\"} Use custom configuration schema in existing secrets. Note, the secrets has to contain the key configuration.json or any basename as specified in cnConfiguratorConfigurationFile. global.cnConfiguratorCustomSchema.secretName string \"\" The name of the secrets used for storing custom configuration schema. global.cnConfiguratorDumpFile string \"/etc/jans/conf/configuration.out.json\" Path to dumped configuration schema file global.cnDocumentStoreType string \"DB\" Document store type to use for shibboleth files DB. global.cnGoogleApplicationCredentials string \"/etc/jans/conf/google-credentials.json\" Base64 encoded service account. The sa must have roles/secretmanager.admin to use Google secrets. Leave as this is a sensible default. global.cnPersistenceType string \"sql\" Persistence backend to run Janssen with hybrid global.cnPrometheusPort string \"\" Port used by Prometheus JMX agent (default to empty string). To enable Prometheus JMX agent, set the value to a number. global.cnSqlPasswordFile string \"/etc/jans/conf/sql_password\" Path to SQL password file global.config-api.appLoggers object {\"configApiLogLevel\":\"INFO\",\"configApiLogTarget\":\"STDOUT\",\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.config-api.appLoggers.configApiLogLevel string \"INFO\" configapi.log level global.config-api.appLoggers.configApiLogTarget string \"STDOUT\" configapi.log target global.config-api.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e config-api_persistence ===> 2022-12-20 17:49:55,744 INFO global.config-api.appLoggers.persistenceDurationLogLevel string \"INFO\" config-api_persistence_duration.log level global.config-api.appLoggers.persistenceDurationLogTarget string \"FILE\" config-api_persistence_duration.log target global.config-api.appLoggers.persistenceLogLevel string \"INFO\" config-api_persistence.log level global.config-api.appLoggers.persistenceLogTarget string \"FILE\" config-api_persistence.log target global.config-api.appLoggers.scriptLogLevel string \"INFO\" config-api_script.log level global.config-api.appLoggers.scriptLogTarget string \"FILE\" config-api_script.log target global.config-api.cnCustomJavaOptions string \"\" passing custom java options to config-api. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.config-api.configApiServerServiceName string \"config-api\" Name of the config-api service. Please keep it as default. global.config-api.enabled bool true Boolean flag to enable/disable the config-api chart. global.config-api.ingress object {\"configApiAdditionalAnnotations\":{},\"configApiEnabled\":true,\"configApiLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.config-api.ingress.configApiAdditionalAnnotations object {} ConfigAPI ingress resource additional annotations. global.config-api.ingress.configApiLabels object {} configAPI ingress resource labels. key app is taken global.config-api.plugins string \"fido2,scim,user-mgt\" Comma-separated values of enabled plugins (supported plugins are \"admin-ui\",\"fido2\",\"scim\",\"user-mgt\",\"jans-link\",\"kc-saml\") global.config.enabled bool true Boolean flag to enable/disable the configuration chart. This normally should never be false global.configAdapterName string \"kubernetes\" The config backend adapter that will hold Janssen configuration layer. aws global.configSecretAdapter string \"kubernetes\" The config backend adapter that will hold Janssen secret layer. vault global.fido2.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"fido2LogLevel\":\"INFO\",\"fido2LogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.fido2.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e fido2 ===> 2022-12-20 17:49:55,744 INFO global.fido2.appLoggers.fido2LogLevel string \"INFO\" fido2.log level global.fido2.appLoggers.fido2LogTarget string \"STDOUT\" fido2.log target global.fido2.appLoggers.persistenceDurationLogLevel string \"INFO\" fido2_persistence_duration.log level global.fido2.appLoggers.persistenceDurationLogTarget string \"FILE\" fido2_persistence_duration.log target global.fido2.appLoggers.persistenceLogLevel string \"INFO\" fido2_persistence.log level global.fido2.appLoggers.persistenceLogTarget string \"FILE\" fido2_persistence.log target global.fido2.appLoggers.scriptLogLevel string \"INFO\" fido2_script.log level global.fido2.appLoggers.scriptLogTarget string \"FILE\" fido2_script.log target global.fido2.cnCustomJavaOptions string \"\" passing custom java options to fido2. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.fido2.enabled bool true Boolean flag to enable/disable the fido2 chart. global.fido2.fido2ServiceName string \"fido2\" Name of the fido2 service. Please keep it as default. global.fido2.ingress object {\"fido2AdditionalAnnotations\":{},\"fido2ConfigAdditionalAnnotations\":{},\"fido2ConfigEnabled\":false,\"fido2ConfigLabels\":{},\"fido2Enabled\":false,\"fido2Labels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.fido2.ingress.fido2AdditionalAnnotations object {} fido2 ingress resource additional annotations. global.fido2.ingress.fido2ConfigAdditionalAnnotations object {} fido2 config ingress resource additional annotations. global.fido2.ingress.fido2ConfigEnabled bool false Enable endpoint /.well-known/fido2-configuration global.fido2.ingress.fido2ConfigLabels object {} fido2 config ingress resource labels. key app is taken global.fido2.ingress.fido2Enabled bool false Enable endpoint /jans-fido2 global.fido2.ingress.fido2Labels object {} fido2 ingress resource labels. key app is taken global.fqdn string \"demoexample.jans.io\" Fully qualified domain name to be used for Janssen installation. This address will be used to reach Janssen services. global.gcePdStorageType string \"pd-standard\" GCE storage kind if using Google disks global.isFqdnRegistered bool false Boolean flag to enable mapping global.lbIp to global.fqdn inside pods on clouds that provide static ip for load balancers. On cloud that provide only addresses to the LB this flag will enable a script to actively scan config.configmap.lbAddr and update the hosts file inside the pods automatically. global.istio.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of global.istio.additionalLabels object {} Additional labels that will be added across the gateway in the format of global.istio.enabled bool false Boolean flag that enables using istio side-cars with Janssen services. global.istio.gateways list [] Override the gateway that can be created by default. This is used when istio ingress has already been setup and the gateway exists. global.istio.ingress bool false Boolean flag that enables using istio gateway for Janssen. This assumes istio ingress is installed and hence the LB is available. global.istio.namespace string \"istio-system\" The namespace istio is deployed in. The is normally istio-system. global.jobTtlSecondsAfterFinished int 300 https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/ global.kc-scheduler.enabled bool false Boolean flag to enable/disable the kc-scheduler cronjob chart. global.lbIp string \"22.22.22.22\" The Loadbalancer IP created by nginx or istio on clouds that provide static IPs. This is not needed if global.fqdn is globally resolvable. global.link.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"linkLogLevel\":\"INFO\",\"linkLogTarget\":\"STDOUT\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.link.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e link-persistence ===> 2022-12-20 17:49:55,744 INFO global.link.appLoggers.linkLogLevel string \"INFO\" cacherefresh.log level global.link.appLoggers.linkLogTarget string \"STDOUT\" cacherefresh.log target global.link.appLoggers.persistenceDurationLogLevel string \"INFO\" cacherefresh_persistence_duration.log level global.link.appLoggers.persistenceDurationLogTarget string \"FILE\" cacherefresh_persistence_duration.log target global.link.appLoggers.persistenceLogLevel string \"INFO\" cacherefresh_persistence.log level global.link.appLoggers.persistenceLogTarget string \"FILE\" cacherefresh_persistence.log target global.link.appLoggers.scriptLogLevel string \"INFO\" cacherefresh_script.log level global.link.appLoggers.scriptLogTarget string \"FILE\" cacherefresh_script.log target global.link.cnCustomJavaOptions string \"\" passing custom java options to link. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.link.enabled bool false Boolean flag to enable/disable the link chart. global.link.ingress object {\"linkEnabled\":true} Enable endpoints in either istio or nginx ingress depending on users choice global.link.linkServiceName string \"link\" Name of the link service. Please keep it as default. global.nginx-ingress.enabled bool true Boolean flag to enable/disable the nginx-ingress definitions chart. global.persistence.enabled bool true Boolean flag to enable/disable the persistence chart. global.saml.cnCustomJavaOptions string \"\" passing custom java options to saml. DO NOT PASS JAVA_OPTIONS in envs. global.saml.enabled bool false Boolean flag to enable/disable the saml chart. global.saml.ingress object {\"samlAdditionalAnnotations\":{},\"samlEnabled\":false,\"samlLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.saml.ingress.samlAdditionalAnnotations object {} SAML ingress resource additional annotations. global.saml.ingress.samlLabels object {} SAML config ingress resource labels. key app is taken global.saml.samlServiceName string \"saml\" Name of the saml service. Please keep it as default. global.scim.appLoggers object {\"enableStdoutLogPrefix\":\"true\",\"persistenceDurationLogLevel\":\"INFO\",\"persistenceDurationLogTarget\":\"FILE\",\"persistenceLogLevel\":\"INFO\",\"persistenceLogTarget\":\"FILE\",\"scimLogLevel\":\"INFO\",\"scimLogTarget\":\"STDOUT\",\"scriptLogLevel\":\"INFO\",\"scriptLogTarget\":\"FILE\"} App loggers can be configured to define where the logs will be redirected to and the level of each in which it should be displayed. global.scim.appLoggers.enableStdoutLogPrefix string \"true\" Enable log prefixing which enables prepending the STDOUT logs with the file name. i.e jans-scim ===> 2022-12-20 17:49:55,744 INFO global.scim.appLoggers.persistenceDurationLogLevel string \"INFO\" jans-scim_persistence_duration.log level global.scim.appLoggers.persistenceDurationLogTarget string \"FILE\" jans-scim_persistence_duration.log target global.scim.appLoggers.persistenceLogLevel string \"INFO\" jans-scim_persistence.log level global.scim.appLoggers.persistenceLogTarget string \"FILE\" jans-scim_persistence.log target global.scim.appLoggers.scimLogLevel string \"INFO\" jans-scim.log level global.scim.appLoggers.scimLogTarget string \"STDOUT\" jans-scim.log target global.scim.appLoggers.scriptLogLevel string \"INFO\" jans-scim_script.log level global.scim.appLoggers.scriptLogTarget string \"FILE\" jans-scim_script.log target global.scim.cnCustomJavaOptions string \"\" passing custom java options to scim. Notice you do not need to pass in any loggers options as they are introduced below in appLoggers. DO NOT PASS JAVA_OPTIONS in envs. global.scim.enabled bool true Boolean flag to enable/disable the SCIM chart. global.scim.ingress object {\"scimAdditionalAnnotations\":{},\"scimConfigAdditionalAnnotations\":{},\"scimConfigEnabled\":false,\"scimConfigLabels\":{},\"scimEnabled\":false,\"scimLabels\":{}} Enable endpoints in either istio or nginx ingress depending on users choice global.scim.ingress.scimAdditionalAnnotations object {} SCIM ingress resource additional annotations. global.scim.ingress.scimConfigAdditionalAnnotations object {} SCIM config ingress resource additional annotations. global.scim.ingress.scimConfigEnabled bool false Enable endpoint /.well-known/scim-configuration global.scim.ingress.scimConfigLabels object {} SCIM config ingress resource labels. key app is taken global.scim.ingress.scimEnabled bool false Enable SCIM endpoints /jans-scim global.scim.ingress.scimLabels object {} SCIM config ingress resource labels. key app is taken global.scim.scimServiceName string \"scim\" Name of the scim service. Please keep it as default. global.serviceAccountName string \"default\" service account used by Kubernetes resources global.storageClass object {\"allowVolumeExpansion\":true,\"allowedTopologies\":[],\"mountOptions\":[\"debug\"],\"parameters\":{},\"provisioner\":\"microk8s.io/hostpath\",\"reclaimPolicy\":\"Retain\",\"volumeBindingMode\":\"WaitForFirstConsumer\"} StorageClass section. This is not currently used by the openbanking distribution. You may specify custom parameters as needed. global.storageClass.parameters object {} parameters: fsType: \"\" kind: \"\" pool: \"\" storageAccountType: \"\" type: \"\" global.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service. Envs defined in global.userEnvs will be globally available to all services global.usrEnvs.normal object {} Add custom normal envs to the service. variable1: value1 global.usrEnvs.secret object {} Add custom secret envs to the service. variable1: value1 kc-scheduler object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/kc-scheduler\",\"tag\":\"0.0.0-nightly\"},\"interval\":10,\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Responsible for synchronizing Keycloak SAML clients kc-scheduler.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of kc-scheduler.additionalLabels object {} Additional labels that will be added across the gateway in the format of kc-scheduler.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. kc-scheduler.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh kc-scheduler.dnsConfig object {} Add custom dns config kc-scheduler.dnsPolicy string \"\" Add custom dns policy kc-scheduler.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. kc-scheduler.image.pullSecrets list [] Image Pull Secrets kc-scheduler.image.repository string \"ghcr.io/janssenproject/jans/kc-scheduler\" Image to use for deploying. kc-scheduler.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. kc-scheduler.interval int 10 Interval of running the scheduler (in minutes) kc-scheduler.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. kc-scheduler.resources.limits.cpu string \"300m\" CPU limit. kc-scheduler.resources.limits.memory string \"300Mi\" Memory limit. kc-scheduler.resources.requests.cpu string \"300m\" CPU request. kc-scheduler.resources.requests.memory string \"300Mi\" Memory request. kc-scheduler.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service kc-scheduler.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 kc-scheduler.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 kc-scheduler.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers kc-scheduler.volumes list [] Configure any additional volumes that need to be attached to the pod link object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/link\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Link. link.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of link.additionalLabels object {} Additional labels that will be added across the gateway in the format of link.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. link.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh link.dnsConfig object {} Add custom dns config link.dnsPolicy string \"\" Add custom dns policy link.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler link.hpa.behavior object {} Scaling Policies link.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set link.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. link.image.pullSecrets list [] Image Pull Secrets link.image.repository string \"ghcr.io/janssenproject/jans/link\" Image to use for deploying. link.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. link.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. link.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http liveness probe endpoint link.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget link.readinessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http readiness probe endpoint link.replicas int 1 Service replica number. link.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}} Resource specs. link.resources.limits.cpu string \"500m\" CPU limit. link.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. link.resources.requests.cpu string \"500m\" CPU request. link.resources.requests.memory string \"1200Mi\" Memory request. link.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ link.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service link.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 link.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 link.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers link.volumes list [] Configure any additional volumes that need to be attached to the pod nginx-ingress object {\"ingress\":{\"additionalAnnotations\":{},\"additionalLabels\":{},\"hosts\":[\"demoexample.jans.io\"],\"ingressClassName\":\"nginx\",\"path\":\"/\",\"tls\":[{\"hosts\":[\"demoexample.jans.io\"],\"secretName\":\"tls-certificate\"}]}} Nginx ingress definitions chart nginx-ingress.ingress.additionalAnnotations object {} Additional annotations that will be added across all ingress definitions in the format of {cert-manager.io/issuer: \"letsencrypt-prod\"} Enable client certificate authentication nginx.ingress.kubernetes.io/auth-tls-verify-client: \"optional\" Create the secret containing the trusted ca certificates nginx.ingress.kubernetes.io/auth-tls-secret: \"janssen/tls-certificate\" Specify the verification depth in the client certificates chain nginx.ingress.kubernetes.io/auth-tls-verify-depth: \"1\" Specify if certificates are passed to upstream server nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: \"true\" nginx-ingress.ingress.additionalLabels object {} Additional labels that will be added across all ingress definitions in the format of nginx-ingress.ingress.tls list [{\"hosts\":[\"demoexample.jans.io\"],\"secretName\":\"tls-certificate\"}] Secrets holding HTTPS CA cert and key. persistence object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/persistence-loader\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"resources\":{\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} Job to generate data and initial config for Janssen Server persistence layer. persistence.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of persistence.additionalLabels object {} Additional labels that will be added across the gateway in the format of persistence.customCommand list [] Add custom job's command. If passed, it will override the default conditional command. persistence.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh persistence.dnsConfig object {} Add custom dns config persistence.dnsPolicy string \"\" Add custom dns policy persistence.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. persistence.image.pullSecrets list [] Image Pull Secrets persistence.image.repository string \"ghcr.io/janssenproject/jans/persistence-loader\" Image to use for deploying. persistence.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. persistence.resources object {\"limits\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"},\"requests\":{\"cpu\":\"300m\",\"memory\":\"300Mi\"}} Resource specs. persistence.resources.limits.cpu string \"300m\" CPU limit persistence.resources.limits.memory string \"300Mi\" Memory limit. persistence.resources.requests.cpu string \"300m\" CPU request. persistence.resources.requests.memory string \"300Mi\" Memory request. persistence.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service persistence.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 persistence.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 persistence.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers persistence.volumes list [] Configure any additional volumes that need to be attached to the pod saml object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/saml\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} SAML. saml.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of saml.additionalLabels object {} Additional labels that will be added across the gateway in the format of saml.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. saml.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh saml.dnsConfig object {} Add custom dns config saml.dnsPolicy string \"\" Add custom dns policy saml.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler saml.hpa.behavior object {} Scaling Policies saml.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set saml.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. saml.image.pullSecrets list [] Image Pull Secrets saml.image.repository string \"ghcr.io/janssenproject/jans/saml\" Image to use for deploying. saml.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. saml.livenessProbe object {\"exec\":{\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]},\"failureThreshold\":10,\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for the auth server if needed. saml.livenessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http liveness probe endpoint saml.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget saml.readinessProbe.exec object {\"command\":[\"python3\",\"/app/scripts/healthcheck.py\"]} http readiness probe endpoint saml.replicas int 1 Service replica number. saml.resources object {\"limits\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"500m\",\"memory\":\"1200Mi\"}} Resource specs. saml.resources.limits.cpu string \"500m\" CPU limit. saml.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. saml.resources.requests.cpu string \"500m\" CPU request. saml.resources.requests.memory string \"1200Mi\" Memory request. saml.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ saml.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service saml.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 saml.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 saml.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers saml.volumes list [] Configure any additional volumes that need to be attached to the pod scim object {\"additionalAnnotations\":{},\"additionalLabels\":{},\"customCommand\":[],\"customScripts\":[],\"dnsConfig\":{},\"dnsPolicy\":\"\",\"hpa\":{\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50},\"image\":{\"pullPolicy\":\"IfNotPresent\",\"pullSecrets\":[],\"repository\":\"ghcr.io/janssenproject/jans/scim\",\"tag\":\"0.0.0-nightly\"},\"lifecycle\":{},\"livenessProbe\":{\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5},\"pdb\":{\"enabled\":true,\"maxUnavailable\":\"90%\"},\"readinessProbe\":{\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5},\"replicas\":1,\"resources\":{\"limits\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"},\"requests\":{\"cpu\":\"1000m\",\"memory\":\"1200Mi\"}},\"service\":{\"name\":\"http-scim\",\"port\":8080},\"topologySpreadConstraints\":{},\"usrEnvs\":{\"normal\":{},\"secret\":{}},\"volumeMounts\":[],\"volumes\":[]} System for Cross-domain Identity Management (SCIM) version 2.0 scim.additionalAnnotations object {} Additional annotations that will be added across the gateway in the format of scim.additionalLabels object {} Additional labels that will be added across the gateway in the format of scim.customCommand list [] Add custom pod's command. If passed, it will override the default conditional command. scim.customScripts list [] Add custom scripts that have been mounted to run before the entrypoint. - /tmp/custom.sh - /tmp/custom2.sh scim.dnsConfig object {} Add custom dns config scim.dnsPolicy string \"\" Add custom dns policy scim.hpa object {\"behavior\":{},\"enabled\":true,\"maxReplicas\":10,\"metrics\":[],\"minReplicas\":1,\"targetCPUUtilizationPercentage\":50} Configure the HorizontalPodAutoscaler scim.hpa.behavior object {} Scaling Policies scim.hpa.metrics list [] metrics if targetCPUUtilizationPercentage is not set scim.image.pullPolicy string \"IfNotPresent\" Image pullPolicy to use for deploying. scim.image.pullSecrets list [] Image Pull Secrets scim.image.repository string \"ghcr.io/janssenproject/jans/scim\" Image to use for deploying. scim.image.tag string \"0.0.0-nightly\" Image tag to use for deploying. scim.livenessProbe object {\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":30,\"periodSeconds\":30,\"timeoutSeconds\":5} Configure the liveness healthcheck for SCIM if needed. scim.livenessProbe.httpGet.path string \"/jans-scim/sys/health-check\" http liveness probe endpoint scim.pdb object {\"enabled\":true,\"maxUnavailable\":\"90%\"} Configure the PodDisruptionBudget scim.readinessProbe object {\"httpGet\":{\"path\":\"/jans-scim/sys/health-check\",\"port\":8080},\"initialDelaySeconds\":25,\"periodSeconds\":25,\"timeoutSeconds\":5} Configure the readiness healthcheck for the SCIM if needed. scim.readinessProbe.httpGet.path string \"/jans-scim/sys/health-check\" http readiness probe endpoint scim.replicas int 1 Service replica number. scim.resources.limits.cpu string \"1000m\" CPU limit. scim.resources.limits.memory string \"1200Mi\" Memory limit. This value is used to calculate memory allocation for Java. Currently it only supports Mi . Please refrain from using other units. scim.resources.requests.cpu string \"1000m\" CPU request. scim.resources.requests.memory string \"1200Mi\" Memory request. scim.service.name string \"http-scim\" The name of the scim port within the scim service. Please keep it as default. scim.service.port int 8080 Port of the scim service. Please keep it as default. scim.topologySpreadConstraints object {} Configure the topology spread constraints. Notice this is a map NOT a list as in the upstream API https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ scim.usrEnvs object {\"normal\":{},\"secret\":{}} Add custom normal and secret envs to the service scim.usrEnvs.normal object {} Add custom normal envs to the service variable1: value1 scim.usrEnvs.secret object {} Add custom secret envs to the service variable1: value1 scim.volumeMounts list [] Configure any additional volumesMounts that need to be attached to the containers scim.volumes list [] Configure any additional volumes that need to be attached to the pod Autogenerated from chart metadata using helm-docs v1.14.2", "title": "Values"}, {"location": "janssen-server/scim/bulk-users/", "tags": ["administration", "scim", "bulk-users"], "text": "Adding user in bulk # SCIM supports a bulk operation allowing consumers of the service to send multiple resource operations in a single request. This means the body of a bulk operation may contain one or more operations belonging to any of the supported HTTP verbs, e.g., POST, PUT, DELETE, etc. This feature is useful, for instance, to create several users at once as we'll see below. Endpoint # The bulk endpoint is accessible at https://<your-server-mame>/jans-scim/restv1/v2/Bulk . Requests must be sent with a bearer token having scope https://jans.io/scim/bulk Bulk payload # A bulk is structured as a JSON document with two required properties: schemas : A list with the single string value urn:ietf:params:scim:api:messages:2.0:BulkRequest Operations : A JSON array describing every operation to perform in the order provided An operation is a JSON document with the following: method : The HTTP verb of the operation to perform path : The path of the actual endpoint to hit relative to the SCIM root. For instance, to create a user, it will be /Users data : The payload of the actual operation. This is required only for POST, PUT, or PATCH Payload example for adding users # { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:BulkRequest\" ], \"Operations\": [ { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"alanis\" } }, { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"sheryl\", \"active\": true, \"password\": \"top-secret\", \"roles\": [{ \"value\" : \"Master of puppets\" }] } }, { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"becca\", \"externalId\":\"becca_ponx_1234\", \"name\":{ \"familyName\": \"Cadalzo\", \"givenName\": \"Rebecca\" } } } ] } The above payload illustrates how to insert three users with different details each. Bulk response # The result of a bulk operation is likewise retrieved in JSON object format: schemas : A list with the single string value urn:ietf:params:scim:api:messages:2.0:BulkResponse Operations : A JSON array describing the response of every operation performed whether failed or successful An operation is a JSON document with the following: method : The HTTP verb of the operation performed location : The resource endpoint URL. For example, in the case of user creation, this will be the URL where the user's details can be retrieved status : A string value reporting the HTTP response code obtained for the given operation response : A JSON object only present when the status does not belong to the 2XX (success) family. It contains details of the error that occurred Response example # The following contains a potential response obtained for the bulk request mentioned earlier: { \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:BulkResponse\"], \"Operations\": [ { \"method\": \"POST\", \"location\": \"https://acme.co/jans-scim/restv1/v2/Users/92b725cd\", \"status\": \"201\" }, { \"method\": \"POST\", \"location\": \"https://acme.co/jans-scim/restv1/v2/Users/a27725cf\", \"status\": \"201\" }, { \"method\": \"POST\", \"status\": \"409\", \"response\":{ \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:Error\"], \"scimType\": \"uniqueness\" \"detail\": \"User 'becca' already exists\" } } ] } Bulk operation configuration # SCIM Jans server has a couple of configuration properties related to bulk operations: bulkMaxOperations : The maximum number of operations per bulk request. Default is 30 bulkMaxPayloadSize : The maximum payload size in bytes. Default value is 3072000", "title": "Bulk Adding Users"}, {"location": "janssen-server/scim/bulk-users/#adding-user-in-bulk", "text": "SCIM supports a bulk operation allowing consumers of the service to send multiple resource operations in a single request. This means the body of a bulk operation may contain one or more operations belonging to any of the supported HTTP verbs, e.g., POST, PUT, DELETE, etc. This feature is useful, for instance, to create several users at once as we'll see below.", "title": "Adding user in bulk"}, {"location": "janssen-server/scim/bulk-users/#endpoint", "text": "The bulk endpoint is accessible at https://<your-server-mame>/jans-scim/restv1/v2/Bulk . Requests must be sent with a bearer token having scope https://jans.io/scim/bulk", "title": "Endpoint"}, {"location": "janssen-server/scim/bulk-users/#bulk-payload", "text": "A bulk is structured as a JSON document with two required properties: schemas : A list with the single string value urn:ietf:params:scim:api:messages:2.0:BulkRequest Operations : A JSON array describing every operation to perform in the order provided An operation is a JSON document with the following: method : The HTTP verb of the operation to perform path : The path of the actual endpoint to hit relative to the SCIM root. For instance, to create a user, it will be /Users data : The payload of the actual operation. This is required only for POST, PUT, or PATCH", "title": "Bulk payload"}, {"location": "janssen-server/scim/bulk-users/#payload-example-for-adding-users", "text": "{ \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:BulkRequest\" ], \"Operations\": [ { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"alanis\" } }, { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"sheryl\", \"active\": true, \"password\": \"top-secret\", \"roles\": [{ \"value\" : \"Master of puppets\" }] } }, { \"method\": \"POST\", \"path\": \"/Users\", \"data\": { \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"], \"userName\": \"becca\", \"externalId\":\"becca_ponx_1234\", \"name\":{ \"familyName\": \"Cadalzo\", \"givenName\": \"Rebecca\" } } } ] } The above payload illustrates how to insert three users with different details each.", "title": "Payload example for adding users"}, {"location": "janssen-server/scim/bulk-users/#bulk-response", "text": "The result of a bulk operation is likewise retrieved in JSON object format: schemas : A list with the single string value urn:ietf:params:scim:api:messages:2.0:BulkResponse Operations : A JSON array describing the response of every operation performed whether failed or successful An operation is a JSON document with the following: method : The HTTP verb of the operation performed location : The resource endpoint URL. For example, in the case of user creation, this will be the URL where the user's details can be retrieved status : A string value reporting the HTTP response code obtained for the given operation response : A JSON object only present when the status does not belong to the 2XX (success) family. It contains details of the error that occurred", "title": "Bulk response"}, {"location": "janssen-server/scim/bulk-users/#response-example", "text": "The following contains a potential response obtained for the bulk request mentioned earlier: { \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:BulkResponse\"], \"Operations\": [ { \"method\": \"POST\", \"location\": \"https://acme.co/jans-scim/restv1/v2/Users/92b725cd\", \"status\": \"201\" }, { \"method\": \"POST\", \"location\": \"https://acme.co/jans-scim/restv1/v2/Users/a27725cf\", \"status\": \"201\" }, { \"method\": \"POST\", \"status\": \"409\", \"response\":{ \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:Error\"], \"scimType\": \"uniqueness\" \"detail\": \"User 'becca' already exists\" } } ] }", "title": "Response example"}, {"location": "janssen-server/scim/bulk-users/#bulk-operation-configuration", "text": "SCIM Jans server has a couple of configuration properties related to bulk operations: bulkMaxOperations : The maximum number of operations per bulk request. Default is 30 bulkMaxPayloadSize : The maximum payload size in bytes. Default value is 3072000", "title": "Bulk operation configuration"}, {"location": "janssen-server/scim/config/", "tags": ["administration", "scim", "configuration"], "text": "SCIM configuration # Relevant configuration properties of the Jans SCIM server are summarized in the table below: Property Default value Description maxCount 200 Maximum number of results per page in search endpoints bulkMaxOperations 30 Maximum number of operations admitted in a single bulk request bulkMaxPayloadSize 3072000 Maximum payload size in bytes admitted in a single bulk request userExtensionSchemaURI urn:ietf:params:scim:schemas:extension:gluu:2.0:User URI schema associated to the User Extension skipDefinedPasswordValidation false Whether the validation rules defined for the password attribute in the server should be bypassed when a user is created/updated loggingLevel INFO The logging level Configuration management using CLI # To retrieve the current server configuration run the command python3 jans cli --operation-id get-scim-config To modify some aspect of the retrieved configuration prepare a PATCH request in JSON format. For instance: PATCH [ { \"op\" : \"replace\" , \"path\" : \"bulkMaxOperations\" , \"value\" : 100 }, { \"op\" : \"replace\" , \"path\" : \"loggingLevel\" , \"value\" : \"DEBUG\" } ] These contents should be then passed to the patch-scim-config operation, e.g. python3 jans cli --operation-id patch-scim-config --data <path-to-JSON-file> Configuration management using TUI # To retrieve the current server configuration using TUI proceed as below: Launch TUI, e.g. by running jans tui , and follow the prompts Highlight the SCIM tab using your keyboard's left/right arrow key Highlight the \"Get Scim Configuration\" button using the tab key Press enter You can modify the configuration in place by editing the fields of your interest. To persist the changes, highlight the \"Save\" button at the bottom and press enter. SCIM Operations Guide using CLI, TUI and API # SCIM operations support mutiple options. Please check out this documentation for guidelines of scim operations. When will changes take effect? # Any configuration update will take effect one minute after it has been applied whether via CLI or TUI.", "title": "Configuration"}, {"location": "janssen-server/scim/config/#scim-configuration", "text": "Relevant configuration properties of the Jans SCIM server are summarized in the table below: Property Default value Description maxCount 200 Maximum number of results per page in search endpoints bulkMaxOperations 30 Maximum number of operations admitted in a single bulk request bulkMaxPayloadSize 3072000 Maximum payload size in bytes admitted in a single bulk request userExtensionSchemaURI urn:ietf:params:scim:schemas:extension:gluu:2.0:User URI schema associated to the User Extension skipDefinedPasswordValidation false Whether the validation rules defined for the password attribute in the server should be bypassed when a user is created/updated loggingLevel INFO The logging level", "title": "SCIM configuration"}, {"location": "janssen-server/scim/config/#configuration-management-using-cli", "text": "To retrieve the current server configuration run the command python3 jans cli --operation-id get-scim-config To modify some aspect of the retrieved configuration prepare a PATCH request in JSON format. For instance: PATCH [ { \"op\" : \"replace\" , \"path\" : \"bulkMaxOperations\" , \"value\" : 100 }, { \"op\" : \"replace\" , \"path\" : \"loggingLevel\" , \"value\" : \"DEBUG\" } ] These contents should be then passed to the patch-scim-config operation, e.g. python3 jans cli --operation-id patch-scim-config --data <path-to-JSON-file>", "title": "Configuration management using CLI"}, {"location": "janssen-server/scim/config/#configuration-management-using-tui", "text": "To retrieve the current server configuration using TUI proceed as below: Launch TUI, e.g. by running jans tui , and follow the prompts Highlight the SCIM tab using your keyboard's left/right arrow key Highlight the \"Get Scim Configuration\" button using the tab key Press enter You can modify the configuration in place by editing the fields of your interest. To persist the changes, highlight the \"Save\" button at the bottom and press enter.", "title": "Configuration management using TUI"}, {"location": "janssen-server/scim/config/#scim-operations-guide-using-cli-tui-and-api", "text": "SCIM operations support mutiple options. Please check out this documentation for guidelines of scim operations.", "title": "SCIM Operations Guide using CLI, TUI and API"}, {"location": "janssen-server/scim/config/#when-will-changes-take-effect", "text": "Any configuration update will take effect one minute after it has been applied whether via CLI or TUI.", "title": "When will changes take effect?"}, {"location": "janssen-server/scim/custom-attributes/", "tags": ["administration", "scim", "custom-attributes"], "text": "Custom Attributes # RFC 7643 defines the schema for resource types in SCIM (see section 3.3). In other words, it defines structures in terms of attributes to represent users and groups as well as attribute types, mutability, cardinality, and so on. Although the schema covers many attributes one might think of, at times you will need to add your own attributes for specific needs. This is where user extensions pitch in, they allow you to create custom attributes for SCIM. To do so, you will have to: Add an attribute to Database schema Include the new attribute in an object class such as jansPerson Register and activate your new attribute through Jans TUI . Please visit this page for a more detailed explanation. When registering the attribute in the TUI , please ensure you have set the Include in SCIM Extension parameter to true . Once you submit this form, your attribute will be part of the User Extension . You can verify this by inspecting the Schema endpoint: Command https://<host-name>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:extension:gluu:2.0:User In the JSON response, your new added attribute will appear. To customize the URI associated to the extension (whose default value is urn:ietf:params:scim:schemas:extension:gluu:2.0:User ), you can use TUI: Navigate to SCIM using Jans TUI jans tui Locate the Scim properties section Set a value in the field User Extension Schema URI Save the changes", "title": "Adding Custom Attributes"}, {"location": "janssen-server/scim/custom-attributes/#custom-attributes", "text": "RFC 7643 defines the schema for resource types in SCIM (see section 3.3). In other words, it defines structures in terms of attributes to represent users and groups as well as attribute types, mutability, cardinality, and so on. Although the schema covers many attributes one might think of, at times you will need to add your own attributes for specific needs. This is where user extensions pitch in, they allow you to create custom attributes for SCIM. To do so, you will have to: Add an attribute to Database schema Include the new attribute in an object class such as jansPerson Register and activate your new attribute through Jans TUI . Please visit this page for a more detailed explanation. When registering the attribute in the TUI , please ensure you have set the Include in SCIM Extension parameter to true . Once you submit this form, your attribute will be part of the User Extension . You can verify this by inspecting the Schema endpoint: Command https://<host-name>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:extension:gluu:2.0:User In the JSON response, your new added attribute will appear. To customize the URI associated to the extension (whose default value is urn:ietf:params:scim:schemas:extension:gluu:2.0:User ), you can use TUI: Navigate to SCIM using Jans TUI jans tui Locate the Scim properties section Set a value in the field User Extension Schema URI Save the changes", "title": "Custom Attributes"}, {"location": "janssen-server/scim/logs/", "tags": ["administration", "scim"], "text": "SCIM Logs # Logs can be found under /opt/jans/jetty/jans-scim/logs in your Janssen Server. The default logging level is INFO but this can be changed to any of TRACE , DEBUG , WARN , OR ERROR via TUI. To do so launch TUI, e.g. jans tui , and navigate to SCIM tab. Then in \"Logging Level\" select the desired option. Finally hit \"Save\".", "title": "Logs"}, {"location": "janssen-server/scim/logs/#scim-logs", "text": "Logs can be found under /opt/jans/jetty/jans-scim/logs in your Janssen Server. The default logging level is INFO but this can be changed to any of TRACE , DEBUG , WARN , OR ERROR via TUI. To do so launch TUI, e.g. jans tui , and navigate to SCIM tab. Then in \"Logging Level\" select the desired option. Finally hit \"Save\".", "title": "SCIM Logs"}, {"location": "janssen-server/scim/monitoring/", "tags": ["administration", "scim"], "text": "How is SCIM data stored? # SCIM schema spec does not use LDAP attribute names but a different naming convention for resource attributes (note this is not the case of custom attributes where the SCIM name used is that of the LDAP attribute). It is possible to determine if a given LDAP attribute is being mapped to a SCIM attribute. For that you need to check in Jans TUI Auth-Server >> Attributes and click on any attributes. Check Include in SCIM Extension: is true or false . Whenever you try to map any LDAP attribute to a SCIM attribute keep it's value true . Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Monitoring"}, {"location": "janssen-server/scim/monitoring/#how-is-scim-data-stored", "text": "SCIM schema spec does not use LDAP attribute names but a different naming convention for resource attributes (note this is not the case of custom attributes where the SCIM name used is that of the LDAP attribute). It is possible to determine if a given LDAP attribute is being mapped to a SCIM attribute. For that you need to check in Jans TUI Auth-Server >> Attributes and click on any attributes. Check Include in SCIM Extension: is true or false . Whenever you try to map any LDAP attribute to a SCIM attribute keep it's value true .", "title": "How is SCIM data stored?"}, {"location": "janssen-server/scim/monitoring/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/scim/monitoring/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/scim/oauth-protection/", "tags": ["administration", "scim"], "text": "OAuth protection # The SCIM API endpoints are by default protected by (Bearer) OAuth 2.0 tokens. Depending on the operation, these tokens must have certain scopes for the operations to be authorized. The table below summarizes this fact: Scope Description https://jans.io/scim/users.read Query/Search user resources https://jans.io/scim/users.write Modify user resources https://jans.io/scim/groups.read Query group resources https://jans.io/scim/groups.write Modify group resources https://jans.io/scim/fido.read Query fido resources https://jans.io/scim/fido.write Modify fido resources https://jans.io/scim/fido2.read Query fido 2 resources https://jans.io/scim/fido2.write Modify fido 2 resources https://jans.io/scim/bulk Send requests to the bulk endpoint https://jans.io/scim/all-resources.search Access the root .search endpoint Correspondence of endpoints vs. scopes can be found in the SCIM OpenAPI descriptor you can find here . Client details # To obtain valid tokens, you would normally have to register a client (in the server) capable of obtaining tokens with the scopes needed. Registration is out of the scope of this document, however you can leverage the client that is already bundled in your server for SCIM interaction. With this client you can issue tokens with any SCIM-related scope. Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE . Getting a token # This is a curl example of how to get a token valid for retrieving and modifying users (line breaks added for readability). Note the use of white space to separate scope names. Command curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type = client_credentials -d scope = 'https://jans.io/scim/users.read https://jans.io/scim/users.write' https://your-jans-server/jans-auth/restv1/token Grab the \"access_token\" from the obtained response. Issue a request to the service # The below is a curl example of how to call an operation by passing the previously obtained token (line breaks added for readability): Command curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://your-jans-server/jans-scim/restv1/v2/Users The output should show valid SCIM (JSON) output. Account the access token is short-lived: once it expires you will get a status response of 401 and need to re-request the token as in the previous step. Deactivating OAuth mode # OAuth tokens usage is a safe, standardized approach for controlling access to resources. If for some reason you want to turn off protection you can do so by activating bypass mode: in TUI, navigate to SCIM tab and under \"Protection Mode\" select \"BYPASS\". Finally press \"Save\". Caution: keep in mind that with \"BYPASS\" you should add some sort of protection to your endpoints, say, at the network level to avoid anyone to mess with your user base among other resources.", "title": "OAuth Protection"}, {"location": "janssen-server/scim/oauth-protection/#oauth-protection", "text": "The SCIM API endpoints are by default protected by (Bearer) OAuth 2.0 tokens. Depending on the operation, these tokens must have certain scopes for the operations to be authorized. The table below summarizes this fact: Scope Description https://jans.io/scim/users.read Query/Search user resources https://jans.io/scim/users.write Modify user resources https://jans.io/scim/groups.read Query group resources https://jans.io/scim/groups.write Modify group resources https://jans.io/scim/fido.read Query fido resources https://jans.io/scim/fido.write Modify fido resources https://jans.io/scim/fido2.read Query fido 2 resources https://jans.io/scim/fido2.write Modify fido 2 resources https://jans.io/scim/bulk Send requests to the bulk endpoint https://jans.io/scim/all-resources.search Access the root .search endpoint Correspondence of endpoints vs. scopes can be found in the SCIM OpenAPI descriptor you can find here .", "title": "OAuth protection"}, {"location": "janssen-server/scim/oauth-protection/#client-details", "text": "To obtain valid tokens, you would normally have to register a client (in the server) capable of obtaining tokens with the scopes needed. Registration is out of the scope of this document, however you can leverage the client that is already bundled in your server for SCIM interaction. With this client you can issue tokens with any SCIM-related scope. Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE .", "title": "Client details"}, {"location": "janssen-server/scim/oauth-protection/#getting-a-token", "text": "This is a curl example of how to get a token valid for retrieving and modifying users (line breaks added for readability). Note the use of white space to separate scope names. Command curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type = client_credentials -d scope = 'https://jans.io/scim/users.read https://jans.io/scim/users.write' https://your-jans-server/jans-auth/restv1/token Grab the \"access_token\" from the obtained response.", "title": "Getting a token"}, {"location": "janssen-server/scim/oauth-protection/#issue-a-request-to-the-service", "text": "The below is a curl example of how to call an operation by passing the previously obtained token (line breaks added for readability): Command curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://your-jans-server/jans-scim/restv1/v2/Users The output should show valid SCIM (JSON) output. Account the access token is short-lived: once it expires you will get a status response of 401 and need to re-request the token as in the previous step.", "title": "Issue a request to the service"}, {"location": "janssen-server/scim/oauth-protection/#deactivating-oauth-mode", "text": "OAuth tokens usage is a safe, standardized approach for controlling access to resources. If for some reason you want to turn off protection you can do so by activating bypass mode: in TUI, navigate to SCIM tab and under \"Protection Mode\" select \"BYPASS\". Finally press \"Save\". Caution: keep in mind that with \"BYPASS\" you should add some sort of protection to your endpoints, say, at the network level to avoid anyone to mess with your user base among other resources.", "title": "Deactivating OAuth mode"}, {"location": "janssen-server/scim/security/", "tags": ["administration", "scim"], "text": "Security considerations # SCIM API allows administrators and developers manage a key asset in an IAM deployment, namely users. Additionally, other resources like groups and registered fido devices can be managed in Janssen Server via SCIM. Clearly, this kind of API must not be anonymously accessible. However, the SCIM standard does not define a specific mechanism to prevent unauthorized requests to endpoints. There are just a few guidelines in section 2 of RFC 7644 concerned with authentication and authorization. Currently, the Janssen server supports an OAuth-based mechanism to protect these endpoints; you can find more information in this regard here . Nonetheless, it is recommended not to expose this API outside the organization's network. Ideally administrators should block any external attempt to access URLs under the path https://your-jans-server/jans-scim .", "title": "Security Considerations"}, {"location": "janssen-server/scim/security/#security-considerations", "text": "SCIM API allows administrators and developers manage a key asset in an IAM deployment, namely users. Additionally, other resources like groups and registered fido devices can be managed in Janssen Server via SCIM. Clearly, this kind of API must not be anonymously accessible. However, the SCIM standard does not define a specific mechanism to prevent unauthorized requests to endpoints. There are just a few guidelines in section 2 of RFC 7644 concerned with authentication and authorization. Currently, the Janssen server supports an OAuth-based mechanism to protect these endpoints; you can find more information in this regard here . Nonetheless, it is recommended not to expose this API outside the organization's network. Ideally administrators should block any external attempt to access URLs under the path https://your-jans-server/jans-scim .", "title": "Security considerations"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/", "tags": ["administration", "user management", "cli", "tui"], "text": "Local User Management # In this document we will cover managing people in the Jans Server's Jans CLI and Jans TUI. Manage data in Jans TUI # We can easily add a user using Jans TUI. To do that, run the TUI using jans tui for example, and click on the Users tab. Let's see at a glance user attributes. Attributes Description Username ... Password ... First Name ... Middle Name ... Last Name ... Display Name ... Email ... Active ... Nickname ... CIBA Device Registration Token ... CIBA User code ... Locale ... Website URL ... IMAP Data ... jansAdminUIRole ... Enrollment code ... User Permission ... Preferred Language ... Profile URL ... Secret Question ... Email Verified ... Birthdate ... Time zone info ... Phone Number verified ... Preferred Username ... TransientId ... PersistentId ... Country ... Secret Answer ... OpenID Connect JSON formatted address ... User certificate ... Organization ... Picture URL ... Let's add an user by selecting Add Users tab. Initially we can provide bellow attributes value, We can add extra claims simple by slecting Add Claim Finally save and exit. We will get an unique inum Change User Password # No chance to recover user password, but you can change. To change password of a user navigate/or search user and press key p when the target user is higlighted. In the figure below, passowrd of user sakamura is being changed. Once you write new password (it will be displayed while you type), go to button < Save > and press Enter. Manage User FIDO Devices # To view and manage users registered FIDO devices, first navigate/or search user and press key f on the keyboard. If user has any registered FIDO device, a popup will appears as in image below: You can veiw details of a device by pressing Enter. To delete a device press key d , you will be prompted for confirmation. This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Using CLI/TUI"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#local-user-management", "text": "In this document we will cover managing people in the Jans Server's Jans CLI and Jans TUI.", "title": "Local User Management"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#manage-data-in-jans-tui", "text": "We can easily add a user using Jans TUI. To do that, run the TUI using jans tui for example, and click on the Users tab. Let's see at a glance user attributes. Attributes Description Username ... Password ... First Name ... Middle Name ... Last Name ... Display Name ... Email ... Active ... Nickname ... CIBA Device Registration Token ... CIBA User code ... Locale ... Website URL ... IMAP Data ... jansAdminUIRole ... Enrollment code ... User Permission ... Preferred Language ... Profile URL ... Secret Question ... Email Verified ... Birthdate ... Time zone info ... Phone Number verified ... Preferred Username ... TransientId ... PersistentId ... Country ... Secret Answer ... OpenID Connect JSON formatted address ... User certificate ... Organization ... Picture URL ... Let's add an user by selecting Add Users tab. Initially we can provide bellow attributes value, We can add extra claims simple by slecting Add Claim Finally save and exit. We will get an unique inum", "title": "Manage data in Jans TUI"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#change-user-password", "text": "No chance to recover user password, but you can change. To change password of a user navigate/or search user and press key p when the target user is higlighted. In the figure below, passowrd of user sakamura is being changed. Once you write new password (it will be displayed while you type), go to button < Save > and press Enter.", "title": "Change User Password"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#manage-user-fido-devices", "text": "To view and manage users registered FIDO devices, first navigate/or search user and press key f on the keyboard. If user has any registered FIDO device, a popup will appears as in image below: You can veiw details of a device by pressing Enter. To delete a device press key d , you will be prompted for confirmation.", "title": "Manage User FIDO Devices"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/usermgmt/usermgmt-cli-tui/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/usermgmt/usermgmt-jans-link/", "tags": ["administration", "user management", "jans-link"], "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Using jans-link"}, {"location": "janssen-server/usermgmt/usermgmt-jans-link/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "janssen-server/usermgmt/usermgmt-jans-link/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "janssen-server/usermgmt/usermgmt-jans-link/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "janssen-server/usermgmt/usermgmt-scim/", "tags": ["administration", "user management", "scim"], "text": "SCIM User Management # SCIM is a specification designed to reduce the complexity of user management operations by providing a common user schema and the patterns for exchanging such schema using HTTP in a platform-neutral fashion. The aim of SCIM is achieving interoperability, security, and scalability in the context of identity management. For your reference, the current version of the standard is governed by the following documents: RFC 7642 , RFC 7643 , and RFC 7644 . Installation # The API is available as a component of Jans Server. Upon installation you can select if you want SCIM included in your environment. To add SCIM post-install do the following: Run python3 /opt/jans/jans-setup/setup.py --install-scim About API endpoints # Throughout this document, you will notice endpoints are prefixed with path: /jans-scim/restv1/v2 API Protection # Clearly, this API must not be anonymously accessed. However, the basic SCIM standard does not define a specific mechanism to prevent unauthorized requests to endpoints. There are just a few guidelines in section 2 of RFC 7644 concerned with authentication and authorization. OAUTH, This is the default and recommended mechanism BYPASS Depending on the scopes associated to a token, you will be granted (or denied) access to perform certain operations. The following lists the available scopes: Scope Actions allowed https://jans.io/scim/users.read Query user resources https://jans.io/scim/users.write Modify user resources https://jans.io/scim/groups.read Query group resources https://jans.io/scim/groups.write Modify group resources https://jans.io/scim/fido.read Query fido resources https://jans.io/scim/fido.write Modify fido resources https://jans.io/scim/fido2.read Query fido 2 resources https://jans.io/scim/fido2.write Modify fido 2 resources https://jans.io/scim/all-resources.search Access the root .search endpoint https://jans.io/scim/bulk Send requests to the bulk endpoint In order to facilitate the process of getting an access token, your Janssen installation already bundles an OAuth client named \"SCIM client\" with support for all the scopes above. This client uses the client_credentials grant type and client_secret_basic mechanism to authenticate to the token endpoint. Where to locate SCIM-related logs # Please see here besides SCIM log is located at /opt/jans/jetty/jans-scim/logs/scim.log If you use SCIM custom script aslo see /opt/jans/jetty/jans-scim/logs/scim_script.log API documentation at a glance # SCIM API doc page describes about our implementation of SCIM. The API has also been documented using OpenAPI (swagger) specification for the interested. Find yaml files here . Working in OAuth mode # To know more about OAuth protection mode please visit here . The SCIM API endpoints are by default protected by (Bearer) OAuth 2.0 tokens. Depending on the operation, these tokens must have certain scopes for the operations to be authorized. We need a client to get Bearer token. Get SCIM Client # Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. To see in JSON formate please press d . From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE . Get Access token # Let's get a token, curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type=client_credentials -d scope='https://jans.io/scim/users.read https://jans.io/scim/users write' https://<jans-server>/jans-auth/restv1/token > /tmp/token.json In response token.json we will get access_token { \"access_token\":\"11a76589-7955-4247-9ca5-f3ad7884305...\", \"scope\":\"https://jans.io/scim/users.read\", \"token_type\":\"Bearer\", \"expires_in\":299 } Retrive existing User # To get an existing user curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://<jans-server>/jans-scim/restv1/v2/Users > /tmp/user.json In response user.json we will get { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\": 1, \"startIndex\": 1, \"itemsPerPage\": 1, \"Resources\": [ { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"5fdbb720-a1fd-477f-af92-b7c054f02c98\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-12T14:54:09.531Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/5fdbb720-a1fd-477f-af92-b7c054f02c98\" }, \"userName\": \"admin\", \"name\": { \"familyName\": \"...\", \"givenName\": \"...\", \"middleName\": \"...\", \"formatted\": \"...\" }, \"displayName\": \"Admin\", \"active\": true, \"emails\": [ { \"value\": \"example@gluu.org\", \"primary\": false } ], \"groups\": [ { \"value\": \"60B7\", \"display\": \"Jannsen Manager Group\", \"type\": \"direct\", \"$ref\": \"https://raju.jans13.me/jans-scim/restv1/v2/Groups/60B7\" } ] } ] } Creating Resource # Create an User # Let's start creating a dummy user. A client sends a POST request containing a \"User\" to the \"/Users\" endpoint. POST /Users HTTP/1.1 Host: example.com Accept: application/scim+json Content-Type: application/scim+json Authorization: Bearer h480djs93hd8.. Content-Length: ... { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" } } Open a text editor and copy paste the json body, name as input.json . Hit on your terminal with bellow command. curl -k -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users response looks like { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T19:43:32.945Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Barbara\", \"formatted\": \"Ms. Barbara J Jensen III\" } } This new user has been given an id . If possible, inspect your ou=people branch and find the entry whose inum matches the id given. An easier option would be to via Jans TUI and go to Users and search \"bjensen\" to see the recently created user. Updating a User(PUT) # Overwrite your input.json with the following. Replace content in angle brackets accordingly: { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" }, \"displayName\": \"Jensen Barbara\", \"emails\": [ { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": true } ] } PUT with curl: curl -k -X PUT -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Response (output.json) will show the same contents of a full retrieval. Please verify changes were applied whether by inspecting LDAP or issuing a GET. If you have followed the steps properly, you should notice a new e-mail added and the change in displayName attribute Updating a User (PATCH) # With patching, you can be very precise about the modifications you want to apply. Patching syntax follows JSON Patch spec (RFC 6902) closely. While it's not a must to read the RFC to learn how patch works, see section 3.5.2 of SCIM protocol (RFC 7644) to get the grasp. If you prefer reading code, patch test cases found in the Java scim-client project are worth to look at. The following is a simple example that illustrates the kind of modifications developers can achieve via PATCH . Overwrite your input.json with the following: { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"value\": { \"name\": { \"givenName\": \"Joey\" } } }, { \"op\": \"replace\", \"path\": \"emails[type eq \\\"work\\\" or primary eq false].value\", \"value\": \"jensen@example.com\" }, { \"op\": \"add\", \"value\": { \"name\": { \"middleName\": \"Jhon\" } } }, { \"op\": \"add\", \"value\": { \"emails\": [ { \"primary\": true, \"value\": \"my@own.mail\" } ], \"phoneNumbers\": [ { \"type\": \"home\", \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } }, { \"op\": \"remove\", \"path\": \"name.middleName\" }, { \"op\": \"remove\", \"path\": \"phoneNumbers[value ew \\\"01\\\"].type\" } ] } A collection of modification are provided under \"Operations\". They are processed in order of appearance. Also, every operation has a type; patching supports add, remove and replace. The first operations states the following: replace the value of givenName subattribute (that belongs to complex attribute name ) with the string \"Joey\". Operations are easier to understand when using a \"path\". The second operation replaces the value subattribute inside the complex multi-valued attribute emails. Inside the square brackets, we find a filter expression, so the replacement does not apply to all emails in the list but only to those matching the criterion. So the second operation can be read as \"set the value of value subattribute to string jensen@example.com where the type subattribute of the email equals to string \"work\" or if primary attribute is false\". The third operation is similar to the first. It sets the value of a subattribute which was unassigned (null). You could have used \"replace\" operation in this case and results would have been identical. The fourth operation is more interesting. It adds to the current list of emails a new one. It supplies a couple of subattributes for the email to include: primary and value. Additionally, we set the value of (previously unassigned) phoneNumbers multi-valued attribute passing a list of elements. In the fifth operation, we remove the middleName attribute that was set in operation three. Note how we make explicit the path of data to nullify: \"name.middleName\". The sixth operation allows us to remove a specific subattribute of phoneNumbers . The aim is to nullify the \"type\" of the item whose phone number value ends with \"01\". The remove operation can also be used to remove a complete item from a list, or empty the whole list by providing a suitable value for \"path\". Now let's see it in action: curl -k -X PATCH -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> So far our resource look like this { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T22:34:27.465Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Joey\", \"formatted\": \"Ms. Barbara J Jensen III\" }, \"displayName\": \"Jensen Barbara\", \"active\": false, \"emails\": [ { \"value\": \"my@own.mail\", \"primary\": true }, { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": false } ], \"phoneNumbers\": [ { \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } Note the primary subattribute accompanying email \"my@own.mail\" is false but when inserted we provided true . This is because the SCIM specification states that after modifications are applied to resources (PUT or PATCH) , there cannot be more than one item in a multi-valued attribute with primary value set as true . To see more sample JSON payloads, check the .json files used by the scim-client test cases referenced above. Deleting Users # For deleting, the DELETE method of HTTP is used. No input file is used in this case. A delete request could be the following: curl -k -X DELETE -H 'Authorization: Bearer ACCESS_TOKEN' https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Use the inum of our dummy user, Jensen Barbara . Check your LDAP or via Jans TUI to see that Bjensen is gone. How is SCIM data stored? # SCIM schema spec does not use LDAP attribute names but a different naming convention for resource attributes (note this is not the case of custom attributes where the SCIM name used is that of the LDAP attribute). It is possible to determine if a given LDAP attribute is being mapped to a SCIM attribute. For that you need to check in Jans TUI Auth-Server >> Attributes and click on any attributes. Check Include in SCIM Extension: is true or false . Whenever you try to map any LDAP attribute to a SCIM attribute keep it's value true . FIDO Devices # A FIDO device represents a user credential stored in the Jans Server database that is compliant with the FIDO standard. These devices are used as a second factor in a setting of strong authentication. FIDO devices were superseded by FIDO 2 devices in Jans Server. FIDO 2 devices # FIDO 2 devices are credentials that adhere to the more current Fido 2.0 initiative (WebAuthn + CTAP). Examples of FIDO 2 devices are USB security keys and Super Gluu devices. The SCIM endpoints for FIDO 2 allow application developers to query, update and delete already existing devices. Addition of devices do not take place through the service since this process requires direct end-user interaction, ie. device enrolling. The schema attributes for a device of this kind can be found by hitting the URL https://<jans-server>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:Fido2Device To distinguish between regular FIDO2 and SuperGluu devices, note only SuperGluu entries have the attribute deviceData populated (i.e. not null) Example: Querying Enrolled Devices # Say we are interested in having a list of Super Gluu devices users have enrolled and whose operating system is iOS. We may issue a query like this: curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=deviceData co \"ios\"' -d count=10 https://<jans-server>/jans-scim/restv1/v2/Fido2Devices The response will be like: { \"totalResults\": ..., \"itemsPerPage\": ..., \"startIndex\": 1, \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"Resources\": [ { \"id\": \"...\", \"meta\": {...}, \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:Fido2Device\"], \"userId\": \"...\", ... \"deviceData\": \"{...}\", \"displayName\": ..., }, ... ] } Potential performance issues with Group endpoints # In SCIM a group resource basically consists of an identifier, a display name, and a collection of members associated to it. Also, every member is made up of a user identifier, his display name, and other attributes. As a consequence, retrieving group information requires making a correlation with existing user data. Since Gluu database model does not follow a relational database pattern this may entail a considerable amount of user queries when groups contain thousands of members. While this could have been workarounded by storing members' display names inside group entries, this brings additional problems to deal with. Another source of potential overhead stems from creation and modification of groups where many new users are associated to a given group: by default checks are made to guarantee only existing users are attached to groups, thus requiring continuous database queries. Currently there are two ways to lower the amount of database lookups required for SCIM group operations: Explicitly excluding display names from responses Pass the overhead bypass flag to skip members validations The first approach consists of using the query parameter excludedAttributes (see RFC 7644 ) so that display names are neither retrieved from database nor sent in responses. A value like members.display does the job. Note the query parameter attributes can also be used for this purpose, for example with a value like members.value that will output only members' identifiers and ignore other non-required attributes. This approach is particularly useful in search and retrievals when users' display names are not needed. The second is a stronger approach that turns off validation of incoming members data: if the usage of a POST/PUT/PATCH operation implies adding members, their existence is not verified, they will simply get added. Here, the client application is responsible for sending accurate data. To use this approach add a query or header parameter named Group-Overhead-Bypass with any value. Note under this mode of operation: Display names are never returned regardless of attributes or excludedAttributes parameters values Remove/replace patch operations that involve display names in path filters are ignored, eg: \"path\": \"members[value eq \\\"2819c223\\\" or display eq \\\"Joe\\\"]\" User Registration Process with SCIM # SCIM service has many use cases. One interesting and often arising is that of coding your own user registration process. With your SCIM endpoints you can build a custom application to maintain user entries in your database. Important Considerations # Here, you have some useful tips before you start: Choose a toolset you feel comfortable to work with. Keep in mind that you have to leverage the capabilities of your language/framework to issue complex HTTPS requests. Be sure that: You will be able to use at least the following verbs: GET, POST, PUT, and DELETE You can send headers in your requests as well as reading them from the service response If not supported natively, choose a library to facilitate JSON content manipulation. As you have already noticed we have been dealing with JSON for requests as well as for responses. Experience shows that being able to map from objects (or data structures) of your language to Json and viceversa helps saving hours of coding. Shape your data model early. List the attributes your application will operate upon and correlate with those found in the SCIM user schema. You can learn about the schema in RFC 7644 . At least, take a look at the JSON-formatted schema that your Jans Server shows: visit https://<host-name>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:User You will have to manipulate database contents very often as you develop and run tests, thus, find a suitable tool for the task. In the case of LDAP, a TUI client is a good choice. Always check your logs . In this user management guide with SCIM, we have already touched upon the fundamentals of SCIM in Jans Server and shown a good amount of sample requests for manipulation of user information. However, keep in mind the SCIM spec documents are definitely the key reference to build working request messages, specially RFC 7643 , and RFC 7644 .", "title": "Using SCIM"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#scim-user-management", "text": "SCIM is a specification designed to reduce the complexity of user management operations by providing a common user schema and the patterns for exchanging such schema using HTTP in a platform-neutral fashion. The aim of SCIM is achieving interoperability, security, and scalability in the context of identity management. For your reference, the current version of the standard is governed by the following documents: RFC 7642 , RFC 7643 , and RFC 7644 .", "title": "SCIM User Management"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#installation", "text": "The API is available as a component of Jans Server. Upon installation you can select if you want SCIM included in your environment. To add SCIM post-install do the following: Run python3 /opt/jans/jans-setup/setup.py --install-scim", "title": "Installation"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#about-api-endpoints", "text": "Throughout this document, you will notice endpoints are prefixed with path: /jans-scim/restv1/v2", "title": "About API endpoints"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#api-protection", "text": "Clearly, this API must not be anonymously accessed. However, the basic SCIM standard does not define a specific mechanism to prevent unauthorized requests to endpoints. There are just a few guidelines in section 2 of RFC 7644 concerned with authentication and authorization. OAUTH, This is the default and recommended mechanism BYPASS Depending on the scopes associated to a token, you will be granted (or denied) access to perform certain operations. The following lists the available scopes: Scope Actions allowed https://jans.io/scim/users.read Query user resources https://jans.io/scim/users.write Modify user resources https://jans.io/scim/groups.read Query group resources https://jans.io/scim/groups.write Modify group resources https://jans.io/scim/fido.read Query fido resources https://jans.io/scim/fido.write Modify fido resources https://jans.io/scim/fido2.read Query fido 2 resources https://jans.io/scim/fido2.write Modify fido 2 resources https://jans.io/scim/all-resources.search Access the root .search endpoint https://jans.io/scim/bulk Send requests to the bulk endpoint In order to facilitate the process of getting an access token, your Janssen installation already bundles an OAuth client named \"SCIM client\" with support for all the scopes above. This client uses the client_credentials grant type and client_secret_basic mechanism to authenticate to the token endpoint.", "title": "API Protection"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#where-to-locate-scim-related-logs", "text": "Please see here besides SCIM log is located at /opt/jans/jetty/jans-scim/logs/scim.log If you use SCIM custom script aslo see /opt/jans/jetty/jans-scim/logs/scim_script.log", "title": "Where to locate SCIM-related logs"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#api-documentation-at-a-glance", "text": "SCIM API doc page describes about our implementation of SCIM. The API has also been documented using OpenAPI (swagger) specification for the interested. Find yaml files here .", "title": "API documentation at a glance"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#working-in-oauth-mode", "text": "To know more about OAuth protection mode please visit here . The SCIM API endpoints are by default protected by (Bearer) OAuth 2.0 tokens. Depending on the operation, these tokens must have certain scopes for the operations to be authorized. We need a client to get Bearer token.", "title": "Working in OAuth mode"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#get-scim-client", "text": "Let's obtain the credentials of this client first. In TUI, navigate to Auth Server > Clients . In the search field type SCIM (uppercase). Highlight the row that matches a client named \"SCIM Client\" and press Enter. To see in JSON formate please press d . From the \"Basic\" section, grab the \"client id\" and \"client secret\". This secret is encrypted, to decrypt it, in a terminal run /opt/jans/bin/encode.py -D ENCRYPTED-SECRET-HERE .", "title": "Get SCIM Client"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#get-access-token", "text": "Let's get a token, curl -k -u 'CLIENT_ID:DECRYPTED_CLIENT_SECRET' -k -d grant_type=client_credentials -d scope='https://jans.io/scim/users.read https://jans.io/scim/users write' https://<jans-server>/jans-auth/restv1/token > /tmp/token.json In response token.json we will get access_token { \"access_token\":\"11a76589-7955-4247-9ca5-f3ad7884305...\", \"scope\":\"https://jans.io/scim/users.read\", \"token_type\":\"Bearer\", \"expires_in\":299 }", "title": "Get Access token"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#retrive-existing-user", "text": "To get an existing user curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=displayName co \"Admin\"' https://<jans-server>/jans-scim/restv1/v2/Users > /tmp/user.json In response user.json we will get { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"totalResults\": 1, \"startIndex\": 1, \"itemsPerPage\": 1, \"Resources\": [ { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"5fdbb720-a1fd-477f-af92-b7c054f02c98\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-12T14:54:09.531Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/5fdbb720-a1fd-477f-af92-b7c054f02c98\" }, \"userName\": \"admin\", \"name\": { \"familyName\": \"...\", \"givenName\": \"...\", \"middleName\": \"...\", \"formatted\": \"...\" }, \"displayName\": \"Admin\", \"active\": true, \"emails\": [ { \"value\": \"example@gluu.org\", \"primary\": false } ], \"groups\": [ { \"value\": \"60B7\", \"display\": \"Jannsen Manager Group\", \"type\": \"direct\", \"$ref\": \"https://raju.jans13.me/jans-scim/restv1/v2/Groups/60B7\" } ] } ] }", "title": "Retrive existing User"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#creating-resource", "text": "", "title": "Creating Resource"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#create-an-user", "text": "Let's start creating a dummy user. A client sends a POST request containing a \"User\" to the \"/Users\" endpoint. POST /Users HTTP/1.1 Host: example.com Accept: application/scim+json Content-Type: application/scim+json Authorization: Bearer h480djs93hd8.. Content-Length: ... { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" } } Open a text editor and copy paste the json body, name as input.json . Hit on your terminal with bellow command. curl -k -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users response looks like { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T19:43:32.945Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Barbara\", \"formatted\": \"Ms. Barbara J Jensen III\" } } This new user has been given an id . If possible, inspect your ou=people branch and find the entry whose inum matches the id given. An easier option would be to via Jans TUI and go to Users and search \"bjensen\" to see the recently created user.", "title": "Create an User"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#updating-a-userput", "text": "Overwrite your input.json with the following. Replace content in angle brackets accordingly: { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"userName\": \"bjensen\", \"externalId\": \"bjensen\", \"name\": { \"formatted\": \"Ms. Barbara J Jensen III\", \"familyName\": \"Jensen\", \"givenName\": \"Barbara\" }, \"displayName\": \"Jensen Barbara\", \"emails\": [ { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": true } ] } PUT with curl: curl -k -X PUT -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Response (output.json) will show the same contents of a full retrieval. Please verify changes were applied whether by inspecting LDAP or issuing a GET. If you have followed the steps properly, you should notice a new e-mail added and the change in displayName attribute", "title": "Updating a User(PUT)"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#updating-a-user-patch", "text": "With patching, you can be very precise about the modifications you want to apply. Patching syntax follows JSON Patch spec (RFC 6902) closely. While it's not a must to read the RFC to learn how patch works, see section 3.5.2 of SCIM protocol (RFC 7644) to get the grasp. If you prefer reading code, patch test cases found in the Java scim-client project are worth to look at. The following is a simple example that illustrates the kind of modifications developers can achieve via PATCH . Overwrite your input.json with the following: { \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:PatchOp\" ], \"Operations\": [ { \"op\": \"replace\", \"value\": { \"name\": { \"givenName\": \"Joey\" } } }, { \"op\": \"replace\", \"path\": \"emails[type eq \\\"work\\\" or primary eq false].value\", \"value\": \"jensen@example.com\" }, { \"op\": \"add\", \"value\": { \"name\": { \"middleName\": \"Jhon\" } } }, { \"op\": \"add\", \"value\": { \"emails\": [ { \"primary\": true, \"value\": \"my@own.mail\" } ], \"phoneNumbers\": [ { \"type\": \"home\", \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } }, { \"op\": \"remove\", \"path\": \"name.middleName\" }, { \"op\": \"remove\", \"path\": \"phoneNumbers[value ew \\\"01\\\"].type\" } ] } A collection of modification are provided under \"Operations\". They are processed in order of appearance. Also, every operation has a type; patching supports add, remove and replace. The first operations states the following: replace the value of givenName subattribute (that belongs to complex attribute name ) with the string \"Joey\". Operations are easier to understand when using a \"path\". The second operation replaces the value subattribute inside the complex multi-valued attribute emails. Inside the square brackets, we find a filter expression, so the replacement does not apply to all emails in the list but only to those matching the criterion. So the second operation can be read as \"set the value of value subattribute to string jensen@example.com where the type subattribute of the email equals to string \"work\" or if primary attribute is false\". The third operation is similar to the first. It sets the value of a subattribute which was unassigned (null). You could have used \"replace\" operation in this case and results would have been identical. The fourth operation is more interesting. It adds to the current list of emails a new one. It supplies a couple of subattributes for the email to include: primary and value. Additionally, we set the value of (previously unassigned) phoneNumbers multi-valued attribute passing a list of elements. In the fifth operation, we remove the middleName attribute that was set in operation three. Note how we make explicit the path of data to nullify: \"name.middleName\". The sixth operation allows us to remove a specific subattribute of phoneNumbers . The aim is to nullify the \"type\" of the item whose phone number value ends with \"01\". The remove operation can also be used to remove a complete item from a list, or empty the whole list by providing a suitable value for \"path\". Now let's see it in action: curl -k -X PATCH -H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/scim+json' -d @input.json -o output.json https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> So far our resource look like this { \"schemas\": [ \"urn:ietf:params:scim:schemas:core:2.0:User\" ], \"id\": \"e3009115-b890-4d8b-bd63-bbfef34aa583\", \"externalId\": \"bjensen\", \"meta\": { \"resourceType\": \"User\", \"created\": \"2023-06-26T19:43:32.945Z\", \"lastModified\": \"2023-06-26T22:34:27.465Z\", \"location\": \"https://raju.jans13.me/jans-scim/restv1/v2/Users/e3009115-b890-4d8b-bd63-bbfef34aa583\" }, \"userName\": \"bjensen\", \"name\": { \"familyName\": \"Jensen\", \"givenName\": \"Joey\", \"formatted\": \"Ms. Barbara J Jensen III\" }, \"displayName\": \"Jensen Barbara\", \"active\": false, \"emails\": [ { \"value\": \"my@own.mail\", \"primary\": true }, { \"value\": \"jensen@example.com\", \"type\": \"work\", \"primary\": false } ], \"phoneNumbers\": [ { \"value\": \"5 123 8901\" }, { \"value\": \"5 123 8902\" } ] } Note the primary subattribute accompanying email \"my@own.mail\" is false but when inserted we provided true . This is because the SCIM specification states that after modifications are applied to resources (PUT or PATCH) , there cannot be more than one item in a multi-valued attribute with primary value set as true . To see more sample JSON payloads, check the .json files used by the scim-client test cases referenced above.", "title": "Updating a User (PATCH)"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#deleting-users", "text": "For deleting, the DELETE method of HTTP is used. No input file is used in this case. A delete request could be the following: curl -k -X DELETE -H 'Authorization: Bearer ACCESS_TOKEN' https://<jans-server>/jans-scim/restv1/v2/Users/<user-inum> Use the inum of our dummy user, Jensen Barbara . Check your LDAP or via Jans TUI to see that Bjensen is gone.", "title": "Deleting Users"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#how-is-scim-data-stored", "text": "SCIM schema spec does not use LDAP attribute names but a different naming convention for resource attributes (note this is not the case of custom attributes where the SCIM name used is that of the LDAP attribute). It is possible to determine if a given LDAP attribute is being mapped to a SCIM attribute. For that you need to check in Jans TUI Auth-Server >> Attributes and click on any attributes. Check Include in SCIM Extension: is true or false . Whenever you try to map any LDAP attribute to a SCIM attribute keep it's value true .", "title": "How is SCIM data stored?"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#fido-devices", "text": "A FIDO device represents a user credential stored in the Jans Server database that is compliant with the FIDO standard. These devices are used as a second factor in a setting of strong authentication. FIDO devices were superseded by FIDO 2 devices in Jans Server.", "title": "FIDO Devices"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#fido-2-devices", "text": "FIDO 2 devices are credentials that adhere to the more current Fido 2.0 initiative (WebAuthn + CTAP). Examples of FIDO 2 devices are USB security keys and Super Gluu devices. The SCIM endpoints for FIDO 2 allow application developers to query, update and delete already existing devices. Addition of devices do not take place through the service since this process requires direct end-user interaction, ie. device enrolling. The schema attributes for a device of this kind can be found by hitting the URL https://<jans-server>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:Fido2Device To distinguish between regular FIDO2 and SuperGluu devices, note only SuperGluu entries have the attribute deviceData populated (i.e. not null)", "title": "FIDO 2 devices"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#example-querying-enrolled-devices", "text": "Say we are interested in having a list of Super Gluu devices users have enrolled and whose operating system is iOS. We may issue a query like this: curl -k -G -H 'Authorization: Bearer ACCESS_TOKEN' --data-urlencode 'filter=deviceData co \"ios\"' -d count=10 https://<jans-server>/jans-scim/restv1/v2/Fido2Devices The response will be like: { \"totalResults\": ..., \"itemsPerPage\": ..., \"startIndex\": 1, \"schemas\": [ \"urn:ietf:params:scim:api:messages:2.0:ListResponse\" ], \"Resources\": [ { \"id\": \"...\", \"meta\": {...}, \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:Fido2Device\"], \"userId\": \"...\", ... \"deviceData\": \"{...}\", \"displayName\": ..., }, ... ] }", "title": "Example: Querying Enrolled Devices"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#potential-performance-issues-with-group-endpoints", "text": "In SCIM a group resource basically consists of an identifier, a display name, and a collection of members associated to it. Also, every member is made up of a user identifier, his display name, and other attributes. As a consequence, retrieving group information requires making a correlation with existing user data. Since Gluu database model does not follow a relational database pattern this may entail a considerable amount of user queries when groups contain thousands of members. While this could have been workarounded by storing members' display names inside group entries, this brings additional problems to deal with. Another source of potential overhead stems from creation and modification of groups where many new users are associated to a given group: by default checks are made to guarantee only existing users are attached to groups, thus requiring continuous database queries. Currently there are two ways to lower the amount of database lookups required for SCIM group operations: Explicitly excluding display names from responses Pass the overhead bypass flag to skip members validations The first approach consists of using the query parameter excludedAttributes (see RFC 7644 ) so that display names are neither retrieved from database nor sent in responses. A value like members.display does the job. Note the query parameter attributes can also be used for this purpose, for example with a value like members.value that will output only members' identifiers and ignore other non-required attributes. This approach is particularly useful in search and retrievals when users' display names are not needed. The second is a stronger approach that turns off validation of incoming members data: if the usage of a POST/PUT/PATCH operation implies adding members, their existence is not verified, they will simply get added. Here, the client application is responsible for sending accurate data. To use this approach add a query or header parameter named Group-Overhead-Bypass with any value. Note under this mode of operation: Display names are never returned regardless of attributes or excludedAttributes parameters values Remove/replace patch operations that involve display names in path filters are ignored, eg: \"path\": \"members[value eq \\\"2819c223\\\" or display eq \\\"Joe\\\"]\"", "title": "Potential performance issues with Group endpoints"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#user-registration-process-with-scim", "text": "SCIM service has many use cases. One interesting and often arising is that of coding your own user registration process. With your SCIM endpoints you can build a custom application to maintain user entries in your database.", "title": "User Registration Process with SCIM"}, {"location": "janssen-server/usermgmt/usermgmt-scim/#important-considerations", "text": "Here, you have some useful tips before you start: Choose a toolset you feel comfortable to work with. Keep in mind that you have to leverage the capabilities of your language/framework to issue complex HTTPS requests. Be sure that: You will be able to use at least the following verbs: GET, POST, PUT, and DELETE You can send headers in your requests as well as reading them from the service response If not supported natively, choose a library to facilitate JSON content manipulation. As you have already noticed we have been dealing with JSON for requests as well as for responses. Experience shows that being able to map from objects (or data structures) of your language to Json and viceversa helps saving hours of coding. Shape your data model early. List the attributes your application will operate upon and correlate with those found in the SCIM user schema. You can learn about the schema in RFC 7644 . At least, take a look at the JSON-formatted schema that your Jans Server shows: visit https://<host-name>/jans-scim/restv1/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:User You will have to manipulate database contents very often as you develop and run tests, thus, find a suitable tool for the task. In the case of LDAP, a TUI client is a good choice. Always check your logs . In this user management guide with SCIM, we have already touched upon the fundamentals of SCIM in Jans Server and shown a good amount of sample requests for manipulation of user information. However, keep in mind the SCIM spec documents are definitely the key reference to build working request messages, specially RFC 7643 , and RFC 7644 .", "title": "Important Considerations"}, {"location": "janssen-server/vm-ops/backup/", "tags": ["administration", "vm", "operations", "backup"], "text": "Janssen VM Backup # Best method of Janssen Backup is \"VM Snapshot\" backup. That means, backup / take snapshot of whole virtual machine / droplet / instance which is hosting your Gluu Janssen software. In the event of a production outage, a proper snapshot of the last working condition will help rapidly restore service. Most platform virtualization software and cloud vendors have snapshot backup features. For instance, Digital Ocean has Live Snapshot and Droplet Snapshot; VMWare has Snapshot Manager, etc. The Gluu Server should be backed up frequently-- we recommend at least one daily and one weekly backup of Gluu's data and/or VM . It's also good to have some partial configuration backup as well. Such as: Tarball /opt Tarball /etc/jans Tarball /etc/apache2 Tarball /var/jans Tarball Method # All Jans Server files live in a single folder: /opt. The entire Jans Server folder can be archived using the tar command: Stop the server: systemctl stop list-units --all \"jans*\" Use tar to take a backup: tar cvf jans-backup.tar /opt/jans/ Start the server again: systemctl start list-units --all \"jans*\"", "title": "Backup"}, {"location": "janssen-server/vm-ops/backup/#janssen-vm-backup", "text": "Best method of Janssen Backup is \"VM Snapshot\" backup. That means, backup / take snapshot of whole virtual machine / droplet / instance which is hosting your Gluu Janssen software. In the event of a production outage, a proper snapshot of the last working condition will help rapidly restore service. Most platform virtualization software and cloud vendors have snapshot backup features. For instance, Digital Ocean has Live Snapshot and Droplet Snapshot; VMWare has Snapshot Manager, etc. The Gluu Server should be backed up frequently-- we recommend at least one daily and one weekly backup of Gluu's data and/or VM . It's also good to have some partial configuration backup as well. Such as: Tarball /opt Tarball /etc/jans Tarball /etc/apache2 Tarball /var/jans", "title": "Janssen VM Backup"}, {"location": "janssen-server/vm-ops/backup/#tarball-method", "text": "All Jans Server files live in a single folder: /opt. The entire Jans Server folder can be archived using the tar command: Stop the server: systemctl stop list-units --all \"jans*\" Use tar to take a backup: tar cvf jans-backup.tar /opt/jans/ Start the server again: systemctl start list-units --all \"jans*\"", "title": "Tarball Method"}, {"location": "janssen-server/vm-ops/certificates/", "tags": ["administration", "vm", "operations", "certificates"], "text": "Janssen Certificates # Janssen components have cryptographic keys and X.509 certificates that are stored on the filesystem at the time of installation. Details for certificates associated with each component are provided below. The following certificates are available in the /etc/certs folder. APACHE Jans Auth CA Certificates httpd.crt jans-auth-keys.p12 https.csr httpd.key httpd.key.orig Custom Script JSON Files # Additionally the following json files are available which are used in different custom scripts for multi-factor authentication. cert_creds.json duo_creds.json gplus_client_secrets.json otp_configuration.json super_gluu_creds.json vericloud_jans_creds.json Updating certificates # On a fresh VM installation, Janssen generates self signed certificates. You will want to change these to real certificates. For this documentation we will use certbot using Let's Encrypt certificates. Certbot recommends using snap to install certbot and obtain certificates. The following instructions are for Ubuntu 20; however, any platform supporting snap should work. Backup the /etc/certs folder on your server Install snap sudo snap install core ; sudo snap refresh core Remove any certbot OS packages. This varies across distributions. For Ubuntu: sudo apt remove certbot Install certbot: sudo snap install --classic certbot Issue certificate: certbot --apache -d fqdn_of_Gluu_server Full certificate chain and key are available in: /etc/letsencrypt/live/ location. Reboot your server Installing intermediate certificates # Please follow these steps to install intermediate certificates: Place your intermediate certificate file in /etc/certs Modify /etc/apache2/sites-available/https_jans.conf and add SSLCertificateChainFile /etc/certs/name_of_your_interm_root_cert.crt under the line containing SSLCertificateKeyFile Restart the httpd/apache2 service", "title": "Certificates"}, {"location": "janssen-server/vm-ops/certificates/#janssen-certificates", "text": "Janssen components have cryptographic keys and X.509 certificates that are stored on the filesystem at the time of installation. Details for certificates associated with each component are provided below. The following certificates are available in the /etc/certs folder. APACHE Jans Auth CA Certificates httpd.crt jans-auth-keys.p12 https.csr httpd.key httpd.key.orig", "title": "Janssen Certificates"}, {"location": "janssen-server/vm-ops/certificates/#custom-script-json-files", "text": "Additionally the following json files are available which are used in different custom scripts for multi-factor authentication. cert_creds.json duo_creds.json gplus_client_secrets.json otp_configuration.json super_gluu_creds.json vericloud_jans_creds.json", "title": "Custom Script JSON Files"}, {"location": "janssen-server/vm-ops/certificates/#updating-certificates", "text": "On a fresh VM installation, Janssen generates self signed certificates. You will want to change these to real certificates. For this documentation we will use certbot using Let's Encrypt certificates. Certbot recommends using snap to install certbot and obtain certificates. The following instructions are for Ubuntu 20; however, any platform supporting snap should work. Backup the /etc/certs folder on your server Install snap sudo snap install core ; sudo snap refresh core Remove any certbot OS packages. This varies across distributions. For Ubuntu: sudo apt remove certbot Install certbot: sudo snap install --classic certbot Issue certificate: certbot --apache -d fqdn_of_Gluu_server Full certificate chain and key are available in: /etc/letsencrypt/live/ location. Reboot your server", "title": "Updating certificates"}, {"location": "janssen-server/vm-ops/certificates/#installing-intermediate-certificates", "text": "Please follow these steps to install intermediate certificates: Place your intermediate certificate file in /etc/certs Modify /etc/apache2/sites-available/https_jans.conf and add SSLCertificateChainFile /etc/certs/name_of_your_interm_root_cert.crt under the line containing SSLCertificateKeyFile Restart the httpd/apache2 service", "title": "Installing intermediate certificates"}, {"location": "janssen-server/vm-ops/checking-service-status/", "tags": ["administration", "vm", "operations", "services", "status"], "text": "Janssen System Services # In order to debug issues, checking the Jans services may be necessary. The process to do this differs slightly between operating systems. The following examples are shown on Ubuntu 20.04; however, they should work on any operating system using systemd. Getting list of Jans services # $ sudo systemctl list-units --all \"jans*\" UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed. Other Services # There are more services other than Jans services like Apache. To get the status of those services make sure you use command like sudo systemctl list-units --all \"apache2*\" Note: depending on your OS and the components of Jans installed, the output may be different. Checking status of a service # $ sudo systemctl status jans-auth.service \u25cf jans-auth.service - Janssen OAauth service Loaded: loaded ( /etc/systemd/system/jans-auth.service ; enabled ; vendor preset: enabled ) Active: active ( running ) since Tue 2022 -11-01 15 :03:23 UTC ; 1h 38min ago Process: 44700 ExecStart = /opt/dist/scripts/jans-auth start ( code = exited, status = 0 /SUCCESS ) Main PID: 44727 ( java ) Tasks: 60 ( limit: 4677 ) Memory: 889 .2M CGroup: /system.slice/jans-auth.service \u2514\u250044727 /opt/jre/bin/java -server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base = /etc/jans -Dserver.base = /opt/jans/jetty/jan> In case of an error or a non-functional component, this is where you would find information about the component.", "title": "Checking Service Status"}, {"location": "janssen-server/vm-ops/checking-service-status/#janssen-system-services", "text": "In order to debug issues, checking the Jans services may be necessary. The process to do this differs slightly between operating systems. The following examples are shown on Ubuntu 20.04; however, they should work on any operating system using systemd.", "title": "Janssen System Services"}, {"location": "janssen-server/vm-ops/checking-service-status/#getting-list-of-jans-services", "text": "$ sudo systemctl list-units --all \"jans*\" UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed.", "title": "Getting list of Jans services"}, {"location": "janssen-server/vm-ops/checking-service-status/#other-services", "text": "There are more services other than Jans services like Apache. To get the status of those services make sure you use command like sudo systemctl list-units --all \"apache2*\" Note: depending on your OS and the components of Jans installed, the output may be different.", "title": "Other Services"}, {"location": "janssen-server/vm-ops/checking-service-status/#checking-status-of-a-service", "text": "$ sudo systemctl status jans-auth.service \u25cf jans-auth.service - Janssen OAauth service Loaded: loaded ( /etc/systemd/system/jans-auth.service ; enabled ; vendor preset: enabled ) Active: active ( running ) since Tue 2022 -11-01 15 :03:23 UTC ; 1h 38min ago Process: 44700 ExecStart = /opt/dist/scripts/jans-auth start ( code = exited, status = 0 /SUCCESS ) Main PID: 44727 ( java ) Tasks: 60 ( limit: 4677 ) Memory: 889 .2M CGroup: /system.slice/jans-auth.service \u2514\u250044727 /opt/jre/bin/java -server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base = /etc/jans -Dserver.base = /opt/jans/jetty/jan> In case of an error or a non-functional component, this is where you would find information about the component.", "title": "Checking status of a service"}, {"location": "janssen-server/vm-ops/logs/", "tags": ["administration", "vm", "operations", "log-levels"], "text": "Janssen Log Configuration # The Janssen logs can be viewed via SSH access to the server running the Janssen installation. Log Levels # The following log levels can be configured through the configuration CLI: Log Level Messages Logged Trace All messages Debug Debug level and above Info Informational level and above Warn Warning level and above Error Error level and above Fatal Only fatal errors Off Logging is disabled Configuring Log Levels # Use the following commands to get information on the logging module configuration: To get the logging configuration operation ID: jans cli --info ConfigurationLogging Output would be: # Log configuration operations Operation ID: get-config-logging Description: Returns Jans Authorization Server logging settings. Operation ID: put-config-logging Description: Updates Jans Authorization Server logging settings. Schema: /components/schemas/LoggingConfiguration To get sample schema type jans cli --schema <schma> , for example jans cli --schema /components/schemas/LoggingConfiguration Output: # Generic configuration schema { \"loggingLevel\": \"TRACE\", \"loggingLayout\": \"json\", \"httpLoggingEnabled\": true, \"disableJdkLogger\": false, \"enabledOAuthAuditLogging\": true, \"externalLoggerConfiguration\": null, \"httpLoggingExcludePaths\": [ \"/auth/img\", \"/auth/stylesheet\" ] } Status of current configuration logging: jans cli --operation-id get-config-logging Output: # Current log configuration { \"loggingLevel\": \"INFO\", \"loggingLayout\": \"text\", \"httpLoggingEnabled\": false, \"disableJdkLogger\": true, \"enabledOAuthAuditLogging\": false, \"externalLoggerConfiguration\": null, \"httpLoggingExcludePaths\": null } Let's assume we want to update logging configuration to TRACE . To do this, create a file /tmp/log.json with the following content: { \"loggingLevel\" : \"TRACE\" , \"loggingLayout\" : \"text\" , \"httpLoggingEnabled\" : false , \"disableJdkLogger\" : true , \"enabledOAuthAuditLogging\" : false , \"externalLoggerConfiguration\" : null , \"httpLoggingExcludePaths\" : null } And use the PUT operation with this file as the payload: jans cli --operation-id put-config-logging --data /tmp/log.json The server will now have logs set to TRACE. Setup Logs # The Jans setup logs are available under /opt/jans/jans-setup/logs/ . There are several log files available involving the setup process: mysql.log (Only used if MySQL backend is chosen during setup) os-changes.log setup.log setup_error.log Core Logs # The available logs for Jans server are listed below: Config API logs # /opt/jans/jetty/jans-config-api/logs/ Log File Description configapi.log Config API main log configapi_persistence.log Config API persistence log configapi_persistence_duration.log Config API persistence operation duration log [date].jetty.log Config API Jetty log configapi_script.log Config API custom script log Jans Auth server logs # /opt/jans/jetty/jans-auth/logs/ The most important log files here are described below: jans-auth.log : This log file contains most authentication related information. Generally this is the first log to review for any authentication-related troubleshooting, like authentication failure or missing clients etc. jans-auth_persistence.log : This log file contains information about the Jans Auth server communicating with the persistence backend. jans-auth_script.log : This log file contains debug messages printed from interception scripts . Server Logs # In some cases, it may be necessary to examine the server logs themselves. OS Logs # For Debian based systems: /var/log/syslog For RPM based systems: /var/log/messages Apache2 Server Logs # For Debian based systems: /var/log/apache2/ For RPM based systems: /var/log/httpd/ Apache2 logs are as follows: access_log : This log contains information about requests coming into the Jans Server, success status or requests, execution time for any request etc. error_log : This log shows error messages if the web server encounter any issue while processing incoming requests. other_vhosts_access.log : This log is specific to the Jans Server setup and those links which are being requested by a user from a web browser.", "title": "Logs"}, {"location": "janssen-server/vm-ops/logs/#janssen-log-configuration", "text": "The Janssen logs can be viewed via SSH access to the server running the Janssen installation.", "title": "Janssen Log Configuration"}, {"location": "janssen-server/vm-ops/logs/#log-levels", "text": "The following log levels can be configured through the configuration CLI: Log Level Messages Logged Trace All messages Debug Debug level and above Info Informational level and above Warn Warning level and above Error Error level and above Fatal Only fatal errors Off Logging is disabled", "title": "Log Levels"}, {"location": "janssen-server/vm-ops/logs/#configuring-log-levels", "text": "Use the following commands to get information on the logging module configuration: To get the logging configuration operation ID: jans cli --info ConfigurationLogging Output would be: # Log configuration operations Operation ID: get-config-logging Description: Returns Jans Authorization Server logging settings. Operation ID: put-config-logging Description: Updates Jans Authorization Server logging settings. Schema: /components/schemas/LoggingConfiguration To get sample schema type jans cli --schema <schma> , for example jans cli --schema /components/schemas/LoggingConfiguration Output: # Generic configuration schema { \"loggingLevel\": \"TRACE\", \"loggingLayout\": \"json\", \"httpLoggingEnabled\": true, \"disableJdkLogger\": false, \"enabledOAuthAuditLogging\": true, \"externalLoggerConfiguration\": null, \"httpLoggingExcludePaths\": [ \"/auth/img\", \"/auth/stylesheet\" ] } Status of current configuration logging: jans cli --operation-id get-config-logging Output: # Current log configuration { \"loggingLevel\": \"INFO\", \"loggingLayout\": \"text\", \"httpLoggingEnabled\": false, \"disableJdkLogger\": true, \"enabledOAuthAuditLogging\": false, \"externalLoggerConfiguration\": null, \"httpLoggingExcludePaths\": null } Let's assume we want to update logging configuration to TRACE . To do this, create a file /tmp/log.json with the following content: { \"loggingLevel\" : \"TRACE\" , \"loggingLayout\" : \"text\" , \"httpLoggingEnabled\" : false , \"disableJdkLogger\" : true , \"enabledOAuthAuditLogging\" : false , \"externalLoggerConfiguration\" : null , \"httpLoggingExcludePaths\" : null } And use the PUT operation with this file as the payload: jans cli --operation-id put-config-logging --data /tmp/log.json The server will now have logs set to TRACE.", "title": "Configuring Log Levels"}, {"location": "janssen-server/vm-ops/logs/#setup-logs", "text": "The Jans setup logs are available under /opt/jans/jans-setup/logs/ . There are several log files available involving the setup process: mysql.log (Only used if MySQL backend is chosen during setup) os-changes.log setup.log setup_error.log", "title": "Setup Logs"}, {"location": "janssen-server/vm-ops/logs/#core-logs", "text": "The available logs for Jans server are listed below:", "title": "Core Logs"}, {"location": "janssen-server/vm-ops/logs/#config-api-logs", "text": "/opt/jans/jetty/jans-config-api/logs/ Log File Description configapi.log Config API main log configapi_persistence.log Config API persistence log configapi_persistence_duration.log Config API persistence operation duration log [date].jetty.log Config API Jetty log configapi_script.log Config API custom script log", "title": "Config API logs"}, {"location": "janssen-server/vm-ops/logs/#jans-auth-server-logs", "text": "/opt/jans/jetty/jans-auth/logs/ The most important log files here are described below: jans-auth.log : This log file contains most authentication related information. Generally this is the first log to review for any authentication-related troubleshooting, like authentication failure or missing clients etc. jans-auth_persistence.log : This log file contains information about the Jans Auth server communicating with the persistence backend. jans-auth_script.log : This log file contains debug messages printed from interception scripts .", "title": "Jans Auth server logs"}, {"location": "janssen-server/vm-ops/logs/#server-logs", "text": "In some cases, it may be necessary to examine the server logs themselves.", "title": "Server Logs"}, {"location": "janssen-server/vm-ops/logs/#os-logs", "text": "For Debian based systems: /var/log/syslog For RPM based systems: /var/log/messages", "title": "OS Logs"}, {"location": "janssen-server/vm-ops/logs/#apache2-server-logs", "text": "For Debian based systems: /var/log/apache2/ For RPM based systems: /var/log/httpd/ Apache2 logs are as follows: access_log : This log contains information about requests coming into the Jans Server, success status or requests, execution time for any request etc. error_log : This log shows error messages if the web server encounter any issue while processing incoming requests. other_vhosts_access.log : This log is specific to the Jans Server setup and those links which are being requested by a user from a web browser.", "title": "Apache2 Server Logs"}, {"location": "janssen-server/vm-ops/managing-key-rotation/", "tags": ["administration", "vm", "operations"], "text": "Managing Key Rotation # \"Key-rotation\" is a standard procedure for all OpenID Connect deployment. \"Key-rotation\" means replacing existing signing key with newer cryptographic key. For Janssen server, that specific cryptographic key is jans-auth-keys.pkcs12 . There are two possible ways to manage key rotation: - built-in key rotation - external key rotation For VM by default built-in key rotation is on. Key alias or kid has following format (example connect_76297462-a3f8-498e-afc2-670285292553_sig_rs256 ): <operation_type>_<guid>_<use>_<algorithm> operation_type - specifies operation type of the key, possible values: connect - used for OpenID Connect - usually expirable key ssa - used for SSA - usually with very big expiration date (almost non-expirable) all - key can be use for both connect and ssa guid - unique identifier use - use purpose, possible values are sig for signature and enc for encryption algorithm - algorithm use with given key in signature case it can be RS256 , RS384 , RS512 , ES256 , ES384 , ES512 , PS256 , PS384 , PS512 in encryption case case it can be RSA1_5 , RSA-OAEP Key rotation means that new keys are generated and old one are removed for given algorithm (full replacement). Keys are stored in: - key store file (specified by keyStoreFile ) - on persistence level jwks representation of the key are stored in jansConfWebKeys attribute of jansAppConf entity It's important to note that key inside key store file must have representation in jwks and vice versa. It must be always in sync otherwise AS will throw error. Configuration properties related to key store file: - keyStoreFile - The Key Store File (JKS or PKCS12) - keyStoreSecret - The Key Store password Built-in key rotation # jans-auth-server has KeyGeneratorTimer which is responsible for key rotation. Built-in rotation can be switch on/off via keyRegenerationEnabled AS configuration property (by setting true or false value). graph LR A[Auth Server] --> V(Properties) erDiagram keyRotation { string keyRegenerationEnabled \"True\" string keyRenerationInterval \"48\" string keySelectionStrategy \"OLDER\" string keySignWithSameKeyButDiffAlg \"False\" string keyStoreFile \"/etc/certs/jans-auth-keys.pkcs12\" } Configuration properties relation to built-in rotation: - keyRegenerationEnabled - boolean value specifying whether to turn on ( true value) or off ( false value) built-in key rotation - keyRegenerationInterval - the interval for key regeneration in hours - keyAlgsAllowedForGeneration - List of algorithm allowed to be used for key generation Expiration date during built-in rotation is set as now + keyRegenerationInterval . External key rotation # External rotation means that keys are rotated by script. In this case keyRegenerationEnabled must be set to false value. Script can be scheduled to run periodically. Such script must invoke KeyGenerator class from jans-auth-client-jar-with-dependencies.jar which will keep keys in key store and in AS persistence consistent. See Key Generation page for more details how to generate keys externally. /opt/jre/bin/java -Dlog4j.defaultInitOverride=true -cp /opt/dist/jans/jans-auth-client-jar-with-dependencies.jar io.jans.as.client.util.KeyGenerator -keystore /etc/certs/jans-auth-keys.p12 -keypasswd <Password> -sig_keys RS256 RS384 -enc_keys RSA1_5 RSA-OAEP -key_ops_type ALL -dnname \"CN=jansAuth CA Certificates\" -expiration 2 > /etc/certs/jans-auth-keys.json Useful references # Key Generation", "title": "Managing Key Rotation"}, {"location": "janssen-server/vm-ops/managing-key-rotation/#managing-key-rotation", "text": "\"Key-rotation\" is a standard procedure for all OpenID Connect deployment. \"Key-rotation\" means replacing existing signing key with newer cryptographic key. For Janssen server, that specific cryptographic key is jans-auth-keys.pkcs12 . There are two possible ways to manage key rotation: - built-in key rotation - external key rotation For VM by default built-in key rotation is on. Key alias or kid has following format (example connect_76297462-a3f8-498e-afc2-670285292553_sig_rs256 ): <operation_type>_<guid>_<use>_<algorithm> operation_type - specifies operation type of the key, possible values: connect - used for OpenID Connect - usually expirable key ssa - used for SSA - usually with very big expiration date (almost non-expirable) all - key can be use for both connect and ssa guid - unique identifier use - use purpose, possible values are sig for signature and enc for encryption algorithm - algorithm use with given key in signature case it can be RS256 , RS384 , RS512 , ES256 , ES384 , ES512 , PS256 , PS384 , PS512 in encryption case case it can be RSA1_5 , RSA-OAEP Key rotation means that new keys are generated and old one are removed for given algorithm (full replacement). Keys are stored in: - key store file (specified by keyStoreFile ) - on persistence level jwks representation of the key are stored in jansConfWebKeys attribute of jansAppConf entity It's important to note that key inside key store file must have representation in jwks and vice versa. It must be always in sync otherwise AS will throw error. Configuration properties related to key store file: - keyStoreFile - The Key Store File (JKS or PKCS12) - keyStoreSecret - The Key Store password", "title": "Managing Key Rotation"}, {"location": "janssen-server/vm-ops/managing-key-rotation/#built-in-key-rotation", "text": "jans-auth-server has KeyGeneratorTimer which is responsible for key rotation. Built-in rotation can be switch on/off via keyRegenerationEnabled AS configuration property (by setting true or false value). graph LR A[Auth Server] --> V(Properties) erDiagram keyRotation { string keyRegenerationEnabled \"True\" string keyRenerationInterval \"48\" string keySelectionStrategy \"OLDER\" string keySignWithSameKeyButDiffAlg \"False\" string keyStoreFile \"/etc/certs/jans-auth-keys.pkcs12\" } Configuration properties relation to built-in rotation: - keyRegenerationEnabled - boolean value specifying whether to turn on ( true value) or off ( false value) built-in key rotation - keyRegenerationInterval - the interval for key regeneration in hours - keyAlgsAllowedForGeneration - List of algorithm allowed to be used for key generation Expiration date during built-in rotation is set as now + keyRegenerationInterval .", "title": "Built-in key rotation"}, {"location": "janssen-server/vm-ops/managing-key-rotation/#external-key-rotation", "text": "External rotation means that keys are rotated by script. In this case keyRegenerationEnabled must be set to false value. Script can be scheduled to run periodically. Such script must invoke KeyGenerator class from jans-auth-client-jar-with-dependencies.jar which will keep keys in key store and in AS persistence consistent. See Key Generation page for more details how to generate keys externally. /opt/jre/bin/java -Dlog4j.defaultInitOverride=true -cp /opt/dist/jans/jans-auth-client-jar-with-dependencies.jar io.jans.as.client.util.KeyGenerator -keystore /etc/certs/jans-auth-keys.p12 -keypasswd <Password> -sig_keys RS256 RS384 -enc_keys RSA1_5 RSA-OAEP -key_ops_type ALL -dnname \"CN=jansAuth CA Certificates\" -expiration 2 > /etc/certs/jans-auth-keys.json", "title": "External key rotation"}, {"location": "janssen-server/vm-ops/managing-key-rotation/#useful-references", "text": "Key Generation", "title": "Useful references"}, {"location": "janssen-server/vm-ops/restarting-services/", "tags": ["administration", "vm", "operations", "services", "lifecycle"], "text": "Janssen System Services Lifecycle Management # Getting list of Jans services # sudo systemctl list-units --all \"jans*\" Output should be like below: UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed. Other Services # There are more services other than Jans services like Apache. To get the status of those services make sure you use command like sudo systemctl list-units --all \"apache2*\" Commands (Ubuntu 20.04, RHEL 8, SUSE 15) # Start # systemctl start [service name] Stop # systemctl stop [service name] Status # systemctl status [service name] Restart # systemctl restart [service name] Reload # This command is used for the apache2 and httpd services. systemctl reload [service name]", "title": "Restarting Services"}, {"location": "janssen-server/vm-ops/restarting-services/#janssen-system-services-lifecycle-management", "text": "", "title": "Janssen System Services Lifecycle Management"}, {"location": "janssen-server/vm-ops/restarting-services/#getting-list-of-jans-services", "text": "sudo systemctl list-units --all \"jans*\" Output should be like below: UNIT LOAD ACTIVE SUB DESCRIPTION jans-auth.service loaded active running Janssen OAauth service jans-config-api.service loaded active running Janssen Config API service jans-fido2.service loaded active running Janssen Fido2 Service jans-scim.service loaded active running Janssen Scim service LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 5 loaded units listed.", "title": "Getting list of Jans services"}, {"location": "janssen-server/vm-ops/restarting-services/#other-services", "text": "There are more services other than Jans services like Apache. To get the status of those services make sure you use command like sudo systemctl list-units --all \"apache2*\"", "title": "Other Services"}, {"location": "janssen-server/vm-ops/restarting-services/#commands-ubuntu-2004-rhel-8-suse-15", "text": "", "title": "Commands (Ubuntu 20.04, RHEL 8, SUSE 15)"}, {"location": "janssen-server/vm-ops/restarting-services/#start", "text": "systemctl start [service name]", "title": "Start"}, {"location": "janssen-server/vm-ops/restarting-services/#stop", "text": "systemctl stop [service name]", "title": "Stop"}, {"location": "janssen-server/vm-ops/restarting-services/#status", "text": "systemctl status [service name]", "title": "Status"}, {"location": "janssen-server/vm-ops/restarting-services/#restart", "text": "systemctl restart [service name]", "title": "Restart"}, {"location": "janssen-server/vm-ops/restarting-services/#reload", "text": "This command is used for the apache2 and httpd services. systemctl reload [service name]", "title": "Reload"}, {"location": "janssen-server/vm-ops/upgrade/", "tags": ["administration", "VM", "operations", "upgrade"], "text": "This guide shows how to upgrade a Janssen VM deployment. Note VM deployments don't provide automatic upgrade/update support. Uninstalling and re-installing with newer binaries is the only option that requires re-configuration of auth-server. Though this is made easy using Terraform . We recommend using Kubernetes installations over VM, to avail smooth upgrades and better HA support. Let's assume we are upgrading Jans VM installation from current version to vreplace-janssen-version Keep the old VM installation running. Install on a separate VM the target new Jans installation, i.e. vreplace-janssen-version . You can install with a test client. For example: sudo python3 /opt/jans/jans-setup/setup.py -test-client-id 6382c9da-f25d-435f-ac63-6acde36f4859 -test-client-pw secret1172023 This client-id and client-pw will then be used to import Terraform configurations Use our Terraform docs on the new installation, i.e. vreplace-janssen-version to: import all the global configurations from the new installation using terraform import define all the custom IDP configurations and apply them using terraform apply At this point there should be two versions up, old version and vreplace-janssen-version . Traffic should be switched gradually from the old setup to the new setup. Once confidence is gained, drain the old VM.", "title": "Upgrade"}, {"location": "script-catalog/application_session/application-session/", "tags": ["administration", "developer", "script-catalog"], "text": "Application Session Script Guide # Overview # The Jans-Auth server allows you to modify the session flow through this script. Interface # The Application Session script implement the ApplicationSessionType interface. This extends methods form the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description def startSession(self, httpRequest, sessionId, configurationAttributes) Called when a session is started. def endSession(self, httpRequest, sessionId, configurationAttributes) Called when a session is ended. def onEvent(self, event) Called when a specific session event occurs.. def modifyActiveSessionsResponse(self, jsonArray, context) Called it during /session/active endpoint call to modify response if needed. All methods return true / false , the server issues an error if this response is false . If parameters is not present then error has to be created and false returned. If all is good script has to return true . Objects # Object name Object description customScript io.jans.model.custom.script.model.CustomScript context io.jans.as.server.service.external.context.ExternalScriptContext sessionId io.jans.as.common.model.session.SessionId event io.jans.as.server.service.external.session.SessionEvent httpRequest jakarta.servlet.http.HttpServletRequest jsonArray org.json.JSONArray configurationAttributes java.util.Map SimpleCustomProperty > Common Use Cases # startSession : Validate first session endSession : Print logs onEvent : If event type is AUTHENTICATED, print sessionId in logs modifyActiveSessionsResponse : Print logs Script type: Python # from io.jans.model.custom.script.type.session import ApplicationSessionType from io.jans.service.cdi.util import CdiUtil from io.jans.orm import PersistenceEntryManager from io.jans.as.model.config import StaticConfiguration from io.jans.as.server.model.ldap import TokenEntity from jakarta.faces.application import FacesMessage from io.jans.jsf2.message import FacesMessages from io.jans.util import StringHelper , ArrayHelper from io.jans.as.server.model.config import Constants from java.util import Arrays , ArrayList from io.jans.as.server.service.external.session import SessionEventType import java class ApplicationSession ( ApplicationSessionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Application session. Initialization\" self . entryManager = CdiUtil . bean ( PersistenceEntryManager ) self . staticConfiguration = CdiUtil . bean ( StaticConfiguration ) print \"Application session. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Application session. Destroy\" print \"Application session. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def onEvent ( self , event ): if event . getType () == SessionEventType . AUTHENTICATED : print \"Session is authenticated, session: \" + event . getSessionId () . getId () return def startSession ( self , httpRequest , sessionId , configurationAttributes ): print \"Application session. Starting external session\" user_name = sessionId . getSessionAttributes () . get ( Constants . AUTHENTICATED_USER ) first_session = self . isFirstSession ( user_name ) if not first_session : facesMessages = CdiUtil . bean ( FacesMessages ) facesMessages . add ( FacesMessage . SEVERITY_ERROR , \"Please, end active session first!\" ) return False print \"Application session. External session started successfully\" return True def endSession ( self , httpRequest , sessionId , configurationAttributes ): print \"Application session. Starting external session end\" print \"Application session. External session ended successfully\" return True def modifyActiveSessionsResponse ( self , jsonArray , context ): print \"Application session. Starting external modify active session\" print \"Application session. External modify active session successfully\" return False def isFirstSession ( self , user_name ): tokenLdap = TokenEntity () tokenLdap . setDn ( self . staticConfiguration . getBaseDn () . getClients ()) tokenLdap . setUserId ( user_name ) tokenLdapList = self . entryManager . findEntries ( tokenLdap , 1 ) print \"Application session. isFirstSession. Get result: ' %s '\" % tokenLdapList if ( tokenLdapList != None ) and ( tokenLdapList . size () > 0 ): print \"Application session. isFirstSession: False\" return False print \"Application session. isFirstSession: True\" return True", "title": "Application Session"}, {"location": "script-catalog/application_session/application-session/#application-session-script-guide", "text": "", "title": "Application Session Script Guide"}, {"location": "script-catalog/application_session/application-session/#overview", "text": "The Jans-Auth server allows you to modify the session flow through this script.", "title": "Overview"}, {"location": "script-catalog/application_session/application-session/#interface", "text": "The Application Session script implement the ApplicationSessionType interface. This extends methods form the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/application_session/application-session/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/application_session/application-session/#new-methods", "text": "Method header Method description def startSession(self, httpRequest, sessionId, configurationAttributes) Called when a session is started. def endSession(self, httpRequest, sessionId, configurationAttributes) Called when a session is ended. def onEvent(self, event) Called when a specific session event occurs.. def modifyActiveSessionsResponse(self, jsonArray, context) Called it during /session/active endpoint call to modify response if needed. All methods return true / false , the server issues an error if this response is false . If parameters is not present then error has to be created and false returned. If all is good script has to return true .", "title": "New methods"}, {"location": "script-catalog/application_session/application-session/#objects", "text": "Object name Object description customScript io.jans.model.custom.script.model.CustomScript context io.jans.as.server.service.external.context.ExternalScriptContext sessionId io.jans.as.common.model.session.SessionId event io.jans.as.server.service.external.session.SessionEvent httpRequest jakarta.servlet.http.HttpServletRequest jsonArray org.json.JSONArray configurationAttributes java.util.Map SimpleCustomProperty >", "title": "Objects"}, {"location": "script-catalog/application_session/application-session/#common-use-cases", "text": "startSession : Validate first session endSession : Print logs onEvent : If event type is AUTHENTICATED, print sessionId in logs modifyActiveSessionsResponse : Print logs", "title": "Common Use Cases"}, {"location": "script-catalog/application_session/application-session/#script-type-python", "text": "from io.jans.model.custom.script.type.session import ApplicationSessionType from io.jans.service.cdi.util import CdiUtil from io.jans.orm import PersistenceEntryManager from io.jans.as.model.config import StaticConfiguration from io.jans.as.server.model.ldap import TokenEntity from jakarta.faces.application import FacesMessage from io.jans.jsf2.message import FacesMessages from io.jans.util import StringHelper , ArrayHelper from io.jans.as.server.model.config import Constants from java.util import Arrays , ArrayList from io.jans.as.server.service.external.session import SessionEventType import java class ApplicationSession ( ApplicationSessionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Application session. Initialization\" self . entryManager = CdiUtil . bean ( PersistenceEntryManager ) self . staticConfiguration = CdiUtil . bean ( StaticConfiguration ) print \"Application session. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Application session. Destroy\" print \"Application session. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def onEvent ( self , event ): if event . getType () == SessionEventType . AUTHENTICATED : print \"Session is authenticated, session: \" + event . getSessionId () . getId () return def startSession ( self , httpRequest , sessionId , configurationAttributes ): print \"Application session. Starting external session\" user_name = sessionId . getSessionAttributes () . get ( Constants . AUTHENTICATED_USER ) first_session = self . isFirstSession ( user_name ) if not first_session : facesMessages = CdiUtil . bean ( FacesMessages ) facesMessages . add ( FacesMessage . SEVERITY_ERROR , \"Please, end active session first!\" ) return False print \"Application session. External session started successfully\" return True def endSession ( self , httpRequest , sessionId , configurationAttributes ): print \"Application session. Starting external session end\" print \"Application session. External session ended successfully\" return True def modifyActiveSessionsResponse ( self , jsonArray , context ): print \"Application session. Starting external modify active session\" print \"Application session. External modify active session successfully\" return False def isFirstSession ( self , user_name ): tokenLdap = TokenEntity () tokenLdap . setDn ( self . staticConfiguration . getBaseDn () . getClients ()) tokenLdap . setUserId ( user_name ) tokenLdapList = self . entryManager . findEntries ( tokenLdap , 1 ) print \"Application session. isFirstSession. Get result: ' %s '\" % tokenLdapList if ( tokenLdapList != None ) and ( tokenLdapList . size () > 0 ): print \"Application session. isFirstSession: False\" return False print \"Application session. isFirstSession: True\" return True", "title": "Script type: Python"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/", "tags": ["administration", "developer", "script-catalog"], "text": "Authorization Challenge Custom Script # Overview # The Jans-Auth server implements OAuth 2.0 for First-Party Applications . This script is used to control/customize Authorization Challenge Endpoint. Behavior # In request to Authorization Challenge Endpoint to is expected to have acr_values request parameter which specifies name of the custom script. If parameter is absent or AS can't find script with this name then it falls back to script with name default_challenge . This script is provided during installation and performs basic username / password authentication. POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea&scope=openid+profile+address+email+phone+user_name&state=b4a41b29-51c8-4354-9c8c-fda38b4dbd43&nonce=3a56f8d0-f78e-4b15-857c-3e792801be68&acr_values=&request_session_id=false&password=secret&username=admin There is authorizationChallengeDefaultAcr AS configuration property which allows to change fallback script name from default_challenge to some other value (value must be valid script name present on AS). Interface # The Authorization Challenage script implements the AuthorizationChallenageType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description def authorize(self, context) Called when the request is received. def getAuthenticationMethodClaims(self, context) Called to get authn method claims. It is injected into id_token . Returns key-value map. def prepareAuthzRequest(self, context) Prepared authorization request before authorize method. It's good place to restore data from session if needed. authorize method returns true/false which indicates to server whether to issue authorization_code in response or not. If parameters is not present then error has to be created and false returned. If all is good script has to return true and it's strongly recommended to set user context.getExecutionContext().setUser(user); so AS can keep tracking what exactly user is authenticated. prepareAuthzRequest should typically be used for authorization request manipulation before authorize method is invoked. Also if there is multi-step flow where some data are stored in session object, it is good place to restore data from session into request (please find example in sample below). Objects # Object name Object description customScript The custom script object. Reference context Reference Common Use Case: Authorize user by username/password # Script Type: Java # import io.jans.as.common.model.common.User ; import io.jans.as.common.model.session.DeviceSession ; import io.jans.as.server.authorize.ws.rs.DeviceSessionService ; import io.jans.as.server.service.UserService ; import io.jans.as.server.service.external.context.ExternalScriptContext ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.authzchallenge.AuthorizationChallengeType ; import io.jans.orm.PersistenceEntryManager ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.service.custom.script.CustomScriptManager ; import org.apache.commons.lang3.StringUtils ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.util.Map ; import java.util.HashMap ; import java.util.UUID ; /** * @author Yuriy Z */ public class AuthorizationChallenge implements AuthorizationChallengeType { public static final String USERNAME_PARAMETER = \"username\" ; public static final String PASSWORD_PARAMETER = \"password\" ; private static final Logger log = LoggerFactory . getLogger ( AuthorizationChallenge . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); /** * Return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. * <p> * Implementation of this method should consist of 3 main parts: * 1. validate all parameters are present and if not -> set error and return false * 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true * 3. if not ok -> set error which explains what is wrong and return false * * @param scriptContext ExternalScriptContext, see https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/context/ExternalScriptContext.java * @return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. */ @Override public boolean authorize ( Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. validate all required parameters are present final String username = getParameterOrCreateError ( context , USERNAME_PARAMETER ); if ( StringUtils . isBlank ( username )) { return false ; } final String password = getParameterOrCreateError ( context , PASSWORD_PARAMETER ); if ( StringUtils . isBlank ( password )) { return false ; } scriptLogger . trace ( \"All required parameters are present\" ); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil . bean ( UserService . class ); PersistenceEntryManager entryManager = CdiUtil . bean ( PersistenceEntryManager . class ); final User user = userService . getUser ( username ); if ( user == null ) { scriptLogger . trace ( \"User is not found by username {}\" , username ); createError ( context , \"username_invalid\" ); return false ; } final boolean ok = entryManager . authenticate ( user . getDn (), User . class , password ); if ( ok ) { context . getExecutionContext (). setUser ( user ); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger . trace ( \"User {} is authenticated successfully.\" , username ); return true ; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger . trace ( \"Failed to authenticate user {}. Please check username and password.\" , username ); createError ( context , \"username_or_password_invalid\" ); return false ; } private String getParameterOrCreateError ( ExternalScriptContext context , String parameterName ) { String value = context . getHttpRequest (). getParameter ( parameterName ); if ( StringUtils . isBlank ( value )) { scriptLogger . trace ( \"No '{}' parameter in request\" , parameterName ); value = getParameterFromDeviceSession ( context , parameterName ); } if ( StringUtils . isBlank ( value )) { scriptLogger . trace ( \"{} is not provided\" , parameterName ); createError ( context , String . format ( \"%s_required\" , parameterName )); return null ; } return value ; } private void createError ( ExternalScriptContext context , String errorCode ) { String deviceSessionPart = prepareDeviceSessionSubJson ( context ); final String entity = String . format ( \"{\\\"error\\\": \\\"%s\\\"%s}\" , errorCode , deviceSessionPart ); context . createWebApplicationException ( 401 , entity ); } private String prepareDeviceSessionSubJson ( ExternalScriptContext context ) { DeviceSession authorizationChallengeSessionObject = context . getAuthzRequest (). getDeviceSessionObject (); if ( authorizationChallengeSessionObject != null ) { prepareDeviceSession ( context , authorizationChallengeSessionObject ); return String . format ( \",\\\"auth_session\\\":\\\"%s\\\"\" , authorizationChallengeSessionObject . getId ()); } else if ( context . getAuthzRequest (). isUseDeviceSession ()) { authorizationChallengeSessionObject = prepareDeviceSession ( context , null ); return String . format ( \",\\\"auth_session\\\":\\\"%s\\\"\" , authorizationChallengeSessionObject . getId ()); } return \"\" ; } private DeviceSession prepareDeviceSession ( ExternalScriptContext context , DeviceSession authorizationChallengeSessionObject ) { DeviceSessionService deviceSessionService = CdiUtil . bean ( DeviceSessionService . class ); boolean newSave = authorizationChallengeSessionObject == null ; if ( newSave ) { authorizationChallengeSessionObject = deviceSessionService . newDeviceSession (); } String username = context . getHttpRequest (). getParameter ( USERNAME_PARAMETER ); if ( StringUtils . isNotBlank ( username )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( USERNAME_PARAMETER , username ); } String password = context . getHttpRequest (). getParameter ( PASSWORD_PARAMETER ); if ( StringUtils . isNotBlank ( password )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( PASSWORD_PARAMETER , password ); } String clientId = context . getHttpRequest (). getParameter ( \"client_id\" ); if ( StringUtils . isNotBlank ( clientId )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"client_id\" , clientId ); } String acrValues = context . getHttpRequest (). getParameter ( \"acr_values\" ); if ( StringUtils . isNotBlank ( acrValues )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"acr_values\" , acrValues ); } if ( newSave ) { deviceSessionService . persist ( authorizationChallengeSessionObject ); } else { deviceSessionService . merge ( authorizationChallengeSessionObject ); } return authorizationChallengeSessionObject ; } private String getParameterFromDeviceSession ( ExternalScriptContext context , String parameterName ) { final DeviceSession authorizationChallengeSessionObject = context . getAuthzRequest (). getDeviceSessionObject (); if ( authorizationChallengeSessionObject != null ) { return authorizationChallengeSessionObject . getAttributes (). getAttributes (). get ( parameterName ); } return null ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Destroyed Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public Map < String , String > getAuthenticationMethodClaims ( Object context ) { return new HashMap <> (); } } Multi-step authorization by username and OTP # Script Type: Java # import io.jans.as.common.model.common.User; import io.jans.as.common.model.session.DeviceSession; import io.jans.as.server.authorize.ws.rs.DeviceSessionService; import io.jans.as.server.service.UserService; import io.jans.as.server.service.external.context.ExternalScriptContext; import io.jans.model.SimpleCustomProperty; import io.jans.model.custom.script.model.CustomScript; import io.jans.model.custom.script.type.authzchallenge.AuthorizationChallengeType; import io.jans.orm.PersistenceEntryManager; import io.jans.service.cdi.util.CdiUtil; import io.jans.service.custom.script.CustomScriptManager; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; import java.util.HashMap; import java.util.UUID; /** * Script is to demo 2 steps flow: * 1) First step -> send username * 2) Second step -> send OTP * * AS tracks data by 'auth_session'. See \"prepareDeviceSession()\" method implemention for details. * * @author Yuriy Z */ public class AuthorizationChallenge implements AuthorizationChallengeType { public static final String USERNAME_PARAMETER = \"username\"; public static final String OTP_PARAMETER = \"otp\"; private static final Logger log = LoggerFactory.getLogger(AuthorizationChallenge.class); private static final Logger scriptLogger = LoggerFactory.getLogger(CustomScriptManager.class); /** * Return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. * <p> * Implementation of this method should consist of 3 main parts: * 1. validate all parameters are present and if not -> set error and return false * 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true * 3. if not ok -> set error which explains what is wrong and return false * * @param scriptContext ExternalScriptContext, see https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/context/ExternalScriptContext.java * @return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. */ @Override public boolean authorize(Object scriptContext) { ExternalScriptContext context = (ExternalScriptContext) scriptContext; // 1. As first step we get username final String username = getParameterOrCreateError(context, USERNAME_PARAMETER); if (StringUtils.isBlank(username)) { return false; } // 2. During first execution OTP is not present, so error will be returned with auth_session (which has saved username) // Note: prepareDeviceSession method implemention final String otp = getParameterOrCreateError(context, OTP_PARAMETER); if (StringUtils.isBlank(otp)) { return false; } scriptLogger.trace(\"All required parameters are present\"); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil.bean(UserService.class); PersistenceEntryManager entryManager = CdiUtil.bean(PersistenceEntryManager.class); final User user = userService.getUser(username); if (user == null) { scriptLogger.trace(\"User is not found by username {}\", username); createError(context, \"username_invalid\"); return false; } // for simplicity OTP is here just username password but in real world scenario real OTP validation is needed. final boolean ok = entryManager.authenticate(user.getDn(), User.class, otp); if (ok) { context.getExecutionContext().setUser(user); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger.trace(\"User {} is authenticated successfully.\", username); return true; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger.trace(\"Failed to authenticate user {}. Please check username and OTP.\", username); createError(context, \"username_or_otp_invalid\"); return false; } private String getParameterOrCreateError(ExternalScriptContext context, String parameterName) { String value = context.getHttpRequest().getParameter(parameterName); if (StringUtils.isBlank(value)) { scriptLogger.trace(\"No '{}' parameter in request\", parameterName); value = getParameterFromDeviceSession(context, parameterName); } if (StringUtils.isBlank(value)) { scriptLogger.trace(\"{} is not provided\", parameterName); createError(context, String.format(\"%s_required\", parameterName)); return null; } return value; } private void createError(ExternalScriptContext context, String errorCode) { String deviceSessionPart = prepareDeviceSessionSubJson(context); final String entity = String.format(\"{\\\"error\\\": \\\"%s\\\"%s}\", errorCode, deviceSessionPart); context.createWebApplicationException(401, entity); } private String prepareDeviceSessionSubJson(ExternalScriptContext context) { DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { prepareDeviceSession(context, authorizationChallengeSessionObject); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } else if (context.getAuthzRequest().isUseDeviceSession()) { authorizationChallengeSessionObject = prepareDeviceSession(context, null); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } return \"\"; } private DeviceSession prepareDeviceSession(ExternalScriptContext context, DeviceSession authorizationChallengeSessionObject) { DeviceSessionService deviceSessionService = CdiUtil.bean(DeviceSessionService.class); boolean newSave = authorizationChallengeSessionObject == null; if (newSave) { authorizationChallengeSessionObject = deviceSessionService.newDeviceSession(); } String username = context.getHttpRequest().getParameter(USERNAME_PARAMETER); if (StringUtils.isNotBlank(username)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(USERNAME_PARAMETER, username); } String otp = context.getHttpRequest().getParameter(OTP_PARAMETER); if (StringUtils.isNotBlank(otp)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(OTP_PARAMETER, otp); } String clientId = context.getHttpRequest().getParameter(\"client_id\"); if (StringUtils.isNotBlank(clientId)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"client_id\", clientId); } String acrValues = context.getHttpRequest().getParameter(\"acr_values\"); if (StringUtils.isNotBlank(acrValues)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"acr_values\", acrValues); } if (newSave) { deviceSessionService.persist(authorizationChallengeSessionObject); } else { deviceSessionService.merge(authorizationChallengeSessionObject); } return authorizationChallengeSessionObject; } private String getParameterFromDeviceSession(ExternalScriptContext context, String parameterName) { final DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { return authorizationChallengeSessionObject.getAttributes().getAttributes().get(parameterName); } return null; } @Override public boolean init(Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Initialized Default AuthorizationChallenge Java custom script.\"); return true; } @Override public boolean init(CustomScript customScript, Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Initialized Default AuthorizationChallenge Java custom script.\"); return true; } @Override public boolean destroy(Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Destroyed Default AuthorizationChallenge Java custom script.\"); return true; } @Override public int getApiVersion() { return 11; } @Override public Map<String, String> getAuthenticationMethodClaims(Object context) { return new HashMap<>(); } @Override public void prepareAuthzRequest(Object scriptContext) { ExternalScriptContext context = (ExternalScriptContext) scriptContext; final AuthorizationChallengeSession sessionObject = context.getAuthzRequest().getAuthorizationChallengeSessionObject(); if (sessionObject != null) { final Map<String, String> sessionAttributes = sessionObject.getAttributes().getAttributes(); final String scopeFromSession = sessionAttributes.get(\"scope\"); if (StringUtils.isNotBlank(scopeFromSession) && StringUtils.isBlank(context.getAuthzRequest().getScope())) { context.getAuthzRequest().setScope(scopeFromSession); } } } } Sample Scripts # AuthorizationChallenge Multi-step AuthorizationChallenge", "title": "Authorization Challenge"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#authorization-challenge-custom-script", "text": "", "title": "Authorization Challenge Custom Script"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#overview", "text": "The Jans-Auth server implements OAuth 2.0 for First-Party Applications . This script is used to control/customize Authorization Challenge Endpoint.", "title": "Overview"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#behavior", "text": "In request to Authorization Challenge Endpoint to is expected to have acr_values request parameter which specifies name of the custom script. If parameter is absent or AS can't find script with this name then it falls back to script with name default_challenge . This script is provided during installation and performs basic username / password authentication. POST /jans-auth/restv1/authorize-challenge HTTP/1.1 Host: yuriyz-fond-skink.gluu.info client_id=999e13b8-f4a2-4fed-ad3c-6c88bd2c92ea&scope=openid+profile+address+email+phone+user_name&state=b4a41b29-51c8-4354-9c8c-fda38b4dbd43&nonce=3a56f8d0-f78e-4b15-857c-3e792801be68&acr_values=&request_session_id=false&password=secret&username=admin There is authorizationChallengeDefaultAcr AS configuration property which allows to change fallback script name from default_challenge to some other value (value must be valid script name present on AS).", "title": "Behavior"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#interface", "text": "The Authorization Challenage script implements the AuthorizationChallenageType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#new-methods", "text": "Method header Method description def authorize(self, context) Called when the request is received. def getAuthenticationMethodClaims(self, context) Called to get authn method claims. It is injected into id_token . Returns key-value map. def prepareAuthzRequest(self, context) Prepared authorization request before authorize method. It's good place to restore data from session if needed. authorize method returns true/false which indicates to server whether to issue authorization_code in response or not. If parameters is not present then error has to be created and false returned. If all is good script has to return true and it's strongly recommended to set user context.getExecutionContext().setUser(user); so AS can keep tracking what exactly user is authenticated. prepareAuthzRequest should typically be used for authorization request manipulation before authorize method is invoked. Also if there is multi-step flow where some data are stored in session object, it is good place to restore data from session into request (please find example in sample below).", "title": "New methods"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#objects", "text": "Object name Object description customScript The custom script object. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#common-use-case-authorize-user-by-usernamepassword", "text": "", "title": "Common Use Case: Authorize user by username/password"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#script-type-java", "text": "import io.jans.as.common.model.common.User ; import io.jans.as.common.model.session.DeviceSession ; import io.jans.as.server.authorize.ws.rs.DeviceSessionService ; import io.jans.as.server.service.UserService ; import io.jans.as.server.service.external.context.ExternalScriptContext ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.authzchallenge.AuthorizationChallengeType ; import io.jans.orm.PersistenceEntryManager ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.service.custom.script.CustomScriptManager ; import org.apache.commons.lang3.StringUtils ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.util.Map ; import java.util.HashMap ; import java.util.UUID ; /** * @author Yuriy Z */ public class AuthorizationChallenge implements AuthorizationChallengeType { public static final String USERNAME_PARAMETER = \"username\" ; public static final String PASSWORD_PARAMETER = \"password\" ; private static final Logger log = LoggerFactory . getLogger ( AuthorizationChallenge . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); /** * Return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. * <p> * Implementation of this method should consist of 3 main parts: * 1. validate all parameters are present and if not -> set error and return false * 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true * 3. if not ok -> set error which explains what is wrong and return false * * @param scriptContext ExternalScriptContext, see https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/context/ExternalScriptContext.java * @return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. */ @Override public boolean authorize ( Object scriptContext ) { ExternalScriptContext context = ( ExternalScriptContext ) scriptContext ; // 1. validate all required parameters are present final String username = getParameterOrCreateError ( context , USERNAME_PARAMETER ); if ( StringUtils . isBlank ( username )) { return false ; } final String password = getParameterOrCreateError ( context , PASSWORD_PARAMETER ); if ( StringUtils . isBlank ( password )) { return false ; } scriptLogger . trace ( \"All required parameters are present\" ); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil . bean ( UserService . class ); PersistenceEntryManager entryManager = CdiUtil . bean ( PersistenceEntryManager . class ); final User user = userService . getUser ( username ); if ( user == null ) { scriptLogger . trace ( \"User is not found by username {}\" , username ); createError ( context , \"username_invalid\" ); return false ; } final boolean ok = entryManager . authenticate ( user . getDn (), User . class , password ); if ( ok ) { context . getExecutionContext (). setUser ( user ); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger . trace ( \"User {} is authenticated successfully.\" , username ); return true ; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger . trace ( \"Failed to authenticate user {}. Please check username and password.\" , username ); createError ( context , \"username_or_password_invalid\" ); return false ; } private String getParameterOrCreateError ( ExternalScriptContext context , String parameterName ) { String value = context . getHttpRequest (). getParameter ( parameterName ); if ( StringUtils . isBlank ( value )) { scriptLogger . trace ( \"No '{}' parameter in request\" , parameterName ); value = getParameterFromDeviceSession ( context , parameterName ); } if ( StringUtils . isBlank ( value )) { scriptLogger . trace ( \"{} is not provided\" , parameterName ); createError ( context , String . format ( \"%s_required\" , parameterName )); return null ; } return value ; } private void createError ( ExternalScriptContext context , String errorCode ) { String deviceSessionPart = prepareDeviceSessionSubJson ( context ); final String entity = String . format ( \"{\\\"error\\\": \\\"%s\\\"%s}\" , errorCode , deviceSessionPart ); context . createWebApplicationException ( 401 , entity ); } private String prepareDeviceSessionSubJson ( ExternalScriptContext context ) { DeviceSession authorizationChallengeSessionObject = context . getAuthzRequest (). getDeviceSessionObject (); if ( authorizationChallengeSessionObject != null ) { prepareDeviceSession ( context , authorizationChallengeSessionObject ); return String . format ( \",\\\"auth_session\\\":\\\"%s\\\"\" , authorizationChallengeSessionObject . getId ()); } else if ( context . getAuthzRequest (). isUseDeviceSession ()) { authorizationChallengeSessionObject = prepareDeviceSession ( context , null ); return String . format ( \",\\\"auth_session\\\":\\\"%s\\\"\" , authorizationChallengeSessionObject . getId ()); } return \"\" ; } private DeviceSession prepareDeviceSession ( ExternalScriptContext context , DeviceSession authorizationChallengeSessionObject ) { DeviceSessionService deviceSessionService = CdiUtil . bean ( DeviceSessionService . class ); boolean newSave = authorizationChallengeSessionObject == null ; if ( newSave ) { authorizationChallengeSessionObject = deviceSessionService . newDeviceSession (); } String username = context . getHttpRequest (). getParameter ( USERNAME_PARAMETER ); if ( StringUtils . isNotBlank ( username )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( USERNAME_PARAMETER , username ); } String password = context . getHttpRequest (). getParameter ( PASSWORD_PARAMETER ); if ( StringUtils . isNotBlank ( password )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( PASSWORD_PARAMETER , password ); } String clientId = context . getHttpRequest (). getParameter ( \"client_id\" ); if ( StringUtils . isNotBlank ( clientId )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"client_id\" , clientId ); } String acrValues = context . getHttpRequest (). getParameter ( \"acr_values\" ); if ( StringUtils . isNotBlank ( acrValues )) { authorizationChallengeSessionObject . getAttributes (). getAttributes (). put ( \"acr_values\" , acrValues ); } if ( newSave ) { deviceSessionService . persist ( authorizationChallengeSessionObject ); } else { deviceSessionService . merge ( authorizationChallengeSessionObject ); } return authorizationChallengeSessionObject ; } private String getParameterFromDeviceSession ( ExternalScriptContext context , String parameterName ) { final DeviceSession authorizationChallengeSessionObject = context . getAuthzRequest (). getDeviceSessionObject (); if ( authorizationChallengeSessionObject != null ) { return authorizationChallengeSessionObject . getAttributes (). getAttributes (). get ( parameterName ); } return null ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Destroyed Default AuthorizationChallenge Java custom script.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public Map < String , String > getAuthenticationMethodClaims ( Object context ) { return new HashMap <> (); } }", "title": "Script Type: Java"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#multi-step-authorization-by-username-and-otp", "text": "", "title": "Multi-step authorization by username and OTP"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#script-type-java_1", "text": "import io.jans.as.common.model.common.User; import io.jans.as.common.model.session.DeviceSession; import io.jans.as.server.authorize.ws.rs.DeviceSessionService; import io.jans.as.server.service.UserService; import io.jans.as.server.service.external.context.ExternalScriptContext; import io.jans.model.SimpleCustomProperty; import io.jans.model.custom.script.model.CustomScript; import io.jans.model.custom.script.type.authzchallenge.AuthorizationChallengeType; import io.jans.orm.PersistenceEntryManager; import io.jans.service.cdi.util.CdiUtil; import io.jans.service.custom.script.CustomScriptManager; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; import java.util.HashMap; import java.util.UUID; /** * Script is to demo 2 steps flow: * 1) First step -> send username * 2) Second step -> send OTP * * AS tracks data by 'auth_session'. See \"prepareDeviceSession()\" method implemention for details. * * @author Yuriy Z */ public class AuthorizationChallenge implements AuthorizationChallengeType { public static final String USERNAME_PARAMETER = \"username\"; public static final String OTP_PARAMETER = \"otp\"; private static final Logger log = LoggerFactory.getLogger(AuthorizationChallenge.class); private static final Logger scriptLogger = LoggerFactory.getLogger(CustomScriptManager.class); /** * Return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. * <p> * Implementation of this method should consist of 3 main parts: * 1. validate all parameters are present and if not -> set error and return false * 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true * 3. if not ok -> set error which explains what is wrong and return false * * @param scriptContext ExternalScriptContext, see https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/context/ExternalScriptContext.java * @return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. */ @Override public boolean authorize(Object scriptContext) { ExternalScriptContext context = (ExternalScriptContext) scriptContext; // 1. As first step we get username final String username = getParameterOrCreateError(context, USERNAME_PARAMETER); if (StringUtils.isBlank(username)) { return false; } // 2. During first execution OTP is not present, so error will be returned with auth_session (which has saved username) // Note: prepareDeviceSession method implemention final String otp = getParameterOrCreateError(context, OTP_PARAMETER); if (StringUtils.isBlank(otp)) { return false; } scriptLogger.trace(\"All required parameters are present\"); // 2. main authorization logic, if ok -> set authorized user into \"context.getExecutionContext().setUser(user);\" and return true UserService userService = CdiUtil.bean(UserService.class); PersistenceEntryManager entryManager = CdiUtil.bean(PersistenceEntryManager.class); final User user = userService.getUser(username); if (user == null) { scriptLogger.trace(\"User is not found by username {}\", username); createError(context, \"username_invalid\"); return false; } // for simplicity OTP is here just username password but in real world scenario real OTP validation is needed. final boolean ok = entryManager.authenticate(user.getDn(), User.class, otp); if (ok) { context.getExecutionContext().setUser(user); // <- IMPORTANT : without user set, user relation will not be associated with token scriptLogger.trace(\"User {} is authenticated successfully.\", username); return true; } // 3. not ok -> set error which explains what is wrong and return false scriptLogger.trace(\"Failed to authenticate user {}. Please check username and OTP.\", username); createError(context, \"username_or_otp_invalid\"); return false; } private String getParameterOrCreateError(ExternalScriptContext context, String parameterName) { String value = context.getHttpRequest().getParameter(parameterName); if (StringUtils.isBlank(value)) { scriptLogger.trace(\"No '{}' parameter in request\", parameterName); value = getParameterFromDeviceSession(context, parameterName); } if (StringUtils.isBlank(value)) { scriptLogger.trace(\"{} is not provided\", parameterName); createError(context, String.format(\"%s_required\", parameterName)); return null; } return value; } private void createError(ExternalScriptContext context, String errorCode) { String deviceSessionPart = prepareDeviceSessionSubJson(context); final String entity = String.format(\"{\\\"error\\\": \\\"%s\\\"%s}\", errorCode, deviceSessionPart); context.createWebApplicationException(401, entity); } private String prepareDeviceSessionSubJson(ExternalScriptContext context) { DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { prepareDeviceSession(context, authorizationChallengeSessionObject); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } else if (context.getAuthzRequest().isUseDeviceSession()) { authorizationChallengeSessionObject = prepareDeviceSession(context, null); return String.format(\",\\\"auth_session\\\":\\\"%s\\\"\", authorizationChallengeSessionObject.getId()); } return \"\"; } private DeviceSession prepareDeviceSession(ExternalScriptContext context, DeviceSession authorizationChallengeSessionObject) { DeviceSessionService deviceSessionService = CdiUtil.bean(DeviceSessionService.class); boolean newSave = authorizationChallengeSessionObject == null; if (newSave) { authorizationChallengeSessionObject = deviceSessionService.newDeviceSession(); } String username = context.getHttpRequest().getParameter(USERNAME_PARAMETER); if (StringUtils.isNotBlank(username)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(USERNAME_PARAMETER, username); } String otp = context.getHttpRequest().getParameter(OTP_PARAMETER); if (StringUtils.isNotBlank(otp)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(OTP_PARAMETER, otp); } String clientId = context.getHttpRequest().getParameter(\"client_id\"); if (StringUtils.isNotBlank(clientId)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"client_id\", clientId); } String acrValues = context.getHttpRequest().getParameter(\"acr_values\"); if (StringUtils.isNotBlank(acrValues)) { authorizationChallengeSessionObject.getAttributes().getAttributes().put(\"acr_values\", acrValues); } if (newSave) { deviceSessionService.persist(authorizationChallengeSessionObject); } else { deviceSessionService.merge(authorizationChallengeSessionObject); } return authorizationChallengeSessionObject; } private String getParameterFromDeviceSession(ExternalScriptContext context, String parameterName) { final DeviceSession authorizationChallengeSessionObject = context.getAuthzRequest().getDeviceSessionObject(); if (authorizationChallengeSessionObject != null) { return authorizationChallengeSessionObject.getAttributes().getAttributes().get(parameterName); } return null; } @Override public boolean init(Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Initialized Default AuthorizationChallenge Java custom script.\"); return true; } @Override public boolean init(CustomScript customScript, Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Initialized Default AuthorizationChallenge Java custom script.\"); return true; } @Override public boolean destroy(Map<String, SimpleCustomProperty> configurationAttributes) { scriptLogger.info(\"Destroyed Default AuthorizationChallenge Java custom script.\"); return true; } @Override public int getApiVersion() { return 11; } @Override public Map<String, String> getAuthenticationMethodClaims(Object context) { return new HashMap<>(); } @Override public void prepareAuthzRequest(Object scriptContext) { ExternalScriptContext context = (ExternalScriptContext) scriptContext; final AuthorizationChallengeSession sessionObject = context.getAuthzRequest().getAuthorizationChallengeSessionObject(); if (sessionObject != null) { final Map<String, String> sessionAttributes = sessionObject.getAttributes().getAttributes(); final String scopeFromSession = sessionAttributes.get(\"scope\"); if (StringUtils.isNotBlank(scopeFromSession) && StringUtils.isBlank(context.getAuthzRequest().getScope())) { context.getAuthzRequest().setScope(scopeFromSession); } } } }", "title": "Script Type: Java"}, {"location": "script-catalog/authorization_challenge/authorization-challenge/#sample-scripts", "text": "AuthorizationChallenge Multi-step AuthorizationChallenge", "title": "Sample Scripts"}, {"location": "script-catalog/ciba/ciba/", "tags": ["administration", "developer", "script-catalog"], "text": "CIBA End User Notification Script (EndUserNotification) # Overview # The Jans-Auth server implements OAuth 2.0 Rich Authorization Requests . This script is used to control/customize cache refresh. Interface # The CIBA end user script implements the EndUserNotificationType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description notifyEndUser(self, context) Returns boolean true or false depending on the process, if the notification is sent successfully or not Script Type: Python # from io.jans.as.client.fcm import FirebaseCloudMessagingResponse from io.jans.as.client.fcm import FirebaseCloudMessagingClient from io.jans.as.client.fcm import FirebaseCloudMessagingRequest from io.jans.as.util import RedirectUri from io.jans.model.custom.script.type.ciba import EndUserNotificationType from java.lang import String from java.util import UUID class EndUserNotification(EndUserNotificationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, configurationAttributes): print \"Firebase EndUserNotification script. Initializing ...\" print \"Firebase EndUserNotification script. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Firebase EndUserNotification script. Destroying ...\" print \"Firebase EndUserNotification script. Destroyed successfully\" return True def getApiVersion(self): return 1 # Returns boolean true or false depending on the process, if the notification # is sent successfully or not. def notifyEndUser(self, context): print 'Sending push notification using Firebase Cloud Messaging' appConfiguration = context.getAppConfiguration() encryptionService = context.getEncryptionService() clientId = appConfiguration.getBackchannelClientId() redirectUri = appConfiguration.getBackchannelRedirectUri() url = appConfiguration.getCibaEndUserNotificationConfig().getNotificationUrl() key = encryptionService.decrypt(appConfiguration.getCibaEndUserNotificationConfig().getNotificationKey(), True) to = context.getDeviceRegistrationToken() title = \"oxAuth Authentication Request\" body = \"Client Initiated Backchannel Authentication (CIBA)\" authorizationRequestUri = RedirectUri(appConfiguration.getAuthorizationEndpoint()) authorizationRequestUri.addResponseParameter(\"client_id\", clientId) authorizationRequestUri.addResponseParameter(\"response_type\", \"id_token\") authorizationRequestUri.addResponseParameter(\"scope\", context.getScope()) authorizationRequestUri.addResponseParameter(\"acr_values\", context.getAcrValues()) authorizationRequestUri.addResponseParameter(\"redirect_uri\", redirectUri) authorizationRequestUri.addResponseParameter(\"state\", UUID.randomUUID().toString()) authorizationRequestUri.addResponseParameter(\"nonce\", UUID.randomUUID().toString()) authorizationRequestUri.addResponseParameter(\"prompt\", \"consent\") authorizationRequestUri.addResponseParameter(\"auth_req_id\", context.getAuthReqId()) clickAction = authorizationRequestUri.toString() firebaseCloudMessagingRequest = FirebaseCloudMessagingRequest(key, to, title, body, clickAction) firebaseCloudMessagingClient = FirebaseCloudMessagingClient(url) firebaseCloudMessagingClient.setRequest(firebaseCloudMessagingRequest) firebaseCloudMessagingResponse = firebaseCloudMessagingClient.exec() responseStatus = firebaseCloudMessagingResponse.getStatus() print \"CIBA: firebase cloud messaging result status \" + str(responseStatus) return (responseStatus >= 200 and responseStatus < 300 ) Sample Scripts # EndUserNotification This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "CIBA End User Notification"}, {"location": "script-catalog/ciba/ciba/#ciba-end-user-notification-script-endusernotification", "text": "", "title": "CIBA End User Notification Script (EndUserNotification)"}, {"location": "script-catalog/ciba/ciba/#overview", "text": "The Jans-Auth server implements OAuth 2.0 Rich Authorization Requests . This script is used to control/customize cache refresh.", "title": "Overview"}, {"location": "script-catalog/ciba/ciba/#interface", "text": "The CIBA end user script implements the EndUserNotificationType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/ciba/ciba/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/ciba/ciba/#new-methods", "text": "Method header Method description notifyEndUser(self, context) Returns boolean true or false depending on the process, if the notification is sent successfully or not", "title": "New methods"}, {"location": "script-catalog/ciba/ciba/#script-type-python", "text": "from io.jans.as.client.fcm import FirebaseCloudMessagingResponse from io.jans.as.client.fcm import FirebaseCloudMessagingClient from io.jans.as.client.fcm import FirebaseCloudMessagingRequest from io.jans.as.util import RedirectUri from io.jans.model.custom.script.type.ciba import EndUserNotificationType from java.lang import String from java.util import UUID class EndUserNotification(EndUserNotificationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, configurationAttributes): print \"Firebase EndUserNotification script. Initializing ...\" print \"Firebase EndUserNotification script. Initialized successfully\" return True def destroy(self, configurationAttributes): print \"Firebase EndUserNotification script. Destroying ...\" print \"Firebase EndUserNotification script. Destroyed successfully\" return True def getApiVersion(self): return 1 # Returns boolean true or false depending on the process, if the notification # is sent successfully or not. def notifyEndUser(self, context): print 'Sending push notification using Firebase Cloud Messaging' appConfiguration = context.getAppConfiguration() encryptionService = context.getEncryptionService() clientId = appConfiguration.getBackchannelClientId() redirectUri = appConfiguration.getBackchannelRedirectUri() url = appConfiguration.getCibaEndUserNotificationConfig().getNotificationUrl() key = encryptionService.decrypt(appConfiguration.getCibaEndUserNotificationConfig().getNotificationKey(), True) to = context.getDeviceRegistrationToken() title = \"oxAuth Authentication Request\" body = \"Client Initiated Backchannel Authentication (CIBA)\" authorizationRequestUri = RedirectUri(appConfiguration.getAuthorizationEndpoint()) authorizationRequestUri.addResponseParameter(\"client_id\", clientId) authorizationRequestUri.addResponseParameter(\"response_type\", \"id_token\") authorizationRequestUri.addResponseParameter(\"scope\", context.getScope()) authorizationRequestUri.addResponseParameter(\"acr_values\", context.getAcrValues()) authorizationRequestUri.addResponseParameter(\"redirect_uri\", redirectUri) authorizationRequestUri.addResponseParameter(\"state\", UUID.randomUUID().toString()) authorizationRequestUri.addResponseParameter(\"nonce\", UUID.randomUUID().toString()) authorizationRequestUri.addResponseParameter(\"prompt\", \"consent\") authorizationRequestUri.addResponseParameter(\"auth_req_id\", context.getAuthReqId()) clickAction = authorizationRequestUri.toString() firebaseCloudMessagingRequest = FirebaseCloudMessagingRequest(key, to, title, body, clickAction) firebaseCloudMessagingClient = FirebaseCloudMessagingClient(url) firebaseCloudMessagingClient.setRequest(firebaseCloudMessagingRequest) firebaseCloudMessagingResponse = firebaseCloudMessagingClient.exec() responseStatus = firebaseCloudMessagingResponse.getStatus() print \"CIBA: firebase cloud messaging result status \" + str(responseStatus) return (responseStatus >= 200 and responseStatus < 300 )", "title": "Script Type: Python"}, {"location": "script-catalog/ciba/ciba/#sample-scripts", "text": "EndUserNotification", "title": "Sample Scripts"}, {"location": "script-catalog/ciba/ciba/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/ciba/ciba/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/ciba/ciba/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/client_authn/client-authn/", "tags": ["administration", "developer", "script-catalog"], "text": "Client Authentication Custom Script # Overview # AS support different types of client authentications such as : client_secret_basic client_secret_post client_secret_jwt private_key_jwt Sometimes it's convenient to customize default AS client authentication process. For this reason Client Authentication custom script was introduced. If script successfully authenticated client, it should return it in authenticateClient . If client is not returned then AS performs built-in authentication. Interface # The Client Authentication script implements the ClientAuthnType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description def authenticateClient(self, context) Called when the request is received. authenticateClient method returns authenticated Client object or null if authentication failed. Objects # Object name Object description customScript The custom script object. Reference context Reference Sample script which demonstrates basic client authentication # Script Type: Java # import io.jans.as.common.model.registration.Client ; import io.jans.as.model.config.Constants ; import io.jans.as.server.service.ClientService ; import io.jans.as.server.service.external.context.ExternalClientAuthnContext ; import io.jans.as.server.service.token.TokenService ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.client.ClientAuthnType ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.service.custom.script.CustomScriptManager ; import jakarta.servlet.http.HttpServletRequest ; import jakarta.servlet.http.HttpServletResponse ; import org.apache.commons.codec.binary.Base64 ; import org.apache.commons.lang.StringUtils ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.net.URLDecoder ; import java.nio.charset.StandardCharsets ; import java.util.Map ; /** * @author Yuriy Z */ public class ClientAuthn implements ClientAuthnType { private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public Object authenticateClient ( Object clientAuthnContext ) { final ExternalClientAuthnContext context = ( ExternalClientAuthnContext ) clientAuthnContext ; final HttpServletRequest request = context . getHttpRequest (); final HttpServletResponse response = context . getHttpResponse (); String authorization = request . getHeader ( Constants . AUTHORIZATION ); if ( ! StringUtils . startsWith ( authorization , \"Basic\" )) { context . sendUnauthorizedError (); return null ; } TokenService tokenService = CdiUtil . bean ( TokenService . class ); ClientService clientService = CdiUtil . bean ( ClientService . class ); String base64Token = tokenService . getBasicToken ( authorization ); String token = new String ( Base64 . decodeBase64 ( base64Token ), StandardCharsets . UTF_8 ); int delim = token . indexOf ( \":\" ); if ( delim != - 1 ) { String clientId = URLDecoder . decode ( token . substring ( 0 , delim ), StandardCharsets . UTF_8 ); String clientSecret = URLDecoder . decode ( token . substring ( delim + 1 ), StandardCharsets . UTF_8 ); final boolean authenticated = clientService . authenticate ( clientId , clientSecret ); if ( authenticated ) { final Client client = clientService . getClient ( clientId ); scriptLogger . debug ( \"Successfully performed basic client authentication, clientId: {}\" , clientId ); return client ; } } context . sendUnauthorizedError (); return null ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized ClientAuthn Java custom script.\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized ClientAuthn Java custom script.\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Destroyed ClientAuthn Java custom script.\" ); return false ; } @Override public int getApiVersion () { return 11 ; } } Sample Scripts # ClientAuthentication", "title": "Client Authentication"}, {"location": "script-catalog/client_authn/client-authn/#client-authentication-custom-script", "text": "", "title": "Client Authentication Custom Script"}, {"location": "script-catalog/client_authn/client-authn/#overview", "text": "AS support different types of client authentications such as : client_secret_basic client_secret_post client_secret_jwt private_key_jwt Sometimes it's convenient to customize default AS client authentication process. For this reason Client Authentication custom script was introduced. If script successfully authenticated client, it should return it in authenticateClient . If client is not returned then AS performs built-in authentication.", "title": "Overview"}, {"location": "script-catalog/client_authn/client-authn/#interface", "text": "The Client Authentication script implements the ClientAuthnType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/client_authn/client-authn/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/client_authn/client-authn/#new-methods", "text": "Method header Method description def authenticateClient(self, context) Called when the request is received. authenticateClient method returns authenticated Client object or null if authentication failed.", "title": "New methods"}, {"location": "script-catalog/client_authn/client-authn/#objects", "text": "Object name Object description customScript The custom script object. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/client_authn/client-authn/#sample-script-which-demonstrates-basic-client-authentication", "text": "", "title": "Sample script which demonstrates basic client authentication"}, {"location": "script-catalog/client_authn/client-authn/#script-type-java", "text": "import io.jans.as.common.model.registration.Client ; import io.jans.as.model.config.Constants ; import io.jans.as.server.service.ClientService ; import io.jans.as.server.service.external.context.ExternalClientAuthnContext ; import io.jans.as.server.service.token.TokenService ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.client.ClientAuthnType ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.service.custom.script.CustomScriptManager ; import jakarta.servlet.http.HttpServletRequest ; import jakarta.servlet.http.HttpServletResponse ; import org.apache.commons.codec.binary.Base64 ; import org.apache.commons.lang.StringUtils ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.net.URLDecoder ; import java.nio.charset.StandardCharsets ; import java.util.Map ; /** * @author Yuriy Z */ public class ClientAuthn implements ClientAuthnType { private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public Object authenticateClient ( Object clientAuthnContext ) { final ExternalClientAuthnContext context = ( ExternalClientAuthnContext ) clientAuthnContext ; final HttpServletRequest request = context . getHttpRequest (); final HttpServletResponse response = context . getHttpResponse (); String authorization = request . getHeader ( Constants . AUTHORIZATION ); if ( ! StringUtils . startsWith ( authorization , \"Basic\" )) { context . sendUnauthorizedError (); return null ; } TokenService tokenService = CdiUtil . bean ( TokenService . class ); ClientService clientService = CdiUtil . bean ( ClientService . class ); String base64Token = tokenService . getBasicToken ( authorization ); String token = new String ( Base64 . decodeBase64 ( base64Token ), StandardCharsets . UTF_8 ); int delim = token . indexOf ( \":\" ); if ( delim != - 1 ) { String clientId = URLDecoder . decode ( token . substring ( 0 , delim ), StandardCharsets . UTF_8 ); String clientSecret = URLDecoder . decode ( token . substring ( delim + 1 ), StandardCharsets . UTF_8 ); final boolean authenticated = clientService . authenticate ( clientId , clientSecret ); if ( authenticated ) { final Client client = clientService . getClient ( clientId ); scriptLogger . debug ( \"Successfully performed basic client authentication, clientId: {}\" , clientId ); return client ; } } context . sendUnauthorizedError (); return null ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized ClientAuthn Java custom script.\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Initialized ClientAuthn Java custom script.\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { scriptLogger . info ( \"Destroyed ClientAuthn Java custom script.\" ); return false ; } @Override public int getApiVersion () { return 11 ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/client_authn/client-authn/#sample-scripts", "text": "ClientAuthentication", "title": "Sample Scripts"}, {"location": "script-catalog/client_registration/client-registration/", "tags": ["administration", "developer", "script-catalog"], "text": "Client Registration scripts # Overview # The Jans-Auth server implements the OpenID Connect Dynamic Client Registration specification. This allows developers to register a client with the Authorization Server (AS) without any intervention from the administrator. By default, all clients are given the same default scopes and attributes. Through the use of an interception script, this behavior can be modified. These scripts can be used to analyze the registration request and apply customizations to the registered client. For example, a client can be given specific scopes by analyzing the Software Statement that is sent with the registration request. Behavior # By default, Jans server has no dynamic client registration scripts enabled, and all clients are given the same attributes. When a script is added and enabled, the script will run and return a boolean after applying logic to the registration request. If true , the client is registered and client credentials are returned. Generally, the script is global for all registration requests, and only one script is enabled at a time. Registration flow # sequenceDiagram title Client Registration script autonumber 1 RP->>Jans AS: /register request Jans AS->>Jans AS: Is there a client registration script enabled? Jans AS->>Jans AS: run script note right of Jans AS: Apply custom logic e.g <br/> Add scopes <br/> Set attributes <br/> validate SSA Jans AS->>RP: return client credentials Interface # The client registration script implements the ClientRegistrationType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description def createClient(self, context) Called when the dynamic client registration request is received. def updateClient(self, context) Called when the PUT method is called on registration endpoint to update client details. def getSoftwareStatementHmacSecret(self, context) Returns secret key which will be used to validate Software Statement if HMAC algorithm is used (e.g. HS256, HS512) def getSoftwareStatementJwks(self, context) Returns JWKS which will be used to validate Software Statement if keys are used (e.g. RS256) def modifyPutResponse(self, responseAsJsonObject, executionContext) Modifies the response from the PUT request to registration endpoint def modifyReadResponse(self, responseAsJsonObject, executionContext) Modifies the response from the GET request to registration endpoint def modifyPostResponse(self, responseAsJsonObject, executionContext) Modifies the response from the POST request to registration endpoint Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference responseAsJsonObject Java JSONObject. Reference executionContext Reference Common Use Case: Adding scopes defined in the script configuration parameters # Script Type: Python # from io.jans.model.custom.script.type.client import ClientRegistrationType from io.jans.service.cdi.util import CdiUtil from io.jans.orm.util import StringHelper , ArrayHelper from io.jans.as.server.service import ScopeService import json class ClientRegistration ( ClientRegistrationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Client registration. Initialization\" if ( not configurationAttributes . containsKey ( \"scope_list\" )): print \"Client registration. Initialization failed. Scope List not defined.\" return False else : self . scope_list = configurationAttributes . get ( \"scope_list\" ) . getValue2 () print \"Client registration. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Client registration. Destroy\" print \"Client registration. Destroyed successfully\" return True def createClient ( self , context ): scopeService = CdiUtil . bean ( ScopeService ) currentScopes = client . getScopes () for newScope in self . scope_list : foundScope = scopeService . getScopeById ( newScope ) if foundScope is None : print \"Client Registration. New scope(s) not found.\" return False newScopes = ArrayHelper . addItemToStringArray ( currentScopes , foundScope . getDn ()) client . setScopes ( newScopes ) return True def updateClient ( self , context ): print \"SSA Client registration. UpdateClient method\" pass def getApiVersion ( self ): return 11 # Returns secret key which will be used to validate Software Statement if HMAC algorithm is used (e.g. HS256, HS512). Invoked if oxauth conf property softwareStatementValidationType=SCRIPT which is default/fallback value. def getSoftwareStatementHmacSecret ( self , context ): pass # Returns JWKS which will be used to validate Software Statement if keys are used (e.g. RS256). Invoked if oxauth conf property softwareStatementValidationType=SCRIPT which is default/fallback value. def getSoftwareStatementJwks ( self , context ): pass def modifyPutResponse ( self , responseAsJsonObject , executionContext ): return False def modifyReadResponse ( self , responseAsJsonObject , executionContext ): return False def modifyPostResponse ( self , responseAsJsonObject , executionContext ): return False Script Type: Java # import io.jans.as.common.model.registration.Client ; import io.jans.as.persistence.model.Scope ; import io.jans.as.server.service.ScopeService ; import io.jans.as.server.service.external.context.DynamicClientRegistrationContext ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.client.ClientRegistrationType ; import io.jans.orm.util.ArrayHelper ; import io.jans.service.cdi.util.CdiUtil ; import org.json.JSONArray ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.util.Map ; public class ClientRegistration implements ClientRegistrationType { private static final Logger log = LoggerFactory . getLogger ( ClientRegistration . class ); JSONArray json_array = null ; @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { if ( ! configurationAttributes . containsKey ( \"scope_list\" )) { log . info ( \"Client registration. Initialization failed. Scope List not found.\" ); return false ; } String scope_list = configurationAttributes . get ( \"scope_list\" ). getValue2 (); json_array = new JSONArray ( scope_list ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Client registration. Initialization.\" ); log . info ( configurationAttributes . toString ()); if ( ! configurationAttributes . containsKey ( \"scope_list\" )) { log . info ( \"Client registration. Initialization failed. Scope List not found.\" ); return false ; } String scope_list = configurationAttributes . get ( \"scope_list\" ). getValue2 (); json_array = new JSONArray ( scope_list ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Client registration. Destroy.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean createClient ( Object context ) { log . info ( \"Client registration. CreateClient method\" ); DynamicClientRegistrationContext regContext = ( DynamicClientRegistrationContext ) context ; Client client = regContext . getClient (); ScopeService scopeService = CdiUtil . bean ( ScopeService . class ); String [] currentScopes = client . getScopes (); String [] newScopes = currentScopes . clone (); for ( int i = 0 ; i < json_array . length (); i ++ ) { String scopeName = ( String ) json_array . get ( i ); Scope foundScope = scopeService . getScopeById ( scopeName ); if ( foundScope == null ) { log . info ( \"Client registration. Scope not found\" ); return false ; } newScopes = ArrayHelper . addItemToStringArray ( newScopes , foundScope . getDn ()); } client . setScopes ( newScopes ); log . info ( \"Client registration. Scopes added.\" ); return true ; } @Override public boolean updateClient ( Object context ) { return true ; } // This method needs to be overridden if client is providing an SSA with HMAC @Override public String getSoftwareStatementHmacSecret ( Object context ) { return \"\" ; } // This method needs to be overridden if client is providing an SSA and RS256 validation @Override public String getSoftwareStatementJwks ( Object context ) { return \"\" ; } @Override public String getDcrHmacSecret ( Object o ) { return \"\" ; } @Override public String getDcrJwks ( Object o ) { return \"\" ; } @Override public boolean isCertValidForClient ( Object o , Object o1 ) { return false ; } @Override public boolean modifyPutResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } @Override public boolean modifyReadResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } @Override public boolean modifyPostResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } } Sample Scripts # OpenBanking", "title": "Client Registration"}, {"location": "script-catalog/client_registration/client-registration/#client-registration-scripts", "text": "", "title": "Client Registration scripts"}, {"location": "script-catalog/client_registration/client-registration/#overview", "text": "The Jans-Auth server implements the OpenID Connect Dynamic Client Registration specification. This allows developers to register a client with the Authorization Server (AS) without any intervention from the administrator. By default, all clients are given the same default scopes and attributes. Through the use of an interception script, this behavior can be modified. These scripts can be used to analyze the registration request and apply customizations to the registered client. For example, a client can be given specific scopes by analyzing the Software Statement that is sent with the registration request.", "title": "Overview"}, {"location": "script-catalog/client_registration/client-registration/#behavior", "text": "By default, Jans server has no dynamic client registration scripts enabled, and all clients are given the same attributes. When a script is added and enabled, the script will run and return a boolean after applying logic to the registration request. If true , the client is registered and client credentials are returned. Generally, the script is global for all registration requests, and only one script is enabled at a time.", "title": "Behavior"}, {"location": "script-catalog/client_registration/client-registration/#registration-flow", "text": "sequenceDiagram title Client Registration script autonumber 1 RP->>Jans AS: /register request Jans AS->>Jans AS: Is there a client registration script enabled? Jans AS->>Jans AS: run script note right of Jans AS: Apply custom logic e.g <br/> Add scopes <br/> Set attributes <br/> validate SSA Jans AS->>RP: return client credentials", "title": "Registration flow"}, {"location": "script-catalog/client_registration/client-registration/#interface", "text": "The client registration script implements the ClientRegistrationType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/client_registration/client-registration/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/client_registration/client-registration/#new-methods", "text": "Method header Method description def createClient(self, context) Called when the dynamic client registration request is received. def updateClient(self, context) Called when the PUT method is called on registration endpoint to update client details. def getSoftwareStatementHmacSecret(self, context) Returns secret key which will be used to validate Software Statement if HMAC algorithm is used (e.g. HS256, HS512) def getSoftwareStatementJwks(self, context) Returns JWKS which will be used to validate Software Statement if keys are used (e.g. RS256) def modifyPutResponse(self, responseAsJsonObject, executionContext) Modifies the response from the PUT request to registration endpoint def modifyReadResponse(self, responseAsJsonObject, executionContext) Modifies the response from the GET request to registration endpoint def modifyPostResponse(self, responseAsJsonObject, executionContext) Modifies the response from the POST request to registration endpoint", "title": "New methods"}, {"location": "script-catalog/client_registration/client-registration/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference responseAsJsonObject Java JSONObject. Reference executionContext Reference", "title": "Objects"}, {"location": "script-catalog/client_registration/client-registration/#common-use-case-adding-scopes-defined-in-the-script-configuration-parameters", "text": "", "title": "Common Use Case: Adding scopes defined in the script configuration parameters"}, {"location": "script-catalog/client_registration/client-registration/#script-type-python", "text": "from io.jans.model.custom.script.type.client import ClientRegistrationType from io.jans.service.cdi.util import CdiUtil from io.jans.orm.util import StringHelper , ArrayHelper from io.jans.as.server.service import ScopeService import json class ClientRegistration ( ClientRegistrationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Client registration. Initialization\" if ( not configurationAttributes . containsKey ( \"scope_list\" )): print \"Client registration. Initialization failed. Scope List not defined.\" return False else : self . scope_list = configurationAttributes . get ( \"scope_list\" ) . getValue2 () print \"Client registration. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Client registration. Destroy\" print \"Client registration. Destroyed successfully\" return True def createClient ( self , context ): scopeService = CdiUtil . bean ( ScopeService ) currentScopes = client . getScopes () for newScope in self . scope_list : foundScope = scopeService . getScopeById ( newScope ) if foundScope is None : print \"Client Registration. New scope(s) not found.\" return False newScopes = ArrayHelper . addItemToStringArray ( currentScopes , foundScope . getDn ()) client . setScopes ( newScopes ) return True def updateClient ( self , context ): print \"SSA Client registration. UpdateClient method\" pass def getApiVersion ( self ): return 11 # Returns secret key which will be used to validate Software Statement if HMAC algorithm is used (e.g. HS256, HS512). Invoked if oxauth conf property softwareStatementValidationType=SCRIPT which is default/fallback value. def getSoftwareStatementHmacSecret ( self , context ): pass # Returns JWKS which will be used to validate Software Statement if keys are used (e.g. RS256). Invoked if oxauth conf property softwareStatementValidationType=SCRIPT which is default/fallback value. def getSoftwareStatementJwks ( self , context ): pass def modifyPutResponse ( self , responseAsJsonObject , executionContext ): return False def modifyReadResponse ( self , responseAsJsonObject , executionContext ): return False def modifyPostResponse ( self , responseAsJsonObject , executionContext ): return False", "title": "Script Type: Python"}, {"location": "script-catalog/client_registration/client-registration/#script-type-java", "text": "import io.jans.as.common.model.registration.Client ; import io.jans.as.persistence.model.Scope ; import io.jans.as.server.service.ScopeService ; import io.jans.as.server.service.external.context.DynamicClientRegistrationContext ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.client.ClientRegistrationType ; import io.jans.orm.util.ArrayHelper ; import io.jans.service.cdi.util.CdiUtil ; import org.json.JSONArray ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import java.util.Map ; public class ClientRegistration implements ClientRegistrationType { private static final Logger log = LoggerFactory . getLogger ( ClientRegistration . class ); JSONArray json_array = null ; @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { if ( ! configurationAttributes . containsKey ( \"scope_list\" )) { log . info ( \"Client registration. Initialization failed. Scope List not found.\" ); return false ; } String scope_list = configurationAttributes . get ( \"scope_list\" ). getValue2 (); json_array = new JSONArray ( scope_list ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Client registration. Initialization.\" ); log . info ( configurationAttributes . toString ()); if ( ! configurationAttributes . containsKey ( \"scope_list\" )) { log . info ( \"Client registration. Initialization failed. Scope List not found.\" ); return false ; } String scope_list = configurationAttributes . get ( \"scope_list\" ). getValue2 (); json_array = new JSONArray ( scope_list ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Client registration. Destroy.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean createClient ( Object context ) { log . info ( \"Client registration. CreateClient method\" ); DynamicClientRegistrationContext regContext = ( DynamicClientRegistrationContext ) context ; Client client = regContext . getClient (); ScopeService scopeService = CdiUtil . bean ( ScopeService . class ); String [] currentScopes = client . getScopes (); String [] newScopes = currentScopes . clone (); for ( int i = 0 ; i < json_array . length (); i ++ ) { String scopeName = ( String ) json_array . get ( i ); Scope foundScope = scopeService . getScopeById ( scopeName ); if ( foundScope == null ) { log . info ( \"Client registration. Scope not found\" ); return false ; } newScopes = ArrayHelper . addItemToStringArray ( newScopes , foundScope . getDn ()); } client . setScopes ( newScopes ); log . info ( \"Client registration. Scopes added.\" ); return true ; } @Override public boolean updateClient ( Object context ) { return true ; } // This method needs to be overridden if client is providing an SSA with HMAC @Override public String getSoftwareStatementHmacSecret ( Object context ) { return \"\" ; } // This method needs to be overridden if client is providing an SSA and RS256 validation @Override public String getSoftwareStatementJwks ( Object context ) { return \"\" ; } @Override public String getDcrHmacSecret ( Object o ) { return \"\" ; } @Override public String getDcrJwks ( Object o ) { return \"\" ; } @Override public boolean isCertValidForClient ( Object o , Object o1 ) { return false ; } @Override public boolean modifyPutResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } @Override public boolean modifyReadResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } @Override public boolean modifyPostResponse ( Object responseAsJsonObject , Object executionContext ) { return true ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/client_registration/client-registration/#sample-scripts", "text": "OpenBanking", "title": "Sample Scripts"}, {"location": "script-catalog/config_api/config-api/", "tags": ["administration", "developer", "script-catalog"], "text": "Config Api interception Script # Interface # The Config Api Interception script implements the ConfigApiType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New methods # Method header Method description authorize(self, responseAsJsonObject, context) responseAsJsonObject - is org.codehaus.jettison.json.JSONObject , you can use any method to manipulate json . context is reference of io.jans.as.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenFederation/oxauth project,) Sample script which demonstrates basic client authentication # Script Type: Python # from io.jans.as.model.jwt import Jwt from io.jans.as.model.crypto import AuthCryptoProvider from io.jans.model.custom.script.conf import CustomScriptConfiguration from io.jans.model.custom.script.type.configapi import ConfigApiType from io.jans.orm import PersistenceEntryManager from io.jans.service.cdi.util import CdiUtil from io.jans.util import StringHelper , ArrayHelper from io.jans.configapi.model.configuration import ApiAppConfiguration from org.json import JSONObject from java.lang import String from jakarta.servlet.http import HttpServletRequest from jakarta.servlet.http import HttpServletResponse class ConfigApiAuthorization ( ConfigApiType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"ConfigApiType script. Initializing ...\" print \"ConfigApiType script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"ConfigApiType script. Destroying ...\" print \"ConfigApiType script. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Returns boolean true or false depending on the process, if the client is authorized # or not. # This method is called after introspection response is ready. This method can modify introspection response. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenFederation/oxauth project, ) def authorize ( self , responseAsJsonObject , context ): print \" responseAsJsonObject: %s \" % responseAsJsonObject print \" context: %s \" % context print \"Config Authentication process\" request = context . httpRequest response = context . httpResponse print \" request = : %s \" % request print \" response = : %s \" % response appConfiguration = context . getApiAppConfiguration () customScriptConfiguration = context . getScript () issuer = context . getRequestParameters () . get ( \"ISSUER\" ) token = context . getRequestParameters () . get ( \"TOKEN\" ) method = context . getRequestParameters () . get ( \"METHOD\" ) path = context . getRequestParameters () . get ( \"PATH\" ) print \" requese2: %s \" % request print \" response2 new: %s \" % response print \"ConfigApiType.appConfiguration: %s \" % appConfiguration print \"ConfigApiType.customScriptConfiguration: %s \" % customScriptConfiguration print \"ConfigApiType.issuer: %s \" % issuer print \"ConfigApiType.token: %s \" % token print \"ConfigApiType.method: %s \" % method print \"ConfigApiType.path: %s \" % path #Example to validate method if ( \"GET\" == StringHelper . toUpperCase ( method ) ): print \"Validate method: %s \" % method if ( \"attributes\" == StringHelper . toLowerCase ( path ) ): print \"ConfigApiType.path: %s \" % path responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) print \" final responseAsJsonObject: %s \" % responseAsJsonObject return True Sample Scripts # ConfigApiInterception", "title": "Config API"}, {"location": "script-catalog/config_api/config-api/#config-api-interception-script", "text": "", "title": "Config Api interception Script"}, {"location": "script-catalog/config_api/config-api/#interface", "text": "The Config Api Interception script implements the ConfigApiType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/config_api/config-api/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/config_api/config-api/#new-methods", "text": "Method header Method description authorize(self, responseAsJsonObject, context) responseAsJsonObject - is org.codehaus.jettison.json.JSONObject , you can use any method to manipulate json . context is reference of io.jans.as.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenFederation/oxauth project,)", "title": "New methods"}, {"location": "script-catalog/config_api/config-api/#sample-script-which-demonstrates-basic-client-authentication", "text": "", "title": "Sample script which demonstrates basic client authentication"}, {"location": "script-catalog/config_api/config-api/#script-type-python", "text": "from io.jans.as.model.jwt import Jwt from io.jans.as.model.crypto import AuthCryptoProvider from io.jans.model.custom.script.conf import CustomScriptConfiguration from io.jans.model.custom.script.type.configapi import ConfigApiType from io.jans.orm import PersistenceEntryManager from io.jans.service.cdi.util import CdiUtil from io.jans.util import StringHelper , ArrayHelper from io.jans.configapi.model.configuration import ApiAppConfiguration from org.json import JSONObject from java.lang import String from jakarta.servlet.http import HttpServletRequest from jakarta.servlet.http import HttpServletResponse class ConfigApiAuthorization ( ConfigApiType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"ConfigApiType script. Initializing ...\" print \"ConfigApiType script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"ConfigApiType script. Destroying ...\" print \"ConfigApiType script. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Returns boolean true or false depending on the process, if the client is authorized # or not. # This method is called after introspection response is ready. This method can modify introspection response. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenFederation/oxauth project, ) def authorize ( self , responseAsJsonObject , context ): print \" responseAsJsonObject: %s \" % responseAsJsonObject print \" context: %s \" % context print \"Config Authentication process\" request = context . httpRequest response = context . httpResponse print \" request = : %s \" % request print \" response = : %s \" % response appConfiguration = context . getApiAppConfiguration () customScriptConfiguration = context . getScript () issuer = context . getRequestParameters () . get ( \"ISSUER\" ) token = context . getRequestParameters () . get ( \"TOKEN\" ) method = context . getRequestParameters () . get ( \"METHOD\" ) path = context . getRequestParameters () . get ( \"PATH\" ) print \" requese2: %s \" % request print \" response2 new: %s \" % response print \"ConfigApiType.appConfiguration: %s \" % appConfiguration print \"ConfigApiType.customScriptConfiguration: %s \" % customScriptConfiguration print \"ConfigApiType.issuer: %s \" % issuer print \"ConfigApiType.token: %s \" % token print \"ConfigApiType.method: %s \" % method print \"ConfigApiType.path: %s \" % path #Example to validate method if ( \"GET\" == StringHelper . toUpperCase ( method ) ): print \"Validate method: %s \" % method if ( \"attributes\" == StringHelper . toLowerCase ( path ) ): print \"ConfigApiType.path: %s \" % path responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) print \" final responseAsJsonObject: %s \" % responseAsJsonObject return True", "title": "Script Type: Python"}, {"location": "script-catalog/config_api/config-api/#sample-scripts", "text": "ConfigApiInterception", "title": "Sample Scripts"}, {"location": "script-catalog/consent_gathering/consent-gathering/", "tags": ["administration", "developer", "script-catalog", "ConsentGathering"], "text": "Overview # OAuth 2.0 allows providers to prompt users for consent before releasing their personal information to a client (application). The standard consent process is binary: approve or deny. Using the consent gathering interception script, the consent flow can be customized to meet unique business requirements, for instance to support payment authorization, where you need to present transactional information, or where you need to step-up authentication to add security. Interface # The consent gathering script implements the ConsentGathering interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def authorize(self, step, consentContext) Main consent-gather method. Must return True (if consent gathered successfully) or False (if failed). def getNextStep(self, step, context) def getStepsCount(self, context) Return total number of consent gathering steps def getPageForStep(self, step, context) Returns the consent page corresponding to the current step of consent gathering Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference Use case: Dummy Consent Gathering Form # This script has been adapted from the Gluu Server sample consent gathering script . Script Type: Python # from io.jans.model.custom.script.type.authz import ConsentGatheringType import random class ConsentGathering ( ConsentGatheringType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Consent-Gathering. Initializing ...\" print \"Consent-Gathering. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Consent-Gathering. Destroying ...\" print \"Consent-Gathering. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 # All user entered values can be access via Map<String, String> context.getPageAttributes() def authorize ( self , step , context ): print \"Consent-Gathering. Authorizing...\" if step == 1 : allowButton = context . getRequestParameters () . get ( \"authorizeForm:allowButton\" ) if ( allowButton != None ) and ( len ( allowButton ) > 0 ): print \"Consent-Gathering. Authorization success for step 1\" return True print \"Consent-Gathering. Authorization declined for step 1\" elif step == 2 : allowButton = context . getRequestParameters () . get ( \"authorizeForm:allowButton\" ) if ( allowButton != None ) and ( len ( allowButton ) > 0 ): print \"Consent-Gathering. Authorization success for step 2\" return True print \"Consent-Gathering. Authorization declined for step 2\" return False def getNextStep ( self , step , context ): return - 1 def prepareForStep ( self , step , context ): if not context . isAuthenticated (): print \"User is not authenticated. Aborting authorization flow ...\" return False if step == 2 : pageAttributes = context . getPageAttributes () # Generate random consent gathering request consentRequest = \"Requested transaction # %s approval for the amount of sum $ %s .00\" % ( random . randint ( 100000 , 1000000 ), random . randint ( 1 , 100 ) ) pageAttributes . put ( \"consent_request\" , consentRequest ) return True return True def getStepsCount ( self , context ): return 2 def getPageForStep ( self , step , context ): if step == 1 : return \"/authz/authorize.xhtml\" elif step == 2 : return \"/authz/transaction.xhtml\" return \"\" Script Type: Java # import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.authz.ConsentGatheringType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.ConsentGatheringContext ; import java.util.Map ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class ConsentGathering implements ConsentGatheringType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Initializing...\" ); log . info ( \"Consent gathering. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Initializing...\" ); log . info ( \"Consent gathering. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Destroying...\" ); log . info ( \"Consent gathering. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean authorize ( int step , Object consentContext ) { log . info ( \"Consent gathering. Authorizing...\" ); ConsentGatheringContext gatheringContext = ( ConsentGatheringContext ) consentContext ; String [] allowButton = gatheringContext . getRequestParameters (). get ( \"authorizeForm:allowButton\" ); if ( step == 1 ) { if ( allowButton != null && allowButton . length > 0 ) { log . info ( \"Consent gathering. Authorization success for step 1\" ); return true ; } log . info ( \"Consent gathering. Authorization declined for step 1\" ); } else if ( step == 2 ) { if ( allowButton != null && allowButton . length > 0 ) { log . info ( \"Consent gathering. Authorization success for step 2\" ); return true ; } log . info ( \"Consent gathering. Authorization declined for step 2\" ); } return false ; } @Override public int getNextStep ( int step , Object consentContext ) { return - 1 ; } @Override public boolean prepareForStep ( int step , Object consentContext ) { ConsentGatheringContext gatheringContext = ( ConsentGatheringContext ) consentContext ; if ( ! gatheringContext . isAuthenticated ()) { log . info ( \"User is not authenticated. Aborting authorization flow...\" ); return false ; } if ( step == 2 ) { Map < String , String > pageAttributes = gatheringContext . getPageAttributes (); String consentRequest = \"This is a random consent request\" ; pageAttributes . put ( \"consent_request\" , consentRequest ); return true ; } return false ; } @Override public int getStepsCount ( Object consentContext ) { return 2 ; } @Override public String getPageForStep ( int step , Object consentContext ) { if ( step == 1 ) { return \"/authz/authorize.xhtml\" ; } else if ( step == 2 ) { return \"return \\\"/authz/transaction.xhtml\\\"\" ; } return \"\" ; } }", "title": "Consent Gathering"}, {"location": "script-catalog/consent_gathering/consent-gathering/#overview", "text": "OAuth 2.0 allows providers to prompt users for consent before releasing their personal information to a client (application). The standard consent process is binary: approve or deny. Using the consent gathering interception script, the consent flow can be customized to meet unique business requirements, for instance to support payment authorization, where you need to present transactional information, or where you need to step-up authentication to add security.", "title": "Overview"}, {"location": "script-catalog/consent_gathering/consent-gathering/#interface", "text": "The consent gathering script implements the ConsentGathering interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/consent_gathering/consent-gathering/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/consent_gathering/consent-gathering/#new-methods", "text": "Method header Method description def authorize(self, step, consentContext) Main consent-gather method. Must return True (if consent gathered successfully) or False (if failed). def getNextStep(self, step, context) def getStepsCount(self, context) Return total number of consent gathering steps def getPageForStep(self, step, context) Returns the consent page corresponding to the current step of consent gathering", "title": "New Methods"}, {"location": "script-catalog/consent_gathering/consent-gathering/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/consent_gathering/consent-gathering/#use-case-dummy-consent-gathering-form", "text": "This script has been adapted from the Gluu Server sample consent gathering script .", "title": "Use case: Dummy Consent Gathering Form"}, {"location": "script-catalog/consent_gathering/consent-gathering/#script-type-python", "text": "from io.jans.model.custom.script.type.authz import ConsentGatheringType import random class ConsentGathering ( ConsentGatheringType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Consent-Gathering. Initializing ...\" print \"Consent-Gathering. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Consent-Gathering. Destroying ...\" print \"Consent-Gathering. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 # All user entered values can be access via Map<String, String> context.getPageAttributes() def authorize ( self , step , context ): print \"Consent-Gathering. Authorizing...\" if step == 1 : allowButton = context . getRequestParameters () . get ( \"authorizeForm:allowButton\" ) if ( allowButton != None ) and ( len ( allowButton ) > 0 ): print \"Consent-Gathering. Authorization success for step 1\" return True print \"Consent-Gathering. Authorization declined for step 1\" elif step == 2 : allowButton = context . getRequestParameters () . get ( \"authorizeForm:allowButton\" ) if ( allowButton != None ) and ( len ( allowButton ) > 0 ): print \"Consent-Gathering. Authorization success for step 2\" return True print \"Consent-Gathering. Authorization declined for step 2\" return False def getNextStep ( self , step , context ): return - 1 def prepareForStep ( self , step , context ): if not context . isAuthenticated (): print \"User is not authenticated. Aborting authorization flow ...\" return False if step == 2 : pageAttributes = context . getPageAttributes () # Generate random consent gathering request consentRequest = \"Requested transaction # %s approval for the amount of sum $ %s .00\" % ( random . randint ( 100000 , 1000000 ), random . randint ( 1 , 100 ) ) pageAttributes . put ( \"consent_request\" , consentRequest ) return True return True def getStepsCount ( self , context ): return 2 def getPageForStep ( self , step , context ): if step == 1 : return \"/authz/authorize.xhtml\" elif step == 2 : return \"/authz/transaction.xhtml\" return \"\"", "title": "Script Type: Python"}, {"location": "script-catalog/consent_gathering/consent-gathering/#script-type-java", "text": "import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.authz.ConsentGatheringType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.ConsentGatheringContext ; import java.util.Map ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class ConsentGathering implements ConsentGatheringType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Initializing...\" ); log . info ( \"Consent gathering. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Initializing...\" ); log . info ( \"Consent gathering. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Consent gathering. Destroying...\" ); log . info ( \"Consent gathering. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean authorize ( int step , Object consentContext ) { log . info ( \"Consent gathering. Authorizing...\" ); ConsentGatheringContext gatheringContext = ( ConsentGatheringContext ) consentContext ; String [] allowButton = gatheringContext . getRequestParameters (). get ( \"authorizeForm:allowButton\" ); if ( step == 1 ) { if ( allowButton != null && allowButton . length > 0 ) { log . info ( \"Consent gathering. Authorization success for step 1\" ); return true ; } log . info ( \"Consent gathering. Authorization declined for step 1\" ); } else if ( step == 2 ) { if ( allowButton != null && allowButton . length > 0 ) { log . info ( \"Consent gathering. Authorization success for step 2\" ); return true ; } log . info ( \"Consent gathering. Authorization declined for step 2\" ); } return false ; } @Override public int getNextStep ( int step , Object consentContext ) { return - 1 ; } @Override public boolean prepareForStep ( int step , Object consentContext ) { ConsentGatheringContext gatheringContext = ( ConsentGatheringContext ) consentContext ; if ( ! gatheringContext . isAuthenticated ()) { log . info ( \"User is not authenticated. Aborting authorization flow...\" ); return false ; } if ( step == 2 ) { Map < String , String > pageAttributes = gatheringContext . getPageAttributes (); String consentRequest = \"This is a random consent request\" ; pageAttributes . put ( \"consent_request\" , consentRequest ); return true ; } return false ; } @Override public int getStepsCount ( Object consentContext ) { return 2 ; } @Override public String getPageForStep ( int step , Object consentContext ) { if ( step == 1 ) { return \"/authz/authorize.xhtml\" ; } else if ( step == 2 ) { return \"return \\\"/authz/transaction.xhtml\\\"\" ; } return \"\" ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/discovery/discovery/", "tags": ["administration", "developer", "script-catalog"], "text": "Discovery Script # Overview # This script is used to modify the response of the OpenID well-known discovery endpoint, /.well-known/openid-configuration . The specification for this endpoint is defined in the OpenID Connect documentation . Interface # Methods # The discovery interception script extends the base script type with the init , destroy and getApiVersion methods: Inherited Methods Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . The discovery interception script also adds the following method(s): Method def modifyResponse(self, responseAsJsonObject, context) Method Paramater responseAsJsonObject is org.json.JSONObject context is io.jans.as.server.model.common.ExecutionContext Objects # Definitions of all objects used in the script Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference Common Use Case # Script Type: Python # Add custom values to the OpenID configuration endpoint # from io.jans.model.custom.script.type.discovery import DiscoveryType from java.lang import String class Discovery ( DiscoveryType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Custom Discovery script. Initializing ...\" print \"Custom Discovery script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Custom Discovery script. Destroying ...\" print \"Custom Discovery script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply Discovery method, false - ignore it. # This method is called after Discovery response is ready. This method can modify Discovery response. # Note : # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.server.model.common.ExecutionContext (in https://github.com/JanssenProject project, ) def modifyResponse ( self , responseAsJsonObject , context ): print \"Custom - Inside modifyResponse method of Discovery script ....\" # Add a value to Discovery Response responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) # Filter out a value from Discovery Response responseAsJsonObject . remove ( \"pushed_authorization_request_endpoint\" ) # Get an IP Address of the Client making the request responseAsJsonObject . accumulate ( \"Client IP Address\" , context . getHttpRequest () . getHeader ( \"X-Forwarded-For\" )) return True Script Type: Python # Add custom values, remove values, and add client's IP request # from io.jans.model.custom.script.type.discovery import DiscoveryType from java.lang import String class Discovery ( DiscoveryType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Custom Discovery script. Initializing ...\" print \"Custom Discovery script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Custom Discovery script. Destroying ...\" print \"Custom Discovery script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def modifyResponse ( self , responseAsJsonObject , context ): print \"Custom - Inside modifyResponse method of Discovery script ....\" # Add a value to Discovery Response responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) # Filter out a value from Discovery Response responseAsJsonObject . remove ( \"pushed_authorization_request_endpoint\" ) # Get an IP Address of the Client making the request responseAsJsonObject . accumulate ( \"Client IP Address\" , context . getHttpRequest () . getHeader ( \"X-Forwarded-For\" )) return True Script Type: Java # Add custom values, remove values, and add client's IP request # import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.discovery.DiscoveryType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.model.common.ExecutionContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import org.json.JSONObject ; import java.util.Map ; public class Discovery implements DiscoveryType { private static final Logger log = LoggerFactory . getLogger ( Discovery . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Discovery Java custom script\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Discovery Java custom script\" ); scriptLogger . info ( \"Discovery Java script. Initializing ...\" ); scriptLogger . info ( \"Discovery Java script. Initialized successfully\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Destroy of Discovery Java custom script\" ); scriptLogger . info ( \"Discovery Java script. Destroying ...\" ); scriptLogger . info ( \"Discovery Java script. Destroyed successfully\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { scriptLogger . info ( \"Custom Java - Inside modifyResponse method of Discovery script ....\" ); JSONObject response = ( JSONObject ) responseAsJsonObject ; ExecutionContext ctx = ( ExecutionContext ) context ; // Add a value to Discovery Response response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); // Filter out a value from Discovery Response response . remove ( \"pushed_authorization_request_endpoint\" ); // Get an IP Address of the Client making the request response . accumulate ( \"Client IP Address\" , ctx . getHttpRequest (). getHeader ( \"X-Forwarded-For\" )); return true ; } }", "title": "OpenID Configuration"}, {"location": "script-catalog/discovery/discovery/#discovery-script", "text": "", "title": "Discovery Script"}, {"location": "script-catalog/discovery/discovery/#overview", "text": "This script is used to modify the response of the OpenID well-known discovery endpoint, /.well-known/openid-configuration . The specification for this endpoint is defined in the OpenID Connect documentation .", "title": "Overview"}, {"location": "script-catalog/discovery/discovery/#interface", "text": "", "title": "Interface"}, {"location": "script-catalog/discovery/discovery/#methods", "text": "The discovery interception script extends the base script type with the init , destroy and getApiVersion methods: Inherited Methods Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . The discovery interception script also adds the following method(s): Method def modifyResponse(self, responseAsJsonObject, context) Method Paramater responseAsJsonObject is org.json.JSONObject context is io.jans.as.server.model.common.ExecutionContext", "title": "Methods"}, {"location": "script-catalog/discovery/discovery/#objects", "text": "Definitions of all objects used in the script", "title": "Objects"}, {"location": "script-catalog/discovery/discovery/#objects_1", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/discovery/discovery/#common-use-case", "text": "", "title": "Common Use Case"}, {"location": "script-catalog/discovery/discovery/#script-type-python", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/discovery/discovery/#add-custom-values-to-the-openid-configuration-endpoint", "text": "from io.jans.model.custom.script.type.discovery import DiscoveryType from java.lang import String class Discovery ( DiscoveryType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Custom Discovery script. Initializing ...\" print \"Custom Discovery script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Custom Discovery script. Destroying ...\" print \"Custom Discovery script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply Discovery method, false - ignore it. # This method is called after Discovery response is ready. This method can modify Discovery response. # Note : # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.server.model.common.ExecutionContext (in https://github.com/JanssenProject project, ) def modifyResponse ( self , responseAsJsonObject , context ): print \"Custom - Inside modifyResponse method of Discovery script ....\" # Add a value to Discovery Response responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) # Filter out a value from Discovery Response responseAsJsonObject . remove ( \"pushed_authorization_request_endpoint\" ) # Get an IP Address of the Client making the request responseAsJsonObject . accumulate ( \"Client IP Address\" , context . getHttpRequest () . getHeader ( \"X-Forwarded-For\" )) return True", "title": "Add custom values to the OpenID configuration endpoint"}, {"location": "script-catalog/discovery/discovery/#script-type-python_1", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/discovery/discovery/#add-custom-values-remove-values-and-add-clients-ip-request", "text": "from io.jans.model.custom.script.type.discovery import DiscoveryType from java.lang import String class Discovery ( DiscoveryType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Custom Discovery script. Initializing ...\" print \"Custom Discovery script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Custom Discovery script. Destroying ...\" print \"Custom Discovery script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def modifyResponse ( self , responseAsJsonObject , context ): print \"Custom - Inside modifyResponse method of Discovery script ....\" # Add a value to Discovery Response responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) # Filter out a value from Discovery Response responseAsJsonObject . remove ( \"pushed_authorization_request_endpoint\" ) # Get an IP Address of the Client making the request responseAsJsonObject . accumulate ( \"Client IP Address\" , context . getHttpRequest () . getHeader ( \"X-Forwarded-For\" )) return True", "title": "Add custom values, remove values, and add client's IP request"}, {"location": "script-catalog/discovery/discovery/#script-type-java", "text": "", "title": "Script Type: Java"}, {"location": "script-catalog/discovery/discovery/#add-custom-values-remove-values-and-add-clients-ip-request_1", "text": "import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.discovery.DiscoveryType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.model.common.ExecutionContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import org.json.JSONObject ; import java.util.Map ; public class Discovery implements DiscoveryType { private static final Logger log = LoggerFactory . getLogger ( Discovery . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Discovery Java custom script\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Discovery Java custom script\" ); scriptLogger . info ( \"Discovery Java script. Initializing ...\" ); scriptLogger . info ( \"Discovery Java script. Initialized successfully\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Destroy of Discovery Java custom script\" ); scriptLogger . info ( \"Discovery Java script. Destroying ...\" ); scriptLogger . info ( \"Discovery Java script. Destroyed successfully\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { scriptLogger . info ( \"Custom Java - Inside modifyResponse method of Discovery script ....\" ); JSONObject response = ( JSONObject ) responseAsJsonObject ; ExecutionContext ctx = ( ExecutionContext ) context ; // Add a value to Discovery Response response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); // Filter out a value from Discovery Response response . remove ( \"pushed_authorization_request_endpoint\" ); // Get an IP Address of the Client making the request response . accumulate ( \"Client IP Address\" , ctx . getHttpRequest (). getHeader ( \"X-Forwarded-For\" )); return true ; } }", "title": "Add custom values, remove values, and add client's IP request"}, {"location": "script-catalog/discovery/discovery/", "text": "Discovery Script Guide # Overview # The Authorization Server Metadata spec RFC8414 (also known as OAuth Discovery) defines a format for clients to use to look up the information needed to interact with a particular OAuth server. This includes things like:- - finding the authorization endpoint, - listing the supported scopes and client authentication mechanisms. The \"OpenID Connect Discovery 1.0\" defines the metadata in such a way that is compatible with OpenID Connect Discovery while being applicable to a wider set of OAuth 2.0 use cases. This is intentionally parallel to the way that \"OAuth 2.0 Dynamic Client Registration Protocol\" RFC7591 defines the dynamic client registration mechanisms \"OpenID Connect Dynamic Client Registration 1.0 OpenID.Registration so that is compatible with it. The metadata for an authorization server is retrieved from a know location as a JSON object RFC8259 , which defines its endpoint locations and authorization server capabilities. This metadata can be passed either:- - in a self-asserted fashion from the server origin via HTTPS - or as a set of signed metadata values represented as claims in a JSON Web Token JWT . In the JWT case, the issuer is vouching for the validity of the data coming from the authorization server. This is analogous to the role that the Software Statement plays in OAuth Dynamic Client Registration RFC7591. Note: The means by which the client chooses an authorization server is out of scope. In some cases, the issuer identifier may be manually configured into the client. In other cases, it may be dynamically discovered, for instance, through the use of WebFinger . Discovery script allows to modify response of OpenID Connect Discovery RFC8414 . Methods # The discovery interception script extends the base script type with the methods - Method Method description def init(self, customScript, configurationAttributes) Inherited Method This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) Inherited Method This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) Inherited Method The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 def modifyResponse(self, responseAsJsonObject, context) This method is called after discovery response is ready. This method can modify discovery response. responseAsJsonObject is org.codehaus.jettison.json.JSONObject context is io.jans.as.server.model.common.ExecutionContext The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . configurationAttributes = new HashMap < String , SimpleCustomProperty > () ; configurationAttributes . put ( \"Location Type\" , new SimpleCustomProperty ( \"location_type\" , \"MySQL\" , \"Storage Location for the script\" )) ; Snippet # # Returns boolean , true - apply discovery method , false - ignore it . # This method is called after discovery response is ready . This method can modify discovery response . # Note : # responseAsJsonObject - is org . codehaus . jettison . json . JSONObject , you can use any method to manipulate json # context is reference of io . jans . as . server . model . common . ExecutionContext ( in https : // github . com / JanssenProject project ) def modifyResponse ( self , responseAsJsonObject , context ) : responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True Common Use Cases # Script Type: Python # Add a value (Client IP Address) and Filter out a value from Discovery Response # The sample code snippet shows how to add and filter out a value from Discovery Response. Script Type: Java # Add a value (Client IP Address) and Filter out a value from Discovery Response # The sample code snippet shows how to add and filter out a value from Discovery Response.", "title": "Discovery Script Guide"}, {"location": "script-catalog/discovery/discovery/#discovery-script-guide", "text": "", "title": "Discovery Script Guide"}, {"location": "script-catalog/discovery/discovery/#overview", "text": "The Authorization Server Metadata spec RFC8414 (also known as OAuth Discovery) defines a format for clients to use to look up the information needed to interact with a particular OAuth server. This includes things like:- - finding the authorization endpoint, - listing the supported scopes and client authentication mechanisms. The \"OpenID Connect Discovery 1.0\" defines the metadata in such a way that is compatible with OpenID Connect Discovery while being applicable to a wider set of OAuth 2.0 use cases. This is intentionally parallel to the way that \"OAuth 2.0 Dynamic Client Registration Protocol\" RFC7591 defines the dynamic client registration mechanisms \"OpenID Connect Dynamic Client Registration 1.0 OpenID.Registration so that is compatible with it. The metadata for an authorization server is retrieved from a know location as a JSON object RFC8259 , which defines its endpoint locations and authorization server capabilities. This metadata can be passed either:- - in a self-asserted fashion from the server origin via HTTPS - or as a set of signed metadata values represented as claims in a JSON Web Token JWT . In the JWT case, the issuer is vouching for the validity of the data coming from the authorization server. This is analogous to the role that the Software Statement plays in OAuth Dynamic Client Registration RFC7591. Note: The means by which the client chooses an authorization server is out of scope. In some cases, the issuer identifier may be manually configured into the client. In other cases, it may be dynamically discovered, for instance, through the use of WebFinger . Discovery script allows to modify response of OpenID Connect Discovery RFC8414 .", "title": "Overview"}, {"location": "script-catalog/discovery/discovery/#methods", "text": "The discovery interception script extends the base script type with the methods - Method Method description def init(self, customScript, configurationAttributes) Inherited Method This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) Inherited Method This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) Inherited Method The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 def modifyResponse(self, responseAsJsonObject, context) This method is called after discovery response is ready. This method can modify discovery response. responseAsJsonObject is org.codehaus.jettison.json.JSONObject context is io.jans.as.server.model.common.ExecutionContext The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . configurationAttributes = new HashMap < String , SimpleCustomProperty > () ; configurationAttributes . put ( \"Location Type\" , new SimpleCustomProperty ( \"location_type\" , \"MySQL\" , \"Storage Location for the script\" )) ;", "title": "Methods"}, {"location": "script-catalog/discovery/discovery/#snippet", "text": "# Returns boolean , true - apply discovery method , false - ignore it . # This method is called after discovery response is ready . This method can modify discovery response . # Note : # responseAsJsonObject - is org . codehaus . jettison . json . JSONObject , you can use any method to manipulate json # context is reference of io . jans . as . server . model . common . ExecutionContext ( in https : // github . com / JanssenProject project ) def modifyResponse ( self , responseAsJsonObject , context ) : responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True", "title": "Snippet"}, {"location": "script-catalog/discovery/discovery/#common-use-cases", "text": "", "title": "Common Use Cases"}, {"location": "script-catalog/discovery/discovery/#script-type-python", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/discovery/discovery/#add-a-value-client-ip-address-and-filter-out-a-value-from-discovery-response", "text": "The sample code snippet shows how to add and filter out a value from Discovery Response.", "title": "Add a value (Client IP Address) and Filter out a value from Discovery Response"}, {"location": "script-catalog/discovery/discovery/#script-type-java", "text": "", "title": "Script Type: Java"}, {"location": "script-catalog/discovery/discovery/#add-a-value-client-ip-address-and-filter-out-a-value-from-discovery-response_1", "text": "The sample code snippet shows how to add and filter out a value from Discovery Response.", "title": "Add a value (Client IP Address) and Filter out a value from Discovery Response"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/", "tags": ["administration", "developer", "script-catalog", "DynamicScope"], "text": "Overview # The dynamic scope custom script allows the authorization server to generate a list of claims (and their values) on the fly, depending on circumstances such as the ID of the client requesting it, authenticated user's session parameters, values of other users' attributes, results of some calculations implementing specific business logic and/or requests to remote APIs or databases. Claims are then returned the usual way in a response to a call to the /userinfo endpoint. Interface # The dynamic scope script implements the DynamicScopeType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def update(self, dynamicScopeContext, configurationAttributes) Main dynamic scope method. Peforms any needed logic, updates JSON Web Token and returns True if dynamic scope was added successfully, false otherwise. def getSupportedClaims(self, configurationAttributes) Returns an array of claims that are allowed to be added by the custom script Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference dynamicScopeContext Reference Use case: Add dynamic scope with the org_name claim # This script has been adapted from the Gluu Server sample dynamic scope script Script Type: Python # from java.util import Arrays , ArrayList from io.jans.model.custom.script.type.scope import DynamicScopeType class DynamicScope ( DynamicScopeType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"Dynamic scope. Initialization\" print \"Dynamic scope. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Dynamic scope. Destroy\" print \"Dynamic scope. Destroyed successfully\" return True def update ( self , dynamicScopeContext , configurationAttributes ): print \"Dynamic scope. Update method\" dynamicScopes = dynamicScopeContext . getDynamicScopes () user = dynamicScopeContext . getUser () jsonToken = dynamicScopeContext . getJsonToken () claims = jsonToken . getClaims () # Iterate through list of dynamic scopes in order to add custom scopes if needed print \"Dynamic scope. Dynamic scopes:\" , dynamicScopes for dynamicScope in dynamicScopes : # Add organization name if there is scope = org_name if ( StringHelper . equalsIgnoreCase ( dynamicScope , \"org_name\" )): claims . setClaim ( \"org_name\" , \"Test Value\" ) continue # Add work phone if there is scope = work_phone return True def getApiVersion ( self ): return 1 def getSupportedClaims ( self , configurationAttributes ): return Arrays . asList ( \"org_name\" ) Script Type: Java # import java.util.List ; import java.util.Map ; import java.util.Arrays ; import java.util.ArrayList ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.model.custom.script.type.scope.DynamicScopeType ; import io.jans.as.server.service.external.context.DynamicScopeExternalContext ; import io.jans.as.model.token.JsonWebResponse ; import io.jans.as.model.jwt.JwtClaims ; import io.jans.util.StringHelper ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class DynamicScope implements DynamicScopeType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Initializing...\" ); log . info ( \"Dynamic Scope. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Initializing...\" ); log . info ( \"Dynamic Scope. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Destroying...\" ); log . info ( \"Dynamic Scope. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean update ( Object dynamicScopeContext , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Updating...\" ); DynamicScopeExternalContext dynamicContext = ( DynamicScopeExternalContext ) dynamicScopeContext ; ArrayList < String > dynamicScopes = ( ArrayList < String > ) dynamicContext . getDynamicScopes (); JsonWebResponse jwt = dynamicContext . getJsonWebResponse (); JwtClaims claims = jwt . getClaims (); log . info ( \"Dynamic Scope. Dynamic scopes: \" + dynamicScopes . toString ()); for ( String dynamicScope : dynamicScopes ) { if ( StringHelper . equalsIgnoreCase ( dynamicScope , \"org_name\" )) { claims . setClaim ( \"org_name\" , \"Test Value\" ); continue ; } } return true ; } @Override public List < String > getSupportedClaims ( Map < String , SimpleCustomProperty > configurationAttributes ) { return Arrays . asList ( \"org_name\" ); } } Sample Scripts # Dynamic Permission MemberOf Attribute Organization Name Session Parameter Work Phone", "title": "Dynamic Scope"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#overview", "text": "The dynamic scope custom script allows the authorization server to generate a list of claims (and their values) on the fly, depending on circumstances such as the ID of the client requesting it, authenticated user's session parameters, values of other users' attributes, results of some calculations implementing specific business logic and/or requests to remote APIs or databases. Claims are then returned the usual way in a response to a call to the /userinfo endpoint.", "title": "Overview"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#interface", "text": "The dynamic scope script implements the DynamicScopeType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#new-methods", "text": "Method header Method description def update(self, dynamicScopeContext, configurationAttributes) Main dynamic scope method. Peforms any needed logic, updates JSON Web Token and returns True if dynamic scope was added successfully, false otherwise. def getSupportedClaims(self, configurationAttributes) Returns an array of claims that are allowed to be added by the custom script", "title": "New Methods"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference dynamicScopeContext Reference", "title": "Objects"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#use-case-add-dynamic-scope-with-the-org_name-claim", "text": "This script has been adapted from the Gluu Server sample dynamic scope script", "title": "Use case: Add dynamic scope with the org_name claim"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#script-type-python", "text": "from java.util import Arrays , ArrayList from io.jans.model.custom.script.type.scope import DynamicScopeType class DynamicScope ( DynamicScopeType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"Dynamic scope. Initialization\" print \"Dynamic scope. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Dynamic scope. Destroy\" print \"Dynamic scope. Destroyed successfully\" return True def update ( self , dynamicScopeContext , configurationAttributes ): print \"Dynamic scope. Update method\" dynamicScopes = dynamicScopeContext . getDynamicScopes () user = dynamicScopeContext . getUser () jsonToken = dynamicScopeContext . getJsonToken () claims = jsonToken . getClaims () # Iterate through list of dynamic scopes in order to add custom scopes if needed print \"Dynamic scope. Dynamic scopes:\" , dynamicScopes for dynamicScope in dynamicScopes : # Add organization name if there is scope = org_name if ( StringHelper . equalsIgnoreCase ( dynamicScope , \"org_name\" )): claims . setClaim ( \"org_name\" , \"Test Value\" ) continue # Add work phone if there is scope = work_phone return True def getApiVersion ( self ): return 1 def getSupportedClaims ( self , configurationAttributes ): return Arrays . asList ( \"org_name\" )", "title": "Script Type: Python"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#script-type-java", "text": "import java.util.List ; import java.util.Map ; import java.util.Arrays ; import java.util.ArrayList ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.model.custom.script.type.scope.DynamicScopeType ; import io.jans.as.server.service.external.context.DynamicScopeExternalContext ; import io.jans.as.model.token.JsonWebResponse ; import io.jans.as.model.jwt.JwtClaims ; import io.jans.util.StringHelper ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class DynamicScope implements DynamicScopeType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Initializing...\" ); log . info ( \"Dynamic Scope. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Initializing...\" ); log . info ( \"Dynamic Scope. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Destroying...\" ); log . info ( \"Dynamic Scope. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean update ( Object dynamicScopeContext , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Dynamic Scope. Updating...\" ); DynamicScopeExternalContext dynamicContext = ( DynamicScopeExternalContext ) dynamicScopeContext ; ArrayList < String > dynamicScopes = ( ArrayList < String > ) dynamicContext . getDynamicScopes (); JsonWebResponse jwt = dynamicContext . getJsonWebResponse (); JwtClaims claims = jwt . getClaims (); log . info ( \"Dynamic Scope. Dynamic scopes: \" + dynamicScopes . toString ()); for ( String dynamicScope : dynamicScopes ) { if ( StringHelper . equalsIgnoreCase ( dynamicScope , \"org_name\" )) { claims . setClaim ( \"org_name\" , \"Test Value\" ); continue ; } } return true ; } @Override public List < String > getSupportedClaims ( Map < String , SimpleCustomProperty > configurationAttributes ) { return Arrays . asList ( \"org_name\" ); } }", "title": "Script Type: Java"}, {"location": "script-catalog/dynamic_scope/dynamic-scope/#sample-scripts", "text": "Dynamic Permission MemberOf Attribute Organization Name Session Parameter Work Phone", "title": "Sample Scripts"}, {"location": "script-catalog/end_session/end-session/", "tags": ["administration", "developer", "script-catalog", "EndSession"], "text": "Overview # End Session scripts allows the administrator to modify HTML response for OpenID Connect Frontchannel logout ( spec ). Interface # The end session script implements the EndSessionType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def getFrontchannelHtml(self, context) Returns string, it must be valid HTML (with iframes according to specification ). This method is called on /end_session after actual session is killed and authorization server constructs HTML to return to RP. Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Reference Use case: Dummy Logout Page # This script has been adapted from the Gluu Server sample end session script . Note The example script is a proof of concept, as the getFrontchannelHtml() must return an actual HTML string. Script Type: Python # from io.jans.model.custom.script.type.logout import EndSessionType from java.lang import String class EndSession ( EndSessionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"EndSession script. Initializing ...\" print \"EndSession script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"EndSession script. Destroying ...\" print \"EndSession script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Must return an HTML string def getFrontchannelHtml ( self , context ): return \"\" Script Type: Java # import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.logout.EndSessionType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.EndSessionContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class EndSession implements EndSessionType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Destroying...\" ); log . info ( \"ROPC Script. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public String getFrontchannelHtml ( Object context ) { EndSessionContext endSessionContext = ( EndSessionContext ) context ; // Must return a real HTML string as per OIDC front channel logout spec return \"\" ; } }", "title": "End Session"}, {"location": "script-catalog/end_session/end-session/#overview", "text": "End Session scripts allows the administrator to modify HTML response for OpenID Connect Frontchannel logout ( spec ).", "title": "Overview"}, {"location": "script-catalog/end_session/end-session/#interface", "text": "The end session script implements the EndSessionType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/end_session/end-session/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/end_session/end-session/#new-methods", "text": "Method header Method description def getFrontchannelHtml(self, context) Returns string, it must be valid HTML (with iframes according to specification ). This method is called on /end_session after actual session is killed and authorization server constructs HTML to return to RP.", "title": "New Methods"}, {"location": "script-catalog/end_session/end-session/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Reference", "title": "Objects"}, {"location": "script-catalog/end_session/end-session/#use-case-dummy-logout-page", "text": "This script has been adapted from the Gluu Server sample end session script . Note The example script is a proof of concept, as the getFrontchannelHtml() must return an actual HTML string.", "title": "Use case: Dummy Logout Page"}, {"location": "script-catalog/end_session/end-session/#script-type-python", "text": "from io.jans.model.custom.script.type.logout import EndSessionType from java.lang import String class EndSession ( EndSessionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"EndSession script. Initializing ...\" print \"EndSession script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"EndSession script. Destroying ...\" print \"EndSession script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Must return an HTML string def getFrontchannelHtml ( self , context ): return \"\"", "title": "Script Type: Python"}, {"location": "script-catalog/end_session/end-session/#script-type-java", "text": "import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.logout.EndSessionType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.EndSessionContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class EndSession implements EndSessionType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Destroying...\" ); log . info ( \"ROPC Script. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public String getFrontchannelHtml ( Object context ) { EndSessionContext endSessionContext = ( EndSessionContext ) context ; // Must return a real HTML string as per OIDC front channel logout spec return \"\" ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/id_generator/id-generator/", "tags": ["administration", "developer", "script-catalog", "IdGenerator"], "text": "Overview # By default Janssen Auth Server uses an internal method to generate unique identifiers for new person/client, etc. entries. In most cases the format of the ID is: '!' + idType.getInum() + '!' + four_random_HEX_characters + '.' + four_random_HEX_characters. The ID generation script enables an admin to implement custom ID generation rules. Interface # The ID Generator script implements the IdGeneratorType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def generateId(self, appId, idType, idPrefix, configurationAttributes) appId is application ID, idType is ID Type, idPrefix is ID Prefix Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes Use case: Sample ID generator # This script has been adapted from the Gluu Server sample ID generator script . Script Type: Python # from io.jans.model.custom.script.type.id import IdGeneratorType import java class IdGenerator ( IdGeneratorType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"Id generator. Initialization\" print \"Id generator. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Id generator. Destroy\" print \"Id generator. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Id generator init method # appId is application Id # idType is Id Type # idPrefix is Id Prefix def generateId ( self , appId , idType , idPrefix , configurationAttributes ): print \"Id generator. Generate Id\" print \"Id generator. Generate Id. AppId: '\" , appId , \"', IdType: '\" , idType , \"', IdPrefix: '\" , idPrefix , \"'\" # Return None or empty string to trigger default Id generation method return None Script Type: Java # import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.id.IdGeneratorType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class EndSession implements EndSessionType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Initializing...\" ); log . info ( \"ID Generator. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Initializing...\" ); log . info ( \"ID Generator. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Destroying...\" ); log . info ( \"ID Generator. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public String generateId ( String appId , String idType , String idPrefix , Map < String SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Generate Id\" ); // Return None or empty string to trigger default Id generation method return \"\" ; } }", "title": "ID Generator"}, {"location": "script-catalog/id_generator/id-generator/#overview", "text": "By default Janssen Auth Server uses an internal method to generate unique identifiers for new person/client, etc. entries. In most cases the format of the ID is: '!' + idType.getInum() + '!' + four_random_HEX_characters + '.' + four_random_HEX_characters. The ID generation script enables an admin to implement custom ID generation rules.", "title": "Overview"}, {"location": "script-catalog/id_generator/id-generator/#interface", "text": "The ID Generator script implements the IdGeneratorType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/id_generator/id-generator/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/id_generator/id-generator/#new-methods", "text": "Method header Method description def generateId(self, appId, idType, idPrefix, configurationAttributes) appId is application ID, idType is ID Type, idPrefix is ID Prefix", "title": "New Methods"}, {"location": "script-catalog/id_generator/id-generator/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes", "title": "Objects"}, {"location": "script-catalog/id_generator/id-generator/#use-case-sample-id-generator", "text": "This script has been adapted from the Gluu Server sample ID generator script .", "title": "Use case: Sample ID generator"}, {"location": "script-catalog/id_generator/id-generator/#script-type-python", "text": "from io.jans.model.custom.script.type.id import IdGeneratorType import java class IdGenerator ( IdGeneratorType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"Id generator. Initialization\" print \"Id generator. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Id generator. Destroy\" print \"Id generator. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Id generator init method # appId is application Id # idType is Id Type # idPrefix is Id Prefix def generateId ( self , appId , idType , idPrefix , configurationAttributes ): print \"Id generator. Generate Id\" print \"Id generator. Generate Id. AppId: '\" , appId , \"', IdType: '\" , idType , \"', IdPrefix: '\" , idPrefix , \"'\" # Return None or empty string to trigger default Id generation method return None", "title": "Script Type: Python"}, {"location": "script-catalog/id_generator/id-generator/#script-type-java", "text": "import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.id.IdGeneratorType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class EndSession implements EndSessionType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Initializing...\" ); log . info ( \"ID Generator. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Initializing...\" ); log . info ( \"ID Generator. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Destroying...\" ); log . info ( \"ID Generator. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public String generateId ( String appId , String idType , String idPrefix , Map < String SimpleCustomProperty > configurationAttributes ) { log . info ( \"ID Generator. Generate Id\" ); // Return None or empty string to trigger default Id generation method return \"\" ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/introspection/interception-scripts-debug/", "tags": ["administration", "developer"], "text": "Setup # For development the kubernetes setup must be local and accessible to the debug server address. The following steps will walk you trough a setup using Minikube with docker driver, and ksync for syncing the files between local, and the container. The following instructions assume a fresh ubuntu 20.04, however the setup can be done on a different operating systems such as macOS or Windows. System Requirements # The minimum system requirement for running all jans services are 8GB RAM , 4 CPU , and 50GB disk . This can be dropped to 4GB RAM , 4CPU and 20GB disk space if operating with required services auth-server, and LDAP. Setup Minikube # Install Docker 18.09 or higher. For other operating systems follow the appropriate docs . Install minikube , but do not start it yet. Install kubectl . Once Minikube is installed start it with the docker driver. minikube start --driver = docker If not automatically set configure kubectl to use the cluster: kubectl config use-context minikube Enable ingress on minikube minikube addons enable ingress Install Janssen # Install Helm3 Install Janssen helm repo add jans https://janssenproject.github.io/jans-cloud-native/charts kubectl create ns jans helm install jans-auth jans/jans -n jans --set global.lbIp = \" $( minikube ip ) \" --set global.provisioner = \"k8s.io/minikube-hostpath\" --devel Install Ksync # Once Janssen is fully running we want to create an active sync between a local folder, and the folder that will hold the interception scripts inside the auth server container. Create a folder that will hold the interception script inside the auth server container. Place the namespace where jans is installed in the env JANS_NAMESPACE and execute: JANS_NAMESPACE = <jans-namespace> for pod in $( kubectl get pods -n $JANS_NAMESPACE --selector = APP_NAME = auth-server --output = jsonpath ={ .items..metadata.name } ) ; do kubectl exec -ti $pod -n $JANS_NAMESPACE -- mkdir -p /deploy/interception-scripts-ksync done Install ksync curl https://ksync.github.io/gimme-that/gimme.sh | bash Initialize ksync ksync init -n <jans-namespace> Start ksync. ksync watch -n <jans-namespace> & Open a new terminal and create a folder called interception-scripts-ksync mkdir -p $( pwd ) /interception-scripts-ksync Create a spec to start syncing folders between the local system and auth server container. ksync create --selector = APP_NAME = auth-server $( pwd ) /interception-scripts-ksync /deploy/interception-scripts-ksync -n <jans-namespace> Check the status. Also check the terminal where the watch command is running. ksync get 1. Move the interception script to the local folder $(pwd)/interception-scripts-ksync . In the below example we copied the following script as basic.py : # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2016, Janssen # # Author: Yuriy Movchan # from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper import java class PersonAuthentication ( PersonAuthenticationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Basic. Initialization\" print \"Basic. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Basic. Destroy\" print \"Basic. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 def isValidAuthenticationMethod ( self , usageType , configurationAttributes ): return True def getAlternativeAuthenticationMethod ( self , usageType , configurationAttributes ): return None def authenticate ( self , configurationAttributes , requestParameters , step ): authenticationService = CdiUtil . bean ( AuthenticationService ) if ( step == 1 ): print \"Basic. Authenticate for step 1\" identity = CdiUtil . bean ( Identity ) credentials = identity . getCredentials () user_name = credentials . getUsername () user_password = credentials . getPassword () logged_in = False if ( StringHelper . isNotEmptyString ( user_name ) and StringHelper . isNotEmptyString ( user_password )): logged_in = authenticationService . authenticate ( user_name , user_password ) if ( not logged_in ): return False return True else : return False def prepareForStep ( self , configurationAttributes , requestParameters , step ): if ( step == 1 ): print \"Basic. Prepare for Step 1\" return True else : return False def getExtraParametersForStep ( self , configurationAttributes , step ): return None def getCountAuthenticationSteps ( self , configurationAttributes ): return 1 def getPageForStep ( self , configurationAttributes , step ): return \"\" def getNextStep ( self , configurationAttributes , requestParameters , step ): return - 1 def getLogoutExternalUrl ( self , configurationAttributes , requestParameters ): print \"Get external logout URL call\" return None def logout ( self , configurationAttributes , requestParameters ): return True Install an IDE # The IDE can be of choice but must contain PyDev. We chose Liclipse for this demonstration. Once complete, start the PyDev debug server: Open Liclipse Install the jython jar for the interpreter. wget https://repo1.maven.org/maven2/org/python/jython-standalone/2.7.2/jython-standalone-2.7.2.jar From the menu: go to File -> Open File and choose the interception script that will be debugged in $(pwd)/interception-scripts-ksync . When opening the Python file for the first time, we need to instruct Liclipse to use a specific interpreter. Follow these steps: Press the \"Manual Config\" button in the dialog box after opening the Python file Open \"PyDev->Interpreters->Jython Interpreters\" Click the \"New...\" button in the right panel. Name it \"Jython\" and specify the interpreter executable that was downloaded previously \"jython-standalone-2.7.2.jar\" Click \"OK\", then confirm the settings by clicking \"OK\" again, then \"Apply and Close\" In the final dialog, confirm the settings by clicking \"OK\" From the menu: go to Window -> Perspective -> Open Perspective -> Other.. -> Debug From the menu: go to Pydev > Start Debug Server . Now the server should have started at port 5678 . Take a note of the ip of the computer running Liclipse and save it for later use. Remember that the auth server pod must be able to communicate with this ip. If you have followed the instructions above and installed minikube on your local computer which is the same computer Liclipse is operating on you should be able to reach it from within the pods. Development & Debugging # Now we are ready to perform script development and debugging. Here is a quick overview: Enable remote debugging on the jans-auth service. Instruct the auth server to load the script from the file system instead of LDAP. Add debug instructions to the script. Execute the script. Enable Remote Debugging in jans-auth # In order to enable remote debugging in the jans-auth process, open /etc/default/jans-auth in your favorite text editor. The default JAVA_OPTIONS variable is as follows: JAVA_OPTIONS=\"-server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base=/etc/jans -Dserver.base=/opt/jans/jetty/jans-auth -Dlog.base=/opt/jans/jetty/jans-auth -Dpython.home=/opt/jython\" Modify to this: JAVA_OPTIONS=\"-server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base=/etc/jans -Dserver.base=/opt/jans/jetty/jans-auth -Dlog.base=/opt/jans/jetty/jans-auth -Dpython.home=/opt/jython -Dorg.eclipse.jetty.server.Request.maxFormContentSize=50000000 -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005\" The last line will enable remote debug on port 5005. Now restart the jans-auth service. # To list all jans processes systemctl list-units --all \"jans*\" # On Ubuntu, the service name is jans-auth.service systemctl restart jans-auth.service If you are running Jans on a local VM or anywhere that is not the same as the machine that will be debugging, you will need to set up an SSH tunnel on port 5005. Execute the following command: ssh -L 5005:localhost:5005 <username>@<host> This will cause your local host's port 5005 to listen on the remote server's port 5005. Now you can use your favorite IDE and set up the remote debugger to connect to localhost:5005 . Enable remote debug in Jython Custom Script # For Jython scripts, we need additional steps to enable breakpoints. After the import section, add: REMOTE_DEBUG = True if REMOTE_DEBUG: try: import sys import pydevd except ImportError as ex: print \"Failed to import pydevd: %s\" % ex raise Add the following lines wherever breakpoints are needed: if REMOTE_DEBUG: pydevd.settrace('localhost', port=5678, stdoutToServer=True, stderrToServer=True) Sample Scenario # Copy the below script to $(pwd)/interception-scripts-ksync/basic.py # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2016, Janssen # # Author: Yuriy Movchan # from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper import java class PersonAuthentication ( PersonAuthenticationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Basic. Initialization\" print \"Basic. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Basic. Destroy\" print \"Basic. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 def isValidAuthenticationMethod ( self , usageType , configurationAttributes ): return True def getAlternativeAuthenticationMethod ( self , usageType , configurationAttributes ): return None def authenticate ( self , configurationAttributes , requestParameters , step ): authenticationService = CdiUtil . bean ( AuthenticationService ) if ( step == 1 ): print \"Basic. Authenticate for step 1\" identity = CdiUtil . bean ( Identity ) credentials = identity . getCredentials () user_name = credentials . getUsername () user_password = credentials . getPassword () logged_in = False if ( StringHelper . isNotEmptyString ( user_name ) and StringHelper . isNotEmptyString ( user_password )): logged_in = authenticationService . authenticate ( user_name , user_password ) if ( not logged_in ): return False return True else : return False def prepareForStep ( self , configurationAttributes , requestParameters , step ): if ( step == 1 ): print \"Basic. Prepare for Step 1\" return True else : return False def getExtraParametersForStep ( self , configurationAttributes , step ): return None def getCountAuthenticationSteps ( self , configurationAttributes ): return 1 def getPageForStep ( self , configurationAttributes , step ): return \"\" def getNextStep ( self , configurationAttributes , requestParameters , step ): return - 1 def getLogoutExternalUrl ( self , configurationAttributes , requestParameters ): print \"Get external logout URL call\" return None def logout ( self , configurationAttributes , requestParameters ): return True Make sure to have an LDAP browser available. We recommend Apache Directory Studio . Port forward the opendj pod. kubectl port-forward jans-opendj-0 -n <jans-namespace> 1636 :1636 --address 0 .0.0.0 Create a connection to the ldap browser. The default password will be Test1234# if not changed in the helm install command. Inside the browser navigate to o=jans, ou=scripts . Right click on ou=scripts and click on Quick Search . Inside the pop up box that appears fill Returning Attributes with displayName , and press Apply and Close In the results that appear click on the Dn that has a displayName of basic . Choose to load the script from file instead of ldap. Inside the browser change jansModuleProperty with value {\"value1\":\"location_type\",\"value2\":\"ldap\",\"description\":\"\"} to {\"value1\":\"location_type\",\"value2\":\"file\",\"description\":\"\"} Specify the Script Path location to the location of the folder inside auth server pods: /deploy/interception-scripts-ksync/basic.py . Right click the upper jansModuleProperty and click New Value . A new entry for jansModuleProperty will be created. Insert the following for the value: {\"value1\":\"location_path\",\"value2\":\"/deploy/interception-scripts-ksync/basic.py\",\"description\":\"\"} Enable the script by settings jansEnabled to true . The following is an example of how the basic script entry should look. Check the following log inside the the auth-server container to verify that auth server loaded the script properly: /opt/jans/jetty/jans-auth/logs/jans-auth_script.log . It should look like this: kubectl exec -ti <auth-server-pod-name> -n <jans-namespace> -- tail -f /opt/jans/jetty/jans-auth/logs/jans-auth_script.log You should find the following in the log: ... (PythonService.java:239) - Basic. Initialization ... (PythonService.java:239) - Basic. Initialized successfully Download the jython jar for the interpreter. wget https://repo1.maven.org/maven2/org/python/jython-standalone/2.7.2/jython-standalone-2.7.2.jar From the IDE (Liclipse) menu: navigate to File -> Open File and choose the interception script that will be debugged in $(pwd)/interception-scripts-ksync/basic.py When opening the Python file for the first time, we need to instruct Liclipse to use a specific interpreter. Follow these steps: Press the \"Manual Config\" button in the dialog box after opening the Python file Open \"PyDev->Interpreters->Jython Interpreters\" Click the \"New...\" button in the right panel. Name it \"Jython\" and specify the interpreter executable that was downloaded previously \"jython-standalone-2.7.2.jar\" Click \"OK\", then confirm the settings by clicking \"OK\" again, then \"Apply and Close\" In the final dialog, confirm the settings by clicking \"OK\" Open basic.py in a file editor. After the import section, add the following lines to load the PyDev libraries: REMOTE_DEBUG = True if REMOTE_DEBUG: try: import sys import pydevd except ImportError as ex: print \"Failed to import pydevd: %s\" % ex raise Add this break condition to the first line in the authenticate method. Place the ip of the maching running the ide , here liclipse i.e 192.168.140.2 . if REMOTE_DEBUG: pydevd.settrace ( '<ip-of-machine-running-ide>' , port = 5678 , stdoutToServer = True, stderrToServer = True ) Save basic.py Within one minute, the auth server should load the changed file. Check the following log file again to make sure there are no load errors: /opt/jans/jetty/jans-auth/logs/jans-auth_script.log To check if the script works, update the default authentication method to Basic Authentication. Preform this in the LDAP browser. Navigate to o=jans,ou=configuration . Change the jansAuthMode to basic instead of simple_password_auth . After executing pydevd.settrace the script will transfer execution control to the PyDev server in Liclipse. You can use any debug commands. For example: Step Over (F6), Resume (F8), etc After debugging is finished, resume script execution to transfer execution control back to the auth server.", "title": "Script Debugging"}, {"location": "script-catalog/introspection/interception-scripts-debug/#setup", "text": "For development the kubernetes setup must be local and accessible to the debug server address. The following steps will walk you trough a setup using Minikube with docker driver, and ksync for syncing the files between local, and the container. The following instructions assume a fresh ubuntu 20.04, however the setup can be done on a different operating systems such as macOS or Windows.", "title": "Setup"}, {"location": "script-catalog/introspection/interception-scripts-debug/#system-requirements", "text": "The minimum system requirement for running all jans services are 8GB RAM , 4 CPU , and 50GB disk . This can be dropped to 4GB RAM , 4CPU and 20GB disk space if operating with required services auth-server, and LDAP.", "title": "System Requirements"}, {"location": "script-catalog/introspection/interception-scripts-debug/#setup-minikube", "text": "Install Docker 18.09 or higher. For other operating systems follow the appropriate docs . Install minikube , but do not start it yet. Install kubectl . Once Minikube is installed start it with the docker driver. minikube start --driver = docker If not automatically set configure kubectl to use the cluster: kubectl config use-context minikube Enable ingress on minikube minikube addons enable ingress", "title": "Setup Minikube"}, {"location": "script-catalog/introspection/interception-scripts-debug/#install-janssen", "text": "Install Helm3 Install Janssen helm repo add jans https://janssenproject.github.io/jans-cloud-native/charts kubectl create ns jans helm install jans-auth jans/jans -n jans --set global.lbIp = \" $( minikube ip ) \" --set global.provisioner = \"k8s.io/minikube-hostpath\" --devel", "title": "Install Janssen"}, {"location": "script-catalog/introspection/interception-scripts-debug/#install-ksync", "text": "Once Janssen is fully running we want to create an active sync between a local folder, and the folder that will hold the interception scripts inside the auth server container. Create a folder that will hold the interception script inside the auth server container. Place the namespace where jans is installed in the env JANS_NAMESPACE and execute: JANS_NAMESPACE = <jans-namespace> for pod in $( kubectl get pods -n $JANS_NAMESPACE --selector = APP_NAME = auth-server --output = jsonpath ={ .items..metadata.name } ) ; do kubectl exec -ti $pod -n $JANS_NAMESPACE -- mkdir -p /deploy/interception-scripts-ksync done Install ksync curl https://ksync.github.io/gimme-that/gimme.sh | bash Initialize ksync ksync init -n <jans-namespace> Start ksync. ksync watch -n <jans-namespace> & Open a new terminal and create a folder called interception-scripts-ksync mkdir -p $( pwd ) /interception-scripts-ksync Create a spec to start syncing folders between the local system and auth server container. ksync create --selector = APP_NAME = auth-server $( pwd ) /interception-scripts-ksync /deploy/interception-scripts-ksync -n <jans-namespace> Check the status. Also check the terminal where the watch command is running. ksync get 1. Move the interception script to the local folder $(pwd)/interception-scripts-ksync . In the below example we copied the following script as basic.py : # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2016, Janssen # # Author: Yuriy Movchan # from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper import java class PersonAuthentication ( PersonAuthenticationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Basic. Initialization\" print \"Basic. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Basic. Destroy\" print \"Basic. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 def isValidAuthenticationMethod ( self , usageType , configurationAttributes ): return True def getAlternativeAuthenticationMethod ( self , usageType , configurationAttributes ): return None def authenticate ( self , configurationAttributes , requestParameters , step ): authenticationService = CdiUtil . bean ( AuthenticationService ) if ( step == 1 ): print \"Basic. Authenticate for step 1\" identity = CdiUtil . bean ( Identity ) credentials = identity . getCredentials () user_name = credentials . getUsername () user_password = credentials . getPassword () logged_in = False if ( StringHelper . isNotEmptyString ( user_name ) and StringHelper . isNotEmptyString ( user_password )): logged_in = authenticationService . authenticate ( user_name , user_password ) if ( not logged_in ): return False return True else : return False def prepareForStep ( self , configurationAttributes , requestParameters , step ): if ( step == 1 ): print \"Basic. Prepare for Step 1\" return True else : return False def getExtraParametersForStep ( self , configurationAttributes , step ): return None def getCountAuthenticationSteps ( self , configurationAttributes ): return 1 def getPageForStep ( self , configurationAttributes , step ): return \"\" def getNextStep ( self , configurationAttributes , requestParameters , step ): return - 1 def getLogoutExternalUrl ( self , configurationAttributes , requestParameters ): print \"Get external logout URL call\" return None def logout ( self , configurationAttributes , requestParameters ): return True", "title": "Install Ksync"}, {"location": "script-catalog/introspection/interception-scripts-debug/#install-an-ide", "text": "The IDE can be of choice but must contain PyDev. We chose Liclipse for this demonstration. Once complete, start the PyDev debug server: Open Liclipse Install the jython jar for the interpreter. wget https://repo1.maven.org/maven2/org/python/jython-standalone/2.7.2/jython-standalone-2.7.2.jar From the menu: go to File -> Open File and choose the interception script that will be debugged in $(pwd)/interception-scripts-ksync . When opening the Python file for the first time, we need to instruct Liclipse to use a specific interpreter. Follow these steps: Press the \"Manual Config\" button in the dialog box after opening the Python file Open \"PyDev->Interpreters->Jython Interpreters\" Click the \"New...\" button in the right panel. Name it \"Jython\" and specify the interpreter executable that was downloaded previously \"jython-standalone-2.7.2.jar\" Click \"OK\", then confirm the settings by clicking \"OK\" again, then \"Apply and Close\" In the final dialog, confirm the settings by clicking \"OK\" From the menu: go to Window -> Perspective -> Open Perspective -> Other.. -> Debug From the menu: go to Pydev > Start Debug Server . Now the server should have started at port 5678 . Take a note of the ip of the computer running Liclipse and save it for later use. Remember that the auth server pod must be able to communicate with this ip. If you have followed the instructions above and installed minikube on your local computer which is the same computer Liclipse is operating on you should be able to reach it from within the pods.", "title": "Install an IDE"}, {"location": "script-catalog/introspection/interception-scripts-debug/#development-debugging", "text": "Now we are ready to perform script development and debugging. Here is a quick overview: Enable remote debugging on the jans-auth service. Instruct the auth server to load the script from the file system instead of LDAP. Add debug instructions to the script. Execute the script.", "title": "Development & Debugging"}, {"location": "script-catalog/introspection/interception-scripts-debug/#enable-remote-debugging-in-jans-auth", "text": "In order to enable remote debugging in the jans-auth process, open /etc/default/jans-auth in your favorite text editor. The default JAVA_OPTIONS variable is as follows: JAVA_OPTIONS=\"-server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base=/etc/jans -Dserver.base=/opt/jans/jetty/jans-auth -Dlog.base=/opt/jans/jetty/jans-auth -Dpython.home=/opt/jython\" Modify to this: JAVA_OPTIONS=\"-server -Xms256m -Xmx928m -XX:+DisableExplicitGC -Djans.base=/etc/jans -Dserver.base=/opt/jans/jetty/jans-auth -Dlog.base=/opt/jans/jetty/jans-auth -Dpython.home=/opt/jython -Dorg.eclipse.jetty.server.Request.maxFormContentSize=50000000 -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005\" The last line will enable remote debug on port 5005. Now restart the jans-auth service. # To list all jans processes systemctl list-units --all \"jans*\" # On Ubuntu, the service name is jans-auth.service systemctl restart jans-auth.service If you are running Jans on a local VM or anywhere that is not the same as the machine that will be debugging, you will need to set up an SSH tunnel on port 5005. Execute the following command: ssh -L 5005:localhost:5005 <username>@<host> This will cause your local host's port 5005 to listen on the remote server's port 5005. Now you can use your favorite IDE and set up the remote debugger to connect to localhost:5005 .", "title": "Enable Remote Debugging in jans-auth"}, {"location": "script-catalog/introspection/interception-scripts-debug/#enable-remote-debug-in-jython-custom-script", "text": "For Jython scripts, we need additional steps to enable breakpoints. After the import section, add: REMOTE_DEBUG = True if REMOTE_DEBUG: try: import sys import pydevd except ImportError as ex: print \"Failed to import pydevd: %s\" % ex raise Add the following lines wherever breakpoints are needed: if REMOTE_DEBUG: pydevd.settrace('localhost', port=5678, stdoutToServer=True, stderrToServer=True)", "title": "Enable remote debug in Jython Custom Script"}, {"location": "script-catalog/introspection/interception-scripts-debug/#sample-scenario", "text": "Copy the below script to $(pwd)/interception-scripts-ksync/basic.py # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2016, Janssen # # Author: Yuriy Movchan # from io.jans.service.cdi.util import CdiUtil from io.jans.as.server.security import Identity from io.jans.model.custom.script.type.auth import PersonAuthenticationType from io.jans.as.server.service import AuthenticationService from io.jans.util import StringHelper import java class PersonAuthentication ( PersonAuthenticationType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Basic. Initialization\" print \"Basic. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Basic. Destroy\" print \"Basic. Destroyed successfully\" return True def getAuthenticationMethodClaims ( self , requestParameters ): return None def getApiVersion ( self ): return 11 def isValidAuthenticationMethod ( self , usageType , configurationAttributes ): return True def getAlternativeAuthenticationMethod ( self , usageType , configurationAttributes ): return None def authenticate ( self , configurationAttributes , requestParameters , step ): authenticationService = CdiUtil . bean ( AuthenticationService ) if ( step == 1 ): print \"Basic. Authenticate for step 1\" identity = CdiUtil . bean ( Identity ) credentials = identity . getCredentials () user_name = credentials . getUsername () user_password = credentials . getPassword () logged_in = False if ( StringHelper . isNotEmptyString ( user_name ) and StringHelper . isNotEmptyString ( user_password )): logged_in = authenticationService . authenticate ( user_name , user_password ) if ( not logged_in ): return False return True else : return False def prepareForStep ( self , configurationAttributes , requestParameters , step ): if ( step == 1 ): print \"Basic. Prepare for Step 1\" return True else : return False def getExtraParametersForStep ( self , configurationAttributes , step ): return None def getCountAuthenticationSteps ( self , configurationAttributes ): return 1 def getPageForStep ( self , configurationAttributes , step ): return \"\" def getNextStep ( self , configurationAttributes , requestParameters , step ): return - 1 def getLogoutExternalUrl ( self , configurationAttributes , requestParameters ): print \"Get external logout URL call\" return None def logout ( self , configurationAttributes , requestParameters ): return True Make sure to have an LDAP browser available. We recommend Apache Directory Studio . Port forward the opendj pod. kubectl port-forward jans-opendj-0 -n <jans-namespace> 1636 :1636 --address 0 .0.0.0 Create a connection to the ldap browser. The default password will be Test1234# if not changed in the helm install command. Inside the browser navigate to o=jans, ou=scripts . Right click on ou=scripts and click on Quick Search . Inside the pop up box that appears fill Returning Attributes with displayName , and press Apply and Close In the results that appear click on the Dn that has a displayName of basic . Choose to load the script from file instead of ldap. Inside the browser change jansModuleProperty with value {\"value1\":\"location_type\",\"value2\":\"ldap\",\"description\":\"\"} to {\"value1\":\"location_type\",\"value2\":\"file\",\"description\":\"\"} Specify the Script Path location to the location of the folder inside auth server pods: /deploy/interception-scripts-ksync/basic.py . Right click the upper jansModuleProperty and click New Value . A new entry for jansModuleProperty will be created. Insert the following for the value: {\"value1\":\"location_path\",\"value2\":\"/deploy/interception-scripts-ksync/basic.py\",\"description\":\"\"} Enable the script by settings jansEnabled to true . The following is an example of how the basic script entry should look. Check the following log inside the the auth-server container to verify that auth server loaded the script properly: /opt/jans/jetty/jans-auth/logs/jans-auth_script.log . It should look like this: kubectl exec -ti <auth-server-pod-name> -n <jans-namespace> -- tail -f /opt/jans/jetty/jans-auth/logs/jans-auth_script.log You should find the following in the log: ... (PythonService.java:239) - Basic. Initialization ... (PythonService.java:239) - Basic. Initialized successfully Download the jython jar for the interpreter. wget https://repo1.maven.org/maven2/org/python/jython-standalone/2.7.2/jython-standalone-2.7.2.jar From the IDE (Liclipse) menu: navigate to File -> Open File and choose the interception script that will be debugged in $(pwd)/interception-scripts-ksync/basic.py When opening the Python file for the first time, we need to instruct Liclipse to use a specific interpreter. Follow these steps: Press the \"Manual Config\" button in the dialog box after opening the Python file Open \"PyDev->Interpreters->Jython Interpreters\" Click the \"New...\" button in the right panel. Name it \"Jython\" and specify the interpreter executable that was downloaded previously \"jython-standalone-2.7.2.jar\" Click \"OK\", then confirm the settings by clicking \"OK\" again, then \"Apply and Close\" In the final dialog, confirm the settings by clicking \"OK\" Open basic.py in a file editor. After the import section, add the following lines to load the PyDev libraries: REMOTE_DEBUG = True if REMOTE_DEBUG: try: import sys import pydevd except ImportError as ex: print \"Failed to import pydevd: %s\" % ex raise Add this break condition to the first line in the authenticate method. Place the ip of the maching running the ide , here liclipse i.e 192.168.140.2 . if REMOTE_DEBUG: pydevd.settrace ( '<ip-of-machine-running-ide>' , port = 5678 , stdoutToServer = True, stderrToServer = True ) Save basic.py Within one minute, the auth server should load the changed file. Check the following log file again to make sure there are no load errors: /opt/jans/jetty/jans-auth/logs/jans-auth_script.log To check if the script works, update the default authentication method to Basic Authentication. Preform this in the LDAP browser. Navigate to o=jans,ou=configuration . Change the jansAuthMode to basic instead of simple_password_auth . After executing pydevd.settrace the script will transfer execution control to the PyDev server in Liclipse. You can use any debug commands. For example: Step Over (F6), Resume (F8), etc After debugging is finished, resume script execution to transfer execution control back to the auth server.", "title": "Sample Scenario"}, {"location": "script-catalog/introspection/introspection/", "tags": ["administration", "developer", "script-catalog", "Introspection"], "text": "Introspection Script Guide # Overview # In OAuth 2.0 [RFC6749], the contents of tokens are opaque to clients. However, there is still a large amount of metadata that may be attached to a token, such as its current validity, approved scopes, and information about the context in which the token was issued. These pieces of information are often vital to protected resources making authorization decisions based on the tokens being presented. Token introspection allows a protected resource to query this information. Introspection scripts allows to modify response of Introspection Endpoint spec and present additional meta information surrounding the token. Interface # Introspection script should be associated with client (used for obtaining the token) in order to be run. Otherwise it's possible to set introspectionScriptBackwardCompatibility global AS configuration property to true, in this case AS will run all scripts (ignoring client configuration). Methods # The introspection interception script extends the base script type with the init , destroy and getApiVersion methods: Inherited Methods Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . The introspection interception script also adds the following method(s): Method def modifyResponse(self, responseAsJsonObject, context) Method Paramater responseAsJsonObject is org.codehaus.jettison.json.JSONObject context is io.jans.as.service.external.context.ExternalIntrospectionContext Snippet # # Returns boolean , true - apply introspection method , false - ignore it . # This method is called after introspection response is ready . This method can modify introspection response . # Note : # responseAsJsonObject - is org . codehaus . jettison . json . JSONObject , you can use any method to manipulate json # context is reference of io . jans . as . server . service . external . context . ExternalIntrospectionContext ( in https : // github . com / JanssenProject project ) def modifyResponse ( self , responseAsJsonObject , context ) : responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True It is also possible to run introspection script during access_token creation as JWT. It can be controlled by run_introspection_script_before_jwt_creation client property which is set to false by default. If run_introspection_script_before_jwt_creation set to true and access_token_as_jwt set to true then introspection script will be run before JWT ( access_token ) is created and all JSON values will be transfered to JWT. Also context inside script has additional method which allows to cancel transfering of claims if needed context.setTranferIntrospectionPropertiesIntoJwtClaims(false) Common Use Cases # Script Type: Python # Retrieve Grant, Session and User Details from Access Token # Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. from io.jans.model.custom.script.type.introspection import IntrospectionType from io.jans.as.server.service import SessionIdService from io.jans.service.cdi.util import CdiUtil class Introspection ( IntrospectionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Introspection script. Initializing ...\" print \"Introspection script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Introspection script. Destroying ...\" print \"Introspection script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply introspection method, false - ignore it. # This method is called after introspection response is ready. This method can modify introspection response. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.server.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenProject project, ) def modifyResponse ( self , responseAsJsonObject , context ): authorizationGrant = context . getTokenGrant () if authorizationGrant is None : print \"Introspection. Failed to load authorization grant by context\" return False # Put user_id into response responseAsJsonObject . accumulate ( \"user_id\" , authorizationGrant . getUser () . getUserId ()) # Put custom parameters into response sessionDn = authorizationGrant . getSessionDn () if sessionDn is None : # There is no session print \"Introspection. Failed to load session DN\" return True # Return session_id responseAsJsonObject . accumulate ( \"session_id\" , sessionDn ) sessionIdService = CdiUtil . bean ( SessionIdService ) session = sessionIdService . getSessionById ( sessionDn , False ) if session is None : print \"Introspection. Failed to load session ' %s '\" % sessionDn return True sessionAttributes = session . getSessionAttributes () if sessionAttributes is None : # There is no session attributes return True # Append custom claims if sessionAttributes . containsKey ( \"custom1\" ): responseAsJsonObject . accumulate ( \"custom1\" , sessionAttributes . get ( \"custom1\" )) if sessionAttributes . containsKey ( \"custom2\" ): responseAsJsonObject . accumulate ( \"custom2\" , sessionAttributes . get ( \"custom2\" )) return True Script Type: Java # Retrieve Grant, Session and User Details from Access Token # Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.introspection.IntrospectionType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.ExternalIntrospectionContext ; import io.jans.as.server.model.common.AuthorizationGrant ; import io.jans.as.server.service.SessionIdService ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.as.server.model.common.SessionId ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import org.json.JSONObject ; import java.util.Map ; public class Introspection implements IntrospectionType { private static final Logger log = LoggerFactory . getLogger ( Introspection . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Introspection Java custom script\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Introspection Java custom script\" ); scriptLogger . info ( \"Introspection Java script. Initializing ...\" ); scriptLogger . info ( \"Introspection Java script. Initialized successfully\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Destroy of Introspection Java custom script\" ); scriptLogger . info ( \"Introspection Java script. Destroying ...\" ); scriptLogger . info ( \"Introspection Java script. Destroyed successfully\" ); return true ; } @Override public int getApiVersion () { return 11 ; } // Returns boolean , true - apply introspection method , false - ignore it . // This method is called after introspection response is ready . This method can modify introspection response . // Note : // responseAsJsonObject - is org . json . JSONObject , you can use any method to manipulate json // context is reference of io . jans . as . server . service . external . context . ExternalIntrospectionContext ( in https : // github . com / JanssenProject project , ) @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { JSONObject response = ( JSONObject ) responseAsJsonObject ; ExternalIntrospectionContext ctx = ( ExternalIntrospectionContext ) context ; response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); AuthorizationGrant authorizationGrant = ctx . getTokenGrant (); if ( authorizationGrant == null ) { scriptLogger . info ( \"Introspection Java script. Failed to load authorization grant by context\" ); return false ; } // Put user_id into response response . accumulate ( \"user_id\" , authorizationGrant . getUser () . getUserId ()); // Put custom parameters into response String sessionDn = authorizationGrant . getSessionDn (); if ( sessionDn == null ) { // There is no session scriptLogger . info ( \"Introspection Java script. Failed to load session DN\" ); return true ; } // Return session_id response . accumulate ( \"session_id\" , sessionDn ); SessionIdService sessionIdService = CdiUtil . bean ( SessionIdService . class ); SessionId session = sessionIdService . getSessionById ( sessionDn , false ); if ( session == null ) { scriptLogger . info ( \"Introspection Java script. Failed to load session\" ); return true ; } Map < String , String > sessionAttributes = session . getSessionAttributes (); if ( sessionAttributes == null ) { // There is no session attributes return true ; } // Append custom claims if ( sessionAttributes . containsKey ( \"custom1\" )) { response . accumulate ( \"custom1\" , sessionAttributes . get ( \"custom1\" )); } if ( sessionAttributes . containsKey ( \"custom2\" )) { response . accumulate ( \"custom2\" , sessionAttributes . get ( \"custom2\" )); } return true ; } }", "title": "Introspection"}, {"location": "script-catalog/introspection/introspection/#introspection-script-guide", "text": "", "title": "Introspection Script Guide"}, {"location": "script-catalog/introspection/introspection/#overview", "text": "In OAuth 2.0 [RFC6749], the contents of tokens are opaque to clients. However, there is still a large amount of metadata that may be attached to a token, such as its current validity, approved scopes, and information about the context in which the token was issued. These pieces of information are often vital to protected resources making authorization decisions based on the tokens being presented. Token introspection allows a protected resource to query this information. Introspection scripts allows to modify response of Introspection Endpoint spec and present additional meta information surrounding the token.", "title": "Overview"}, {"location": "script-catalog/introspection/introspection/#interface", "text": "Introspection script should be associated with client (used for obtaining the token) in order to be run. Otherwise it's possible to set introspectionScriptBackwardCompatibility global AS configuration property to true, in this case AS will run all scripts (ignoring client configuration).", "title": "Interface"}, {"location": "script-catalog/introspection/introspection/#methods", "text": "The introspection interception script extends the base script type with the init , destroy and getApiVersion methods: Inherited Methods Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 The configurationAttributes parameter is java.util.Map<String, SimpleCustomProperty> . The introspection interception script also adds the following method(s): Method def modifyResponse(self, responseAsJsonObject, context) Method Paramater responseAsJsonObject is org.codehaus.jettison.json.JSONObject context is io.jans.as.service.external.context.ExternalIntrospectionContext", "title": "Methods"}, {"location": "script-catalog/introspection/introspection/#snippet", "text": "# Returns boolean , true - apply introspection method , false - ignore it . # This method is called after introspection response is ready . This method can modify introspection response . # Note : # responseAsJsonObject - is org . codehaus . jettison . json . JSONObject , you can use any method to manipulate json # context is reference of io . jans . as . server . service . external . context . ExternalIntrospectionContext ( in https : // github . com / JanssenProject project ) def modifyResponse ( self , responseAsJsonObject , context ) : responseAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True It is also possible to run introspection script during access_token creation as JWT. It can be controlled by run_introspection_script_before_jwt_creation client property which is set to false by default. If run_introspection_script_before_jwt_creation set to true and access_token_as_jwt set to true then introspection script will be run before JWT ( access_token ) is created and all JSON values will be transfered to JWT. Also context inside script has additional method which allows to cancel transfering of claims if needed context.setTranferIntrospectionPropertiesIntoJwtClaims(false)", "title": "Snippet"}, {"location": "script-catalog/introspection/introspection/#common-use-cases", "text": "", "title": "Common Use Cases"}, {"location": "script-catalog/introspection/introspection/#script-type-python", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/introspection/introspection/#retrieve-grant-session-and-user-details-from-access-token", "text": "Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. from io.jans.model.custom.script.type.introspection import IntrospectionType from io.jans.as.server.service import SessionIdService from io.jans.service.cdi.util import CdiUtil class Introspection ( IntrospectionType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Introspection script. Initializing ...\" print \"Introspection script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Introspection script. Destroying ...\" print \"Introspection script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply introspection method, false - ignore it. # This method is called after introspection response is ready. This method can modify introspection response. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.server.service.external.context.ExternalIntrospectionContext (in https://github.com/JanssenProject project, ) def modifyResponse ( self , responseAsJsonObject , context ): authorizationGrant = context . getTokenGrant () if authorizationGrant is None : print \"Introspection. Failed to load authorization grant by context\" return False # Put user_id into response responseAsJsonObject . accumulate ( \"user_id\" , authorizationGrant . getUser () . getUserId ()) # Put custom parameters into response sessionDn = authorizationGrant . getSessionDn () if sessionDn is None : # There is no session print \"Introspection. Failed to load session DN\" return True # Return session_id responseAsJsonObject . accumulate ( \"session_id\" , sessionDn ) sessionIdService = CdiUtil . bean ( SessionIdService ) session = sessionIdService . getSessionById ( sessionDn , False ) if session is None : print \"Introspection. Failed to load session ' %s '\" % sessionDn return True sessionAttributes = session . getSessionAttributes () if sessionAttributes is None : # There is no session attributes return True # Append custom claims if sessionAttributes . containsKey ( \"custom1\" ): responseAsJsonObject . accumulate ( \"custom1\" , sessionAttributes . get ( \"custom1\" )) if sessionAttributes . containsKey ( \"custom2\" ): responseAsJsonObject . accumulate ( \"custom2\" , sessionAttributes . get ( \"custom2\" )) return True", "title": "Retrieve Grant, Session and User Details from Access Token"}, {"location": "script-catalog/introspection/introspection/#script-type-java", "text": "", "title": "Script Type: Java"}, {"location": "script-catalog/introspection/introspection/#retrieve-grant-session-and-user-details-from-access-token_1", "text": "Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.introspection.IntrospectionType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.external.context.ExternalIntrospectionContext ; import io.jans.as.server.model.common.AuthorizationGrant ; import io.jans.as.server.service.SessionIdService ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.as.server.model.common.SessionId ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import org.json.JSONObject ; import java.util.Map ; public class Introspection implements IntrospectionType { private static final Logger log = LoggerFactory . getLogger ( Introspection . class ); private static final Logger scriptLogger = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Introspection Java custom script\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Init of Introspection Java custom script\" ); scriptLogger . info ( \"Introspection Java script. Initializing ...\" ); scriptLogger . info ( \"Introspection Java script. Initialized successfully\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Destroy of Introspection Java custom script\" ); scriptLogger . info ( \"Introspection Java script. Destroying ...\" ); scriptLogger . info ( \"Introspection Java script. Destroyed successfully\" ); return true ; } @Override public int getApiVersion () { return 11 ; } // Returns boolean , true - apply introspection method , false - ignore it . // This method is called after introspection response is ready . This method can modify introspection response . // Note : // responseAsJsonObject - is org . json . JSONObject , you can use any method to manipulate json // context is reference of io . jans . as . server . service . external . context . ExternalIntrospectionContext ( in https : // github . com / JanssenProject project , ) @Override public boolean modifyResponse ( Object responseAsJsonObject , Object context ) { JSONObject response = ( JSONObject ) responseAsJsonObject ; ExternalIntrospectionContext ctx = ( ExternalIntrospectionContext ) context ; response . accumulate ( \"key_from_java\" , \"value_from_script_on_java\" ); AuthorizationGrant authorizationGrant = ctx . getTokenGrant (); if ( authorizationGrant == null ) { scriptLogger . info ( \"Introspection Java script. Failed to load authorization grant by context\" ); return false ; } // Put user_id into response response . accumulate ( \"user_id\" , authorizationGrant . getUser () . getUserId ()); // Put custom parameters into response String sessionDn = authorizationGrant . getSessionDn (); if ( sessionDn == null ) { // There is no session scriptLogger . info ( \"Introspection Java script. Failed to load session DN\" ); return true ; } // Return session_id response . accumulate ( \"session_id\" , sessionDn ); SessionIdService sessionIdService = CdiUtil . bean ( SessionIdService . class ); SessionId session = sessionIdService . getSessionById ( sessionDn , false ); if ( session == null ) { scriptLogger . info ( \"Introspection Java script. Failed to load session\" ); return true ; } Map < String , String > sessionAttributes = session . getSessionAttributes (); if ( sessionAttributes == null ) { // There is no session attributes return true ; } // Append custom claims if ( sessionAttributes . containsKey ( \"custom1\" )) { response . accumulate ( \"custom1\" , sessionAttributes . get ( \"custom1\" )); } if ( sessionAttributes . containsKey ( \"custom2\" )) { response . accumulate ( \"custom2\" , sessionAttributes . get ( \"custom2\" )); } return true ; } }", "title": "Retrieve Grant, Session and User Details from Access Token"}, {"location": "script-catalog/introspection/introspection/", "text": "This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Index"}, {"location": "script-catalog/introspection/introspection/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/introspection/introspection/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/introspection/introspection/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/persistence_extension/persistence/", "tags": ["administration", "developer", "script-catalog", "Hashed Passwords", "Entry manager", "Persistence Extension"], "text": "Persistence Script # By overriding the interface methods in PersistenceType inside a custom script you can Load initialization data from DB or initialize services after the creation of Entry Manager. Release resources, terminate services etc. after the destruction of Entry Manager. Create hashed passwords Compare hashed passwords What is an Entry Manager? The Janssen server's Peristence Layer can be MySQL database. Information about an entity (person, session, client, scripts etc) constitutes an Entry. The Entry Manager (CRUD operations) implementation for each type of Persistence is available in the Janssen server and the relevant Entry Manager (SQLEntryManager, etc.) is created when the server starts up. Usage # The Jans-Auth server contains a PeristenceType script. Hashed Passwords # Hashed passwords can be created using any method from this enum , instead of the native/default SSHA256. The ORM module of the Janssen server does the following: When User entry is persisted and userPassword is specified, ORM calls createHashedPassword User authenticates and the password is checked, the ORM module invokes compareHashedPasswords We need to specify which one to use in /etc/gluu/conf/jans-couchbase.properties password.encryption.method: SSHA-256 Implementation createHashedPassword and compareHashedPasswords the script: Creation def createHashedPassword(self, credential): hashed_password= PasswordEncryptionHelper.createStoragePassword(credential, PasswordEncryptionMethod.HASH_METHOD_PKCS5S2) return hashed_password Comparing Hashed Password: def compareHashedPasswords(self, credential, storedCredential): auth_result = PasswordEncryptionHelper.compareCredentials(credential, storedCredential) return auth_result Script Type: Python # Retrieve Grant, Session and User Details from Access Token # Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. from io.jans.service.cdi.util import CdiUtil from io.jans.model.custom.script.type.persistence import PersistenceType from io.jans.util import StringHelper from io.jans.persist.operation.auth import PasswordEncryptionHelper from io.jans.persist.operation.auth import PasswordEncryptionMethod import java class PersistenceExtension ( PersistenceType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Persistence extension. Initialization\" return True def destroy ( self , configurationAttributes ): print \"Persistence extension. Destroy\" return True def getApiVersion ( self ): return 11 def onAfterCreate ( self , context , configurationAttributes ): print \"Persistence extension. Method: onAfterCreate\" def onAfterDestroy ( self , context , configurationAttributes ): print \"Persistence extension. Method: onAfterDestroy\" def createHashedPassword ( self , credential ): print \"Persistence extension. Method: createHashedPassword\" hashed_password = PasswordEncryptionHelper . createStoragePassword ( credential , PasswordEncryptionMethod . HASH_METHOD_PKCS5S2 ) return hashed_password def compareHashedPasswords ( self , credential , storedCredential ): print \"Persistence extension. Method: compareHashedPasswords\" auth_result = PasswordEncryptionHelper . compareCredentials ( credential , storedCredential ) return auth_result", "title": "Persistence"}, {"location": "script-catalog/persistence_extension/persistence/#persistence-script", "text": "By overriding the interface methods in PersistenceType inside a custom script you can Load initialization data from DB or initialize services after the creation of Entry Manager. Release resources, terminate services etc. after the destruction of Entry Manager. Create hashed passwords Compare hashed passwords What is an Entry Manager? The Janssen server's Peristence Layer can be MySQL database. Information about an entity (person, session, client, scripts etc) constitutes an Entry. The Entry Manager (CRUD operations) implementation for each type of Persistence is available in the Janssen server and the relevant Entry Manager (SQLEntryManager, etc.) is created when the server starts up.", "title": "Persistence Script"}, {"location": "script-catalog/persistence_extension/persistence/#usage", "text": "The Jans-Auth server contains a PeristenceType script.", "title": "Usage"}, {"location": "script-catalog/persistence_extension/persistence/#hashed-passwords", "text": "Hashed passwords can be created using any method from this enum , instead of the native/default SSHA256. The ORM module of the Janssen server does the following: When User entry is persisted and userPassword is specified, ORM calls createHashedPassword User authenticates and the password is checked, the ORM module invokes compareHashedPasswords We need to specify which one to use in /etc/gluu/conf/jans-couchbase.properties password.encryption.method: SSHA-256 Implementation createHashedPassword and compareHashedPasswords the script: Creation def createHashedPassword(self, credential): hashed_password= PasswordEncryptionHelper.createStoragePassword(credential, PasswordEncryptionMethod.HASH_METHOD_PKCS5S2) return hashed_password Comparing Hashed Password: def compareHashedPasswords(self, credential, storedCredential): auth_result = PasswordEncryptionHelper.compareCredentials(credential, storedCredential) return auth_result", "title": "Hashed Passwords"}, {"location": "script-catalog/persistence_extension/persistence/#script-type-python", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/persistence_extension/persistence/#retrieve-grant-session-and-user-details-from-access-token", "text": "Following sample code snippet shows how to work backwards from an AccessToken to Grant, Session and User information. from io.jans.service.cdi.util import CdiUtil from io.jans.model.custom.script.type.persistence import PersistenceType from io.jans.util import StringHelper from io.jans.persist.operation.auth import PasswordEncryptionHelper from io.jans.persist.operation.auth import PasswordEncryptionMethod import java class PersistenceExtension ( PersistenceType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Persistence extension. Initialization\" return True def destroy ( self , configurationAttributes ): print \"Persistence extension. Destroy\" return True def getApiVersion ( self ): return 11 def onAfterCreate ( self , context , configurationAttributes ): print \"Persistence extension. Method: onAfterCreate\" def onAfterDestroy ( self , context , configurationAttributes ): print \"Persistence extension. Method: onAfterDestroy\" def createHashedPassword ( self , credential ): print \"Persistence extension. Method: createHashedPassword\" hashed_password = PasswordEncryptionHelper . createStoragePassword ( credential , PasswordEncryptionMethod . HASH_METHOD_PKCS5S2 ) return hashed_password def compareHashedPasswords ( self , credential , storedCredential ): print \"Persistence extension. Method: compareHashedPasswords\" auth_result = PasswordEncryptionHelper . compareCredentials ( credential , storedCredential ) return auth_result", "title": "Retrieve Grant, Session and User Details from Access Token"}, {"location": "script-catalog/person_authentication/person-authentication/", "tags": ["administration", "developer", "script-catalog", "acr_values_supported", "2FA", "PersonAuthenticationType", "acr", "weld"], "text": "Person Authentication scripts # The Janssen Server leverages interception scripts of PersonAuthenticationType which when implemented can facilitate complex multi-step, multi-factor authentication workflows. The authentication flow in the Janssen Server is driven by the OpenID Connect specification . The authorization request to the OP (the Janssen Server) contains an optional query parameter called acr_values which is used by the OP to pick an interception script which will be run when /authorize endpoint (Authentication flow) is invoked. Each authentication method, whose name is the acr value, is tied to a PersonAuthenticationType script which offers the authentication workflow. Typically, a PersonAuthenticationType script can be used to: Introduce a new 2FA authentication mechanism Customize multi-step authentication Offer Social logins Proactively perform fraud detection and block a fraudulent user Authentication mechanisms offered by Jans can be confirmed by checking the Janssen Server OP configuration URL: https://<hostname>/.well-known/openid-configuration under the claim acr_values_supported . Building blocks of an authentication workflow # Jans-auth server comprises of a number of beans, configuration files and Facelets (JSF) views, packaged as a WAR module. That means custom scripts and custom pages (JSF facelets) can make use of business logic already encapsulated in the Weld managed beans. The following sections explain how authentication flow can be built using a custom script. A. Custom script # The PersonAuthenticationType script is described by a java interface whose methods should be overridden to implement an authentication workflow. The article talks about these methods in detail and the psuedo code for each method. B. UI pages: # All web pages are xhtml files. The Command-Action offering by JSF framework is used by the Jans-auth server to implement authentication flows. a. Server-side actions implemented by custom script: # The custom script's authenticate and prepareForStep implementations are called by the following java class - Authenticator . These methods are mapped as command actions and view actions respectively in the web page. Relevant methods: Signature Description boolean authenticate() Makes the authentication flow proceed by calling the authenticate method of the custom script String prepareAuthenticationForStep() Makes the authentication flow proceed by calling the prepareForStep method of the custom script b. Web page in xhtml: # The f:metadata and f:viewAction tags are used to load variables (prepared in the prepareForStep method of the custom script). These variables are rendered on the UI page. <f:metadata> <f:viewAction action=\"#{authenticator.prepareAuthenticationForStep}\" if=\"#{not identity.loggedIn}\" /> </f:metadata> A form submit takes the flow to the authenticate() method of the custom script. <h:commandButton id=\"updateButton\" value=\"Update\" styleClass=\"btn btn-primary col-sm-4\" action=\"#{authenticator.authenticate}\" style=\"margin:5px;\" /> c. Page customizations: # The Jans-auth server comes with a default set of pages for login, logout, errors, authorizations. You can easily override these pages or write new ones. You can easily apply your own stylesheet, images and resouce-bundles to your pages. This article covers all the details you need to write your own web page. C. Business logic in Custom script: # Jans-auth server uses Weld 3.0 (JSR-365 aka CDI 2.0) for managed beans. The most important aspects of business logic are implemented through a set of beans. Details and examples of this can be found in this article D. Third party libraries for use in the custom script # Java or Python libraries to be imported and used very easily. Remember, you can import a python library only if it has been written in \"pure python\". More details of this mentioned here E. Configuring the acr parameter in the Jans-auth server: # The acr parameter can be configured in the following ways : Default authentication method: # default_acr : This is the default authentication mechanism exposed to all applications that send users to the Janssen Server for sign-in. Unless an app specifically requests a different form of authentication using the OpenID Connect acr_values parameter (as specified below), users will receive the form of authentication specified in this field. Internal ACR # If a default ACR is not specified, Janssen will determine it based on enabled scripts and the internal user/password ACR. This internal ACR, simple_password_auth , is set to level -1. This means that it has lower priority than any scripts, so Janssen server will use it only if no other authentication method is set. Use the jans-cli to update / look-up the default authentication method . Authentication method for a client (RP): # A client may also specify default_acr_values during registration (and omit the parameter acr_values while making an authentication request). Multiple Authentication Mechanisms # The Jans Server can concurrently support multiple authentication mechanisms, enabling Web and mobile apps (clients) to request a specific type of authentication using the standard OpenID Connect request parameter: acr_values . Learn more about acr_values in the OpenID Connect core spec . Enabling an authentication mechanism # An Authentication method is offered by the AS if its ACR value i.e. its corresponding custom script is enabled . By default, users will get the default authentication mechanism as specified above. However, using the OpenID Connect acr_values parameter, web and mobile clients can request any enabled authentication mechanism . Obtain the json contents of a custom script by using a jans-cli command like get-config-scripts-by-type , get-config-scripts-by-inum etc. Example : /opt/jans/jans-cli/config-cli.py --operation-id get-config-scripts-by-type --url-suffix type:PERSON_AUTHENTICATION /opt/jans/jans-cli/config-cli.py --operation-id get-config-scripts-by-inum --url-suffix inum:6122281b-b55d-4dd0-8115-b098eeeee2b7 Update the custom script and change the enabled attribute to true Level (rank) of an Authentication mechanism : # Each authentication mechanism (script) has a \"Level\" assigned to it which describes how secure and reliable it is. The higher the \"Level\", higher is the reliability represented by the script. Though several mechanisms can be enabled at the same Janssen server instance at the same time, for any specific user's session only one of them can be set as the current one (and will be returned as acr claim of id_token for them). If after initial session is created a new authorization request from a RP comes in specifying another authentication method, its \"Level\" will be compared to that of the method currently associated with this session. If requested method's \"Level\" is lower or equal to it, nothing is changed and the usual SSO behavior is observed. If it's higher (i.e. a more secure method is requested), it's not possible to serve such request using the existing session's context, and user must re-authenticate themselves to continue. If they succeed, a new session becomes associated with that requested mechanism instead. F. Using person authenticator jansAuthenticator attribute : # The jansAuthenticator attribute can be used in cases when person authenticator need to persist data between person logins. For example script can have enrollment and authentication flows. And after enrollment it needs to store data into user entry for later use in authentication flow. In order to search by enrolled authenticator there is another multi-valued attribute jansExtUid . This attribute has default DB index to quick search. Both attributes is recommended to use In Jans since 1.1.1 version for better compatibility in future. 1. Format of attributes # jansExtUid: [otp:xyz1, cert:xyz2, duo:xyz3, ...] jansAuthenticator: { \"xyz1\": {\"id\": \"xyz1\", \"type\": \"otp\", \"custom\": {...}}, \"xyz2\": {\"id\": \"xyz2\", \"type\": \"cert\", \"custom\": {...}}, \"xyz3\": {\"id\": \"xyz3\", \"type\": \"duo\", \"custom\": {...}}, ... } 2. Sample data: # jansExtUid: [hotp:S9dO_qKQoOcpPk9GuStlNO9seoA=, cert:totp, duo:Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=] jansAuthenticator: { \"S9dO_qKQoOcpPk9GuStlNO9seoA=\": { \"id\": \"S9dO_qKQoOcpPk9GuStlNO9seoA=\", \"type\": \"hotp\", \"custom\": { \"movingFactor\": 3 } }, \"Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=\": { \"id\": \"Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=\", \"type\": \"totp\" } } 2. Access jansAuthenticator and jansExtUid from generic bean # For both attributes there are get/set methods in User entry. After loading user object script can call these methods to get required data. ... @AttributeName(name = \"jansExtUid\") private String[] externalUid; @JsonObject @AttributeName(name = \"jansAuthenticator\") private UserAuthenticatorList authenticator ... public String[] getExternalUid() { return externalUid; } public void setExternalUid(String[] externalUid) { this.externalUid = externalUid; } public UserAuthenticatorList getAuthenticator() { return authenticator; } public void setAuthenticator(UserAuthenticatorList authenticator) { this.authenticator = authenticator; } ... UserAuthenticatorList is defined here . It contains list of UserAuthenticator objects. UserAuthenticator is defined here For convenience in 1.1.1 there is new service UserAuthenticator . See it's code here It provides next API methods: public UserAuthenticatorList getUserAuthenticatorList(SimpleUser user); public List<UserAuthenticator> getUserAuthenticatorsByType(SimpleUser user, String type); public UserAuthenticator getUserAuthenticatorById(SimpleUser user, String id); public void addUserAuthenticator(SimpleUser user, UserAuthenticator userAuthenticator); public void removeUserAuthenticator(SimpleUser user, UserAuthenticator userAuthenticator); public void removeUserAuthenticator(SimpleUser user, String type); public UserAuthenticator createUserAuthenticator(String id, String type); public UserAuthenticator createUserAuthenticator(String id, String type, Map<String, Object> custom); public String formatExternalUid(String id, String type); public boolean checkAndMigrateToAuthenticatorList(SimpleUser user); All these methods update both jansAuthenticator and jansExtUid attributes without persisting changes to DB. After calling these methods script should persist user entry. It's expected behaviour because script might update other fields too. Hence it's better to persist all changes in one update request to DB. 1. Default authentication method: # default_acr : This is the default authentication mechanism exposed to all applications that send users to the Janssen Server for sign-in. Unless an app specifically requests a different form of authentication using the OpenID Connect acr_values parameter (as specified below), users will receive the form of authentication specified in this field. Usage scenarios # A. Implementing 2FA authentication mechanisms # FIDO2 : Authentications using platform authenticators embedded into a person's device or physical USB, NFC or Bluetooth security keys that are inserted into a USB slot of a computer OTP authentication : Authentication mechanism using an app like Google authenticator , FreeOTP or Authy that implements the open standards HOTP and TOTP SMS OTP : Email OTP: B. Implementing Multistep authentication # Redirect to previous step : The script here an example of how the number of steps can be varied depending on the context or business requirement. C. Implementing Social logins # You can use a PersonAuthenticationType script to allow users to sign using credentials from popular Social Identity providers or Inbound Identity Providers like Facebook, Google and Apple. After users authenticate, thier Social Identity Provider credentials are provisioned into the Jans-auth server. More on this topic in this article D. Proactively perform fraud detection # Impossible travel Testing an authentication flow # An example of a complete URL looks like this - ``` https://<your.jans.server>/jans-auth/authorize.htm? \\ response_type=code&redirect_uri=https://<your.jans.server>/admin \\ &client_id=17b8b82e-b3ec-42a2-bd90-097028a37f3 \\ &scope=openid+profile+email+user_name \\ &state=faad2cdjfdddjfkdf&nonce=dajdffdfsdcfff ``` To test , enter the complete URL for authorization in a browser or create a simple webmapage with a link that simulates the user sign-in attempt. If the server is configured properly, the first page for the selected authentication method will be displayed to the user. FAQs # 1. How can error messages be displayed on a web page? # FacesMessage bean is used for this purpose. from org.jans.jsf2.message import FacesMessages from org.jans.service.cdi.util import CdiUtil from javax.faces.application import FacesMessage ... facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Please enter a valid username\") The error will appear in the associated template using the following markup: ... <h:messages /> ... See an example here 2. How is redirection to a third party application for authentication handled in a script? # For user authentication or consent gathering, there might be a need to redirect to a third party application to perform some operation and return the control back to authentication steps of the custom script. Please apply these steps to a person authentication script in such a scenario: Return from def getPageForStep(self, step, context), a page /auth/method_name/redirect.html ; with content similar to the code snippet below - def getPageForStep(self, step, context): return \"/auth/method_name/redirect.html\" Contents of redirect.xhtml should take the flow to prepareForStep method ... <f:metadata> <f:viewAction action=\"#{authenticator.prepareForStep}\" if=\"#{not identity.loggedIn}\" /> </f:metadata> In method prepareForStep prepare data needed for redirect and perform the redirection to the external service. def prepareForStep(self, step, context): ..... facesService = CdiUtil.bean(FacesService) facesService.redirectToExternalURL(third_party_URL ) return True In order to resume flow after the redirection, invoke a similar URL to https://my.gluu.server/postlogin.htm?param=123 from the third party app which takes the flow back to the authenticate method of the custom script. So create an xhtml page postlogin.xhtml which will look like this : <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> <html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:f=\"http://xmlns.jcp.org/jsf/core\"> <f:view transient=\"true\" contentType=\"text/html\"> <f:metadata> <f:viewAction action=\"#{authenticator.authenticateWithOutcome}\" /> </f:metadata> </f:view> </html> The <f:viewAction action=\"#{authenticator.authenticateWithOutcome}\" /> in step 4 takes us to the authenticate method inside the custom script def authenticate(self, configurationAttributes, requestParameters, step): . Here you can use parameters from request param = ServerUtil.getFirstValue(requestParameters, \"param-name\")) perform the state check (state : Opaque value used to maintain state between the request and the callback.) finally, return true or false from this method.", "title": "Person Authentication"}, {"location": "script-catalog/person_authentication/person-authentication/#person-authentication-scripts", "text": "The Janssen Server leverages interception scripts of PersonAuthenticationType which when implemented can facilitate complex multi-step, multi-factor authentication workflows. The authentication flow in the Janssen Server is driven by the OpenID Connect specification . The authorization request to the OP (the Janssen Server) contains an optional query parameter called acr_values which is used by the OP to pick an interception script which will be run when /authorize endpoint (Authentication flow) is invoked. Each authentication method, whose name is the acr value, is tied to a PersonAuthenticationType script which offers the authentication workflow. Typically, a PersonAuthenticationType script can be used to: Introduce a new 2FA authentication mechanism Customize multi-step authentication Offer Social logins Proactively perform fraud detection and block a fraudulent user Authentication mechanisms offered by Jans can be confirmed by checking the Janssen Server OP configuration URL: https://<hostname>/.well-known/openid-configuration under the claim acr_values_supported .", "title": "Person Authentication scripts"}, {"location": "script-catalog/person_authentication/person-authentication/#building-blocks-of-an-authentication-workflow", "text": "Jans-auth server comprises of a number of beans, configuration files and Facelets (JSF) views, packaged as a WAR module. That means custom scripts and custom pages (JSF facelets) can make use of business logic already encapsulated in the Weld managed beans. The following sections explain how authentication flow can be built using a custom script.", "title": "Building blocks of an authentication workflow"}, {"location": "script-catalog/person_authentication/person-authentication/#a-custom-script", "text": "The PersonAuthenticationType script is described by a java interface whose methods should be overridden to implement an authentication workflow. The article talks about these methods in detail and the psuedo code for each method.", "title": "A. Custom script"}, {"location": "script-catalog/person_authentication/person-authentication/#b-ui-pages", "text": "All web pages are xhtml files. The Command-Action offering by JSF framework is used by the Jans-auth server to implement authentication flows.", "title": "B. UI pages:"}, {"location": "script-catalog/person_authentication/person-authentication/#a-server-side-actions-implemented-by-custom-script", "text": "The custom script's authenticate and prepareForStep implementations are called by the following java class - Authenticator . These methods are mapped as command actions and view actions respectively in the web page. Relevant methods: Signature Description boolean authenticate() Makes the authentication flow proceed by calling the authenticate method of the custom script String prepareAuthenticationForStep() Makes the authentication flow proceed by calling the prepareForStep method of the custom script", "title": "a. Server-side actions implemented by custom script:"}, {"location": "script-catalog/person_authentication/person-authentication/#b-web-page-in-xhtml", "text": "The f:metadata and f:viewAction tags are used to load variables (prepared in the prepareForStep method of the custom script). These variables are rendered on the UI page. <f:metadata> <f:viewAction action=\"#{authenticator.prepareAuthenticationForStep}\" if=\"#{not identity.loggedIn}\" /> </f:metadata> A form submit takes the flow to the authenticate() method of the custom script. <h:commandButton id=\"updateButton\" value=\"Update\" styleClass=\"btn btn-primary col-sm-4\" action=\"#{authenticator.authenticate}\" style=\"margin:5px;\" />", "title": "b. Web page in xhtml:"}, {"location": "script-catalog/person_authentication/person-authentication/#c-page-customizations", "text": "The Jans-auth server comes with a default set of pages for login, logout, errors, authorizations. You can easily override these pages or write new ones. You can easily apply your own stylesheet, images and resouce-bundles to your pages. This article covers all the details you need to write your own web page.", "title": "c. Page customizations:"}, {"location": "script-catalog/person_authentication/person-authentication/#c-business-logic-in-custom-script", "text": "Jans-auth server uses Weld 3.0 (JSR-365 aka CDI 2.0) for managed beans. The most important aspects of business logic are implemented through a set of beans. Details and examples of this can be found in this article", "title": "C. Business logic in Custom script:"}, {"location": "script-catalog/person_authentication/person-authentication/#d-third-party-libraries-for-use-in-the-custom-script", "text": "Java or Python libraries to be imported and used very easily. Remember, you can import a python library only if it has been written in \"pure python\". More details of this mentioned here", "title": "D. Third party libraries for use in the custom script"}, {"location": "script-catalog/person_authentication/person-authentication/#e-configuring-the-acr-parameter-in-the-jans-auth-server", "text": "The acr parameter can be configured in the following ways :", "title": "E. Configuring the acr parameter in the Jans-auth server:"}, {"location": "script-catalog/person_authentication/person-authentication/#default-authentication-method", "text": "default_acr : This is the default authentication mechanism exposed to all applications that send users to the Janssen Server for sign-in. Unless an app specifically requests a different form of authentication using the OpenID Connect acr_values parameter (as specified below), users will receive the form of authentication specified in this field.", "title": "Default authentication method:"}, {"location": "script-catalog/person_authentication/person-authentication/#internal-acr", "text": "If a default ACR is not specified, Janssen will determine it based on enabled scripts and the internal user/password ACR. This internal ACR, simple_password_auth , is set to level -1. This means that it has lower priority than any scripts, so Janssen server will use it only if no other authentication method is set. Use the jans-cli to update / look-up the default authentication method .", "title": "Internal ACR"}, {"location": "script-catalog/person_authentication/person-authentication/#authentication-method-for-a-client-rp", "text": "A client may also specify default_acr_values during registration (and omit the parameter acr_values while making an authentication request).", "title": "Authentication method for a client (RP):"}, {"location": "script-catalog/person_authentication/person-authentication/#multiple-authentication-mechanisms", "text": "The Jans Server can concurrently support multiple authentication mechanisms, enabling Web and mobile apps (clients) to request a specific type of authentication using the standard OpenID Connect request parameter: acr_values . Learn more about acr_values in the OpenID Connect core spec .", "title": "Multiple Authentication Mechanisms"}, {"location": "script-catalog/person_authentication/person-authentication/#enabling-an-authentication-mechanism", "text": "An Authentication method is offered by the AS if its ACR value i.e. its corresponding custom script is enabled . By default, users will get the default authentication mechanism as specified above. However, using the OpenID Connect acr_values parameter, web and mobile clients can request any enabled authentication mechanism . Obtain the json contents of a custom script by using a jans-cli command like get-config-scripts-by-type , get-config-scripts-by-inum etc. Example : /opt/jans/jans-cli/config-cli.py --operation-id get-config-scripts-by-type --url-suffix type:PERSON_AUTHENTICATION /opt/jans/jans-cli/config-cli.py --operation-id get-config-scripts-by-inum --url-suffix inum:6122281b-b55d-4dd0-8115-b098eeeee2b7 Update the custom script and change the enabled attribute to true", "title": "Enabling an authentication mechanism"}, {"location": "script-catalog/person_authentication/person-authentication/#level-rank-of-an-authentication-mechanism", "text": "Each authentication mechanism (script) has a \"Level\" assigned to it which describes how secure and reliable it is. The higher the \"Level\", higher is the reliability represented by the script. Though several mechanisms can be enabled at the same Janssen server instance at the same time, for any specific user's session only one of them can be set as the current one (and will be returned as acr claim of id_token for them). If after initial session is created a new authorization request from a RP comes in specifying another authentication method, its \"Level\" will be compared to that of the method currently associated with this session. If requested method's \"Level\" is lower or equal to it, nothing is changed and the usual SSO behavior is observed. If it's higher (i.e. a more secure method is requested), it's not possible to serve such request using the existing session's context, and user must re-authenticate themselves to continue. If they succeed, a new session becomes associated with that requested mechanism instead.", "title": "Level (rank) of an Authentication mechanism :"}, {"location": "script-catalog/person_authentication/person-authentication/#f-using-person-authenticator-jansauthenticator-attribute", "text": "The jansAuthenticator attribute can be used in cases when person authenticator need to persist data between person logins. For example script can have enrollment and authentication flows. And after enrollment it needs to store data into user entry for later use in authentication flow. In order to search by enrolled authenticator there is another multi-valued attribute jansExtUid . This attribute has default DB index to quick search. Both attributes is recommended to use In Jans since 1.1.1 version for better compatibility in future.", "title": "F. Using person authenticator jansAuthenticator attribute :"}, {"location": "script-catalog/person_authentication/person-authentication/#1-format-of-attributes", "text": "jansExtUid: [otp:xyz1, cert:xyz2, duo:xyz3, ...] jansAuthenticator: { \"xyz1\": {\"id\": \"xyz1\", \"type\": \"otp\", \"custom\": {...}}, \"xyz2\": {\"id\": \"xyz2\", \"type\": \"cert\", \"custom\": {...}}, \"xyz3\": {\"id\": \"xyz3\", \"type\": \"duo\", \"custom\": {...}}, ... }", "title": "1. Format of attributes"}, {"location": "script-catalog/person_authentication/person-authentication/#2-sample-data", "text": "jansExtUid: [hotp:S9dO_qKQoOcpPk9GuStlNO9seoA=, cert:totp, duo:Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=] jansAuthenticator: { \"S9dO_qKQoOcpPk9GuStlNO9seoA=\": { \"id\": \"S9dO_qKQoOcpPk9GuStlNO9seoA=\", \"type\": \"hotp\", \"custom\": { \"movingFactor\": 3 } }, \"Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=\": { \"id\": \"Nv7Dg7aP0wRPJd6NHjx1ai9bN9Y=\", \"type\": \"totp\" } }", "title": "2. Sample data:"}, {"location": "script-catalog/person_authentication/person-authentication/#2-access-jansauthenticator-and-jansextuid-from-generic-bean", "text": "For both attributes there are get/set methods in User entry. After loading user object script can call these methods to get required data. ... @AttributeName(name = \"jansExtUid\") private String[] externalUid; @JsonObject @AttributeName(name = \"jansAuthenticator\") private UserAuthenticatorList authenticator ... public String[] getExternalUid() { return externalUid; } public void setExternalUid(String[] externalUid) { this.externalUid = externalUid; } public UserAuthenticatorList getAuthenticator() { return authenticator; } public void setAuthenticator(UserAuthenticatorList authenticator) { this.authenticator = authenticator; } ... UserAuthenticatorList is defined here . It contains list of UserAuthenticator objects. UserAuthenticator is defined here For convenience in 1.1.1 there is new service UserAuthenticator . See it's code here It provides next API methods: public UserAuthenticatorList getUserAuthenticatorList(SimpleUser user); public List<UserAuthenticator> getUserAuthenticatorsByType(SimpleUser user, String type); public UserAuthenticator getUserAuthenticatorById(SimpleUser user, String id); public void addUserAuthenticator(SimpleUser user, UserAuthenticator userAuthenticator); public void removeUserAuthenticator(SimpleUser user, UserAuthenticator userAuthenticator); public void removeUserAuthenticator(SimpleUser user, String type); public UserAuthenticator createUserAuthenticator(String id, String type); public UserAuthenticator createUserAuthenticator(String id, String type, Map<String, Object> custom); public String formatExternalUid(String id, String type); public boolean checkAndMigrateToAuthenticatorList(SimpleUser user); All these methods update both jansAuthenticator and jansExtUid attributes without persisting changes to DB. After calling these methods script should persist user entry. It's expected behaviour because script might update other fields too. Hence it's better to persist all changes in one update request to DB.", "title": "2. Access jansAuthenticator and jansExtUid from generic bean"}, {"location": "script-catalog/person_authentication/person-authentication/#1-default-authentication-method", "text": "default_acr : This is the default authentication mechanism exposed to all applications that send users to the Janssen Server for sign-in. Unless an app specifically requests a different form of authentication using the OpenID Connect acr_values parameter (as specified below), users will receive the form of authentication specified in this field.", "title": "1. Default authentication method:"}, {"location": "script-catalog/person_authentication/person-authentication/#usage-scenarios", "text": "", "title": "Usage scenarios"}, {"location": "script-catalog/person_authentication/person-authentication/#a-implementing-2fa-authentication-mechanisms", "text": "FIDO2 : Authentications using platform authenticators embedded into a person's device or physical USB, NFC or Bluetooth security keys that are inserted into a USB slot of a computer OTP authentication : Authentication mechanism using an app like Google authenticator , FreeOTP or Authy that implements the open standards HOTP and TOTP SMS OTP : Email OTP:", "title": "A. Implementing 2FA authentication mechanisms"}, {"location": "script-catalog/person_authentication/person-authentication/#b-implementing-multistep-authentication", "text": "Redirect to previous step : The script here an example of how the number of steps can be varied depending on the context or business requirement.", "title": "B. Implementing Multistep authentication"}, {"location": "script-catalog/person_authentication/person-authentication/#c-implementing-social-logins", "text": "You can use a PersonAuthenticationType script to allow users to sign using credentials from popular Social Identity providers or Inbound Identity Providers like Facebook, Google and Apple. After users authenticate, thier Social Identity Provider credentials are provisioned into the Jans-auth server. More on this topic in this article", "title": "C. Implementing Social logins"}, {"location": "script-catalog/person_authentication/person-authentication/#d-proactively-perform-fraud-detection", "text": "Impossible travel", "title": "D. Proactively perform fraud detection"}, {"location": "script-catalog/person_authentication/person-authentication/#testing-an-authentication-flow", "text": "An example of a complete URL looks like this - ``` https://<your.jans.server>/jans-auth/authorize.htm? \\ response_type=code&redirect_uri=https://<your.jans.server>/admin \\ &client_id=17b8b82e-b3ec-42a2-bd90-097028a37f3 \\ &scope=openid+profile+email+user_name \\ &state=faad2cdjfdddjfkdf&nonce=dajdffdfsdcfff ``` To test , enter the complete URL for authorization in a browser or create a simple webmapage with a link that simulates the user sign-in attempt. If the server is configured properly, the first page for the selected authentication method will be displayed to the user.", "title": "Testing an authentication flow"}, {"location": "script-catalog/person_authentication/person-authentication/#faqs", "text": "", "title": "FAQs"}, {"location": "script-catalog/person_authentication/person-authentication/#1-how-can-error-messages-be-displayed-on-a-web-page", "text": "FacesMessage bean is used for this purpose. from org.jans.jsf2.message import FacesMessages from org.jans.service.cdi.util import CdiUtil from javax.faces.application import FacesMessage ... facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Please enter a valid username\") The error will appear in the associated template using the following markup: ... <h:messages /> ... See an example here", "title": "1. How can error messages be displayed on a web page?"}, {"location": "script-catalog/person_authentication/person-authentication/#2-how-is-redirection-to-a-third-party-application-for-authentication-handled-in-a-script", "text": "For user authentication or consent gathering, there might be a need to redirect to a third party application to perform some operation and return the control back to authentication steps of the custom script. Please apply these steps to a person authentication script in such a scenario: Return from def getPageForStep(self, step, context), a page /auth/method_name/redirect.html ; with content similar to the code snippet below - def getPageForStep(self, step, context): return \"/auth/method_name/redirect.html\" Contents of redirect.xhtml should take the flow to prepareForStep method ... <f:metadata> <f:viewAction action=\"#{authenticator.prepareForStep}\" if=\"#{not identity.loggedIn}\" /> </f:metadata> In method prepareForStep prepare data needed for redirect and perform the redirection to the external service. def prepareForStep(self, step, context): ..... facesService = CdiUtil.bean(FacesService) facesService.redirectToExternalURL(third_party_URL ) return True In order to resume flow after the redirection, invoke a similar URL to https://my.gluu.server/postlogin.htm?param=123 from the third party app which takes the flow back to the authenticate method of the custom script. So create an xhtml page postlogin.xhtml which will look like this : <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> <html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:f=\"http://xmlns.jcp.org/jsf/core\"> <f:view transient=\"true\" contentType=\"text/html\"> <f:metadata> <f:viewAction action=\"#{authenticator.authenticateWithOutcome}\" /> </f:metadata> </f:view> </html> The <f:viewAction action=\"#{authenticator.authenticateWithOutcome}\" /> in step 4 takes us to the authenticate method inside the custom script def authenticate(self, configurationAttributes, requestParameters, step): . Here you can use parameters from request param = ServerUtil.getFirstValue(requestParameters, \"param-name\")) perform the state check (state : Opaque value used to maintain state between the request and the callback.) finally, return true or false from this method.", "title": "2. How is redirection to a third party application for authentication handled in a script?"}, {"location": "script-catalog/post_authn/post-authentication/", "tags": ["administration", "developer", "script-catalog", "PostAuthn"], "text": "Overview # After the browser has a session, if a person visits the website, the requesting party can obtain a code without the user having to authenticate or authorize. In some cases, it is desirable to insert custom business logic before granting the code or tokens from the authorization endpoint. Post Authentication script allows to force re-authentication or re-authorization (even if client is \"Pre-authorized\" or client authorization persistence is on). Interface # The post authentication script implements the PostAuthnType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def forceReAuthentication(self, context) This method is called during Authorization Request at Authorization Endpoint. If True is returned, session is set as unauthenticated and user is send for authentication. def forceAuthorization(self, context) This method is called during Authorization Request at Authorization Endpoint. If True is returned user is send for Authorization. By default if client is \"Pre-Authorized\" or \"Client Persist Authorizations\" is on, authorization is skipped. This script has higher priority and can cancel Pre-Authorization and persisted authorizations. Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference Use case: Dummy Post Authentication script (does not force re-authentication) # This was adapted from Gluu Post Authentication script example . Script Type: Python # from io.jans.model.custom.script.type.postauthn import PostAuthnType class PostAuthn ( PostAuthnType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Post Authn script. Initializing ...\" print \"Post Authn script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Post Authn script. Destroying ...\" print \"Post Authn script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def forceReAuthentication ( self , context ): return False def forceAuthorization ( self , context ): return False Script Type: Java # import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.postauthn.PostAuthnType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class PostAuthn implements PostAuthnType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Initializing...\" ); log . info ( \"Post Authentication. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Initializing...\" ); log . info ( \"Post Authentication. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Destroying...\" ); log . info ( \"Post Authentication. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean forceReAuthentication ( Object context ) { return false ; } @Override public boolean forceAuthorization ( Object context ) { return false ; } }", "title": "Post Authentication"}, {"location": "script-catalog/post_authn/post-authentication/#overview", "text": "After the browser has a session, if a person visits the website, the requesting party can obtain a code without the user having to authenticate or authorize. In some cases, it is desirable to insert custom business logic before granting the code or tokens from the authorization endpoint. Post Authentication script allows to force re-authentication or re-authorization (even if client is \"Pre-authorized\" or client authorization persistence is on).", "title": "Overview"}, {"location": "script-catalog/post_authn/post-authentication/#interface", "text": "The post authentication script implements the PostAuthnType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/post_authn/post-authentication/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/post_authn/post-authentication/#new-methods", "text": "Method header Method description def forceReAuthentication(self, context) This method is called during Authorization Request at Authorization Endpoint. If True is returned, session is set as unauthenticated and user is send for authentication. def forceAuthorization(self, context) This method is called during Authorization Request at Authorization Endpoint. If True is returned user is send for Authorization. By default if client is \"Pre-Authorized\" or \"Client Persist Authorizations\" is on, authorization is skipped. This script has higher priority and can cancel Pre-Authorization and persisted authorizations.", "title": "New Methods"}, {"location": "script-catalog/post_authn/post-authentication/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/post_authn/post-authentication/#use-case-dummy-post-authentication-script-does-not-force-re-authentication", "text": "This was adapted from Gluu Post Authentication script example .", "title": "Use case: Dummy Post Authentication script (does not force re-authentication)"}, {"location": "script-catalog/post_authn/post-authentication/#script-type-python", "text": "from io.jans.model.custom.script.type.postauthn import PostAuthnType class PostAuthn ( PostAuthnType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Post Authn script. Initializing ...\" print \"Post Authn script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Post Authn script. Destroying ...\" print \"Post Authn script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 def forceReAuthentication ( self , context ): return False def forceAuthorization ( self , context ): return False", "title": "Script Type: Python"}, {"location": "script-catalog/post_authn/post-authentication/#script-type-java", "text": "import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.postauthn.PostAuthnType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class PostAuthn implements PostAuthnType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Initializing...\" ); log . info ( \"Post Authentication. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Initializing...\" ); log . info ( \"Post Authentication. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Post Authentication. Destroying...\" ); log . info ( \"Post Authentication. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean forceReAuthentication ( Object context ) { return false ; } @Override public boolean forceAuthorization ( Object context ) { return false ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/", "tags": ["administration", "developer", "script-catalog", "ResourceOwnerPasswordCredentials"], "text": "Overview # Resource Owner Password Credentials script allows modifying the behavior of Resource Owner Password Credentials Grant ( RFC 6749 ). The script is invoked after normal authentication and can either leave current result or change it - authenticate if not authenticated - it should return True and optionally set user (via context.setUser(user) ). Interface # The ROPC script implements the ResourceOwnerPasswordCredentialsType interface. This extends methods from the base script type in addition to adding new method: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def authenticate(self, context) This method is called after normal ROPC authentication. This method can cancel normal authentication if it returns false and sets context.setUser(null) Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference Use case: Basic ROPC authentication script # This script has been adapted from the Gluu Server sample ROPC script Main usage of script is at Token Endpoint. However sometimes it can be useful to use ROPC custom script at Authorization Endpoint to avoid redirects and pages. By default it is not enabled but it can be enabled if set forceRopcInAuthorizationEndpoint AS configuration property to true . Also it is required to set user in context in custom script ( context.setUser(<user>) ). Without it authorization will go on in normal way (with pages and redirects). Script Type: Python # from io.jans.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType from io.jans.as.server.service import AuthenticationService from io.jans.service.cdi.util import CdiUtil from java.lang import String class ResourceOwnerPasswordCredentials ( ResourceOwnerPasswordCredentialsType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"ROPC script. Initializing ...\" self . usernameParamName = \"username\" self . passwordParamName = \"password\" print \"ROPC script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"ROPC script. Destroying ...\" print \"ROPC script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns True and set user into context when user authenticated succesfully # Returns False when user not authenticated or it's needed to cancel notmal flow def authenticate ( self , context ): print \"ROPC script. Authenticate\" deviceIdParam = context . getHttpRequest () . getParameterValues ( \"device_id\" ) if deviceIdParam != None and ( deviceIdParam . length > 0 ): result = deviceIdParam [ 0 ] == \"device_id_1\" if not result : return False # Set authenticated user in context # context.setUser(user) return True # Do generic authentication in other cases authService = CdiUtil . bean ( AuthenticationService ) username = context . getHttpRequest () . getParameter ( self . usernameParamName ) password = context . getHttpRequest () . getParameter ( self . passwordParamName ) result = authService . authenticate ( username , password ) if not result : print \"ROPC script. Authenticate. Could not authenticate user ' %s ' \" % username return False context . setUser ( authService . getAuthenticatedUser ()) return True Script Type: Java # import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.owner.ResourceOwnerPasswordCredentialsType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.AuthenticationService ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.as.server.service.external.context.ExternalResourceOwnerPasswordCredentialsContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class ResourceOwnerPasswordCredentials implements ResourceOwnerPasswordCredentialsType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); private final String usernameParamName = \"username\" ; private final String passwordParamName = \"password\" ; @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Destroying...\" ); log . info ( \"ROPC Script. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean authenticate ( Object context ) { log . info ( \"ROPC script. Authenticate\" ); ExternalResourceOwnerPasswordCredentialsContext ropcContext = ( ExternalResourceOwnerPasswordCredentialsContext ) context ; String [] deviceIdParam = ropcContext . getHttpRequest (). getParameterValues ( \"device_id\" ); if ( deviceIdParam != null && deviceIdParam . length > 0 ) { boolean result = deviceIdParam [ 0 ] == \"device_id_1\" ; if ( ! result ) { return false ; } // Set authenticated user in context // context.setUser(user) return true ; } // generic authentication in other cases AuthenticationService authService = CdiUtil . bean ( AuthenticationService . class ); String username = ropcContext . getHttpRequest (). getParameter ( usernameParamName ); String password = ropcContext . getHttpRequest (). getParameter ( passwordParamName ); boolean result = authService . authenticate ( username , password ); if ( ! result ) { log . info ( \"ROPC script. Authenticate. Could not authenticate \" + username ); return false ; } ropcContext . setUser ( authService . getAuthenticatedUser ()); return true ; } } Sample Scripts # Super Gluu ROPW Script 3 Step ROPW Script", "title": "Resource Owner Password Credentials"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#overview", "text": "Resource Owner Password Credentials script allows modifying the behavior of Resource Owner Password Credentials Grant ( RFC 6749 ). The script is invoked after normal authentication and can either leave current result or change it - authenticate if not authenticated - it should return True and optionally set user (via context.setUser(user) ).", "title": "Overview"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#interface", "text": "The ROPC script implements the ResourceOwnerPasswordCredentialsType interface. This extends methods from the base script type in addition to adding new method:", "title": "Interface"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#new-methods", "text": "Method header Method description def authenticate(self, context) This method is called after normal ROPC authentication. This method can cancel normal authentication if it returns false and sets context.setUser(null)", "title": "New Methods"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference", "title": "Objects"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#use-case-basic-ropc-authentication-script", "text": "This script has been adapted from the Gluu Server sample ROPC script Main usage of script is at Token Endpoint. However sometimes it can be useful to use ROPC custom script at Authorization Endpoint to avoid redirects and pages. By default it is not enabled but it can be enabled if set forceRopcInAuthorizationEndpoint AS configuration property to true . Also it is required to set user in context in custom script ( context.setUser(<user>) ). Without it authorization will go on in normal way (with pages and redirects).", "title": "Use case: Basic ROPC authentication script"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#script-type-python", "text": "from io.jans.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType from io.jans.as.server.service import AuthenticationService from io.jans.service.cdi.util import CdiUtil from java.lang import String class ResourceOwnerPasswordCredentials ( ResourceOwnerPasswordCredentialsType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"ROPC script. Initializing ...\" self . usernameParamName = \"username\" self . passwordParamName = \"password\" print \"ROPC script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"ROPC script. Destroying ...\" print \"ROPC script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns True and set user into context when user authenticated succesfully # Returns False when user not authenticated or it's needed to cancel notmal flow def authenticate ( self , context ): print \"ROPC script. Authenticate\" deviceIdParam = context . getHttpRequest () . getParameterValues ( \"device_id\" ) if deviceIdParam != None and ( deviceIdParam . length > 0 ): result = deviceIdParam [ 0 ] == \"device_id_1\" if not result : return False # Set authenticated user in context # context.setUser(user) return True # Do generic authentication in other cases authService = CdiUtil . bean ( AuthenticationService ) username = context . getHttpRequest () . getParameter ( self . usernameParamName ) password = context . getHttpRequest () . getParameter ( self . passwordParamName ) result = authService . authenticate ( username , password ) if not result : print \"ROPC script. Authenticate. Could not authenticate user ' %s ' \" % username return False context . setUser ( authService . getAuthenticatedUser ()) return True", "title": "Script Type: Python"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#script-type-java", "text": "import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.owner.ResourceOwnerPasswordCredentialsType ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.service.AuthenticationService ; import io.jans.service.cdi.util.CdiUtil ; import io.jans.as.server.service.external.context.ExternalResourceOwnerPasswordCredentialsContext ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class ResourceOwnerPasswordCredentials implements ResourceOwnerPasswordCredentialsType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); private final String usernameParamName = \"username\" ; private final String passwordParamName = \"password\" ; @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Initializing...\" ); log . info ( \"ROPC Script. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"ROPC Script. Destroying...\" ); log . info ( \"ROPC Script. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean authenticate ( Object context ) { log . info ( \"ROPC script. Authenticate\" ); ExternalResourceOwnerPasswordCredentialsContext ropcContext = ( ExternalResourceOwnerPasswordCredentialsContext ) context ; String [] deviceIdParam = ropcContext . getHttpRequest (). getParameterValues ( \"device_id\" ); if ( deviceIdParam != null && deviceIdParam . length > 0 ) { boolean result = deviceIdParam [ 0 ] == \"device_id_1\" ; if ( ! result ) { return false ; } // Set authenticated user in context // context.setUser(user) return true ; } // generic authentication in other cases AuthenticationService authService = CdiUtil . bean ( AuthenticationService . class ); String username = ropcContext . getHttpRequest (). getParameter ( usernameParamName ); String password = ropcContext . getHttpRequest (). getParameter ( passwordParamName ); boolean result = authService . authenticate ( username , password ); if ( ! result ) { log . info ( \"ROPC script. Authenticate. Could not authenticate \" + username ); return false ; } ropcContext . setUser ( authService . getAuthenticatedUser ()); return true ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/resource_owner_password_credentials/ropc/#sample-scripts", "text": "Super Gluu ROPW Script 3 Step ROPW Script", "title": "Sample Scripts"}, {"location": "script-catalog/revoke_token/revoke-token/", "tags": ["administration", "developer", "script-catalog", "RevokeToken"], "text": "Overview # Revoke Token scripts allow injecting custom logic during token revocation. Interface # The revoke token script implements the RevokeTokenType interface. This extends methods from the base script type in addition to adding new method: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def revoke(self, context) Token is revoked if this method returns True, skipped otherwise Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Reference Use Case: Basic Token Revocation # This script has been adapted from the Gluu Server sample revoke token script . Script Type: Python # from io.jans.model.custom.script.type.revoke import RevokeTokenType from java.lang import String class RevokeToken ( RevokeTokenType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Revoke Token script. Initializing ...\" print \"Revoke Token script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Revoke Token script. Destroying ...\" print \"Revoke Token script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # This method is called during Revoke Token call. # If True is returned, token is revoked. If False is returned, revoking is skipped. def revoke ( self , context ): return True Script Type: Java # import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.revoke.RevokeTokenType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class RevokeToken implements RevokeTokenType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Initializing...\" ); log . info ( \"Token Revoke. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Initializing...\" ); log . info ( \"Token Revoke. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Destroying...\" ); log . info ( \"Token Revoke. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean revoke ( Object context ) { return true ; } } This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Revoke Token"}, {"location": "script-catalog/revoke_token/revoke-token/#overview", "text": "Revoke Token scripts allow injecting custom logic during token revocation.", "title": "Overview"}, {"location": "script-catalog/revoke_token/revoke-token/#interface", "text": "The revoke token script implements the RevokeTokenType interface. This extends methods from the base script type in addition to adding new method:", "title": "Interface"}, {"location": "script-catalog/revoke_token/revoke-token/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/revoke_token/revoke-token/#new-methods", "text": "Method header Method description def revoke(self, context) Token is revoked if this method returns True, skipped otherwise", "title": "New Methods"}, {"location": "script-catalog/revoke_token/revoke-token/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Reference", "title": "Objects"}, {"location": "script-catalog/revoke_token/revoke-token/#use-case-basic-token-revocation", "text": "This script has been adapted from the Gluu Server sample revoke token script .", "title": "Use Case: Basic Token Revocation"}, {"location": "script-catalog/revoke_token/revoke-token/#script-type-python", "text": "from io.jans.model.custom.script.type.revoke import RevokeTokenType from java.lang import String class RevokeToken ( RevokeTokenType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Revoke Token script. Initializing ...\" print \"Revoke Token script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Revoke Token script. Destroying ...\" print \"Revoke Token script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # This method is called during Revoke Token call. # If True is returned, token is revoked. If False is returned, revoking is skipped. def revoke ( self , context ): return True", "title": "Script Type: Python"}, {"location": "script-catalog/revoke_token/revoke-token/#script-type-java", "text": "import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.revoke.RevokeTokenType ; import io.jans.service.custom.script.CustomScriptManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class RevokeToken implements RevokeTokenType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Initializing...\" ); log . info ( \"Token Revoke. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Initializing...\" ); log . info ( \"Token Revoke. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"Token Revoke. Destroying...\" ); log . info ( \"Token Revoke. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public boolean revoke ( Object context ) { return true ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/revoke_token/revoke-token/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/revoke_token/revoke-token/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/revoke_token/revoke-token/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/scim/scim/", "tags": ["administration", "developer", "script-catalog"], "text": "SCIM Guide # Overview # SCIM script allows you to execute custom logic when certain SCIM API operations are invoked. With SCIM scripts, custom business logic can be executed when several of the SCIM API operations are invoked. This is useful in many situations, for example: Trigger notifications to external systems when certain resources are deleted Alter the actual responses the service produces Attach additional information to resources when they are created or updated Implement a fine-grained level of access to resources so different callers have permission to handle only a restricted number of resources Notes: # In this document, the term resources refer to those \"entities\" the service can manage, for instance, users or groups The term operation refers to any SCIM functionality accessible through its HTTP endpoints Basic development skills are assumed. Some grasp of Java and Python are required as well as understanding of the SCIM protocol. Interface # Methods # API Overview Custom scripts adhere to a simple API (ie. a well-defined collection of methods/routines) that is described in the following. It is advised to check the dummy script provided here as you read this section. Scripts' config properties All methods contain a configurationAttributes parameter, this gives access to the configuration properties of the script itself. This is a relevant aspect of Gluu scripts: they are all parameterizable!. configurationAttributes is a java.util.Map<String, SimpleCustomProperty> and here is how SimpleCustomProperty looks. Basic Methods These are methods not related to SCIM operations but still play key roles: |Method Name|Description|Return Value| |:---|:---|:---| | init |Called when the (SCIM) service starts and every time the script properties or code changes|A boolean value describing success or failure| | destroy |Called every time the script properties or code changes (called before init )|A boolean value describing success or failure| | getApiVersion |Determines what methods are effectively called when SCIM endpoints are invoked|A positive integer| Pre-resource Modification They are called when the resource is about to be persisted. The second parameter in these methods hold the object that will be persisted to permanent storage, thus any change or manipulation upon the object will be reflected in the underlying database (as well as in the output of the SCIM operation call itself). These methods are called regardless of the API version used. Names are self explanatory: Methods 2nd param 2nd param Class/Link createUser , updateUser , deleteUser user ScimCustomPerson createGroup , updateGroup , deleteGroup group GluuGroup Pre-resource modification methods return a boolean. A False value aborts the corresponding SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that update* methods are called for both SCIM PUT and PATCH operations. Post-resource Modification They are called after the resource is persisted. The second parameter in these methods hold the object that was saved. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 2. Methods 2nd param 2nd param Class/Link postCreateUser , postUpdateUser , postDeleteUser user ScimCustomPerson postCreateGroup , postUpdateGroup , postDeleteGroup group GluuGroup Post-resource modification methods return a boolean. A False value aborts the corresponding SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that postUpdate* methods are called for both SCIM PUT and PATCH operations. Single Resource Retrieval These apply for SCIM operations that retrieve a resource by ID. They are called after the resource has been obtained from the database. The second parameter in these methods hold a reference to such object. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 3. Methods 2nd param 2nd param Class/Link getUser user ScimCustomPerson getGroup group GluuGroup Single resource retrieval methods return a boolean. A False value aborts the whole SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Multiple Resources Retrieval These apply for SCIM search operations. They are called after the results have been obtained from the database. The second parameter in these methods hold a reference to such result set. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 4. Methods 2nd param 2nd param Class/Link postSearchUsers results PagedResult postSearchGroups results PagedResult Multiple resources retrieval methods return a boolean. A False value aborts the whole SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that searching using the root .search SCIM endpoint will trigger calls to both of the methods listed. Advanced control These are alternative methods that allow to tweak the response the service produces. They can be employed to introduce complex business rules when operations are executed. These methods are called if getApiVersion returns a number >= 5. Methods manageResourceOperation manageSearchOperation Example: Modifying Search Results # SCIM spec defines the concept of attribute returnability where some attributes should never be part of a response (like passwords), always be returned (like resource identifiers), or be returned by default unless otherwise stated by the excludedAttributes parameter. Assume you are maintaining a user base of secret agents that work for your company and need to avoid exposing information such as their physical addresses for safety reasons. To keep it simple let's restrict the scope to user searches only. In practice you should take steps to hide this data on user retrieval and update. Let's alter postSearchUsers 's second parameter ( results ) to ensure addresses are not leaked: for user in results . getEntries () : user . setAttribute ( \"jansAddress\" , None ) This is very straightforward code except for the usage of jansAddress . Shouldn't it be simply addresses as the known SCIM attribute? Scripts work with entities that are about to be persisted or have already been saved so they kind of resemble the database structure (schema in MySQL terms). It turns out that database attribute names rarely match with SCIM names. While it is easy to know the SCIM name of a database attribute, the converse requires checking the code, however since you already have the skill this shouldn't be a problem: in this Java class you'll find the representation of a user resource in SCIM spec terms. Pay attention to the addresses field and its associated StoreReference annotation that contains the attribute where addresses are actually stored. With that said, save your modifications. You may like the idea of adding some prints for enlightment like: print \"%d entries returned of %d\" % ( results . getEntriesCount () , results . getTotalEntriesCount ()) for user in results . getEntries () : print \"Flushing addresses for user %s\" % user . getUid () user . setAttribute ( \"jansAddress\" , None ) Ensure no addresses are returned anymore in your SCIM user searches. Happy testing! Controlling execution of SCIM operations # With the manageResourceOperation and manageSearchOperation methods you can make complex decisions on how processing should take place based on contextual data and the incoming payload. manageResourceOperation This method is invoked when any following operations are executed: resource creation, modification, removal and retrieval by ID. In case of bulks, the method is called for every operation that fits into these categories. Parameters are described in the table below: Name Description Class/Link context Provides contextual information about the SCIM operation being called such as type of resource involved, HTTP verb, request headers, query params, etc. OperationContext entity A non-null object representing the resource involved A descendant of Entry . If the resource is a user, it will be an instance of ScimCustomPerson . In case of a group, it will be a GluuGroup payload The payload sent in the invocation; null when the operation is removal or retrieval by ID The datatype depends on the operation called. Check the interface that suits best and inspect the first parameter's datatype. The class will belong to some subpackage inside io.jans.scim.model.scim2 This method is expected to return an instance of javax.ws.rs.core.Response that supersedes the output of the operation itself. In other words, the actual processing of the operation is skipped in favor of the code supplied here. However note that minor validations may take place in the payload before your code is actually called. Returning None transfers the control of the operation for normal processing (default Jans implementation). If the method execution crashes at runtime, a 500 HTTP error is sent. Notes: Possible values for context.getResourceType() are: User, Group, FidoDevice, Fido2Device context.getTokenDetails().getValue() is a shortcut that will give you the access token the caller employed to issue the service call Both context.getTokenDetails().getTokenType() and context.getTokenDetails().getScope() return non null values when the protection mechanism of the API is OAuth or test mode Note that for resource creation operation, entity basically contains the same data supplied in the POST payload . In this case, entity has not originated from the database and has not been persisted either For the case of modification, retrieval and removal, entity contains the data currently stored in the database for the resource in question Since many values come from Java code, you can always do getClass().getName() to get an idea of what type of variables you are dealing with To build custom error responses your can reuse some of the getErrorResponse methods of class BaseScimWebService This method offers a high degree of flexibility. Perform careful testing of your code and account all potential scenarios. manageSearchOperation This method is invoked when resource searches are performed. Parameters are described in the table below: name Description Class/Link context Provides contextual information about the SCIM operation being called such as type of resource involved, HTTP verb, request headers, query params, etc. OperationContext searchRequest An object representing the search parameters provided in the call (applies for both GET and POST) SearchRequest Unlike manageResourceOperation , no entity parameter is passed. This is so because making decisions based on already executed searches would have a performance impact. Instead you can use context.setFilterPrepend(...) to help restrict the search against the database: here you can pass a String value that will be interpreted as an SCIM filter expression (see section 3.4.2.2 of RFC 7644). When the search being performed already contains a search filter (i.e. searchRequest.getFilter() is non-empty), a new filter is created by appending both \"subfilters\" with an and operator. As in the case of manageResourceOperation this method is expected to return an instance of javax.ws.rs.core.Response . Returning None transfers the control of the operation for normal processing (the Jans implementation). If the method execution crashes at runtime, a 500 HTTP error is sent. The same recommendations given for manageResourceOperation apply here. If you build filter expressions in your method, ensure they are syntactically valid to avoid your callers getting unexpected \"invalidFilter\" 400 errors. Example: segmenting the user base Let's assume you make use of the SCIM attribute userType so that your user base is partitioned into three disjoint segments according to such attribute and you have designated its possible values to be: Contractor, Employee, or Intern. Suppose your company has three different applications that make management of users in every category, that is, only one application is devoted to manage contractors, another employees, and other interns. You are interested in consistently granting access so that no application can create, query or modify users that don't belong to its focus. To properly handle this multi-tenancy scenario, you decide to use the contextual information coming from every request to determine if the operation should be allowed or not. For this purpose you communicate every application developer to send an additional HTTP header in their call with a value that only you (the administrator) and the developer knows. Let's call it the \"secret\". For the sake of simplicity let's assume developers are external to the company and only you know their identities. They don't know each other so they cannot exchange secrets. The strategy to implement segmentation is rather simple: Alter the default SCIM script by supplying a custom implementation for the methods that control execution Make the HTTP header name be a configuration property of the script so that it is not hard-coded Add a configuration property that contains the mapping of userType value vs. expected header value in JSON format Adding and parsing config properties Using Jans Config CLI update the SCIM script and add properties: custom_header with value USER-SEGMENT-SECRET access_map with value { \"<random_string>\":\"Contractor\", \"<random_string>\":\"Employee\", \"<random_string>\":\"Intern\" } Save the changes. In the init method this properties should be parsed. To start, let's add some imports: from io.jans.scim.ws.rs.scim2 import BaseScimWebService import json Here is how init would look like: def init ( self , configurationAttributes ): self . custom_header = configurationAttributes . get ( \"custom_header\" ) . getValue2 () access_map_json = configurationAttributes . get ( \"access_map\" ) . getValue2 () self . access_map = json . loads ( access_map_json ) print \"ScimEventHandler (init): Initialized successfully\" return True Note no validations took place here: we assumed the script contains the properties, that they are non empty and have sensible values. Allow/Deny resource operations The first step is to know the kind of application that is calling our service. For this purpose let's create a method that given incoming request headers returns the matching userType # headers params is an instance of javax . ws . rs . core . MultivaluedMap < String , String > def getUserType ( self , headers ) : secret = headers . getFirst ( self . custom_header ) if secret in self . access_map : return self . access_map [ secret ] else : return None Now let's code manageResourceOperation . We should allow access only under the following conditions: The getUserType method does not return None The entity object ( ScimCustomPerson instance) has a proper userType value. This means that for user creation, the incoming payload comes with a matching userType and for the other cases, the already stored attribute matches as well Assume that if the operation invoked is not user-related, we should allow access freely. Here is how the implementation might look: def manageResourceOperation ( self , context , entity , payload , configurationAttributes ): print \"manageResourceOperation. SCIM endpoint invoked is %s (HTTP %s )\" % ( context . getPath (), context . getMethod ()) if context . getResourceType () != \"User\" : return None expected_user_type = self . getUserType ( context . getRequestHeaders ()) if expected_user_type != None and entity . getAttribute ( \"jansUsrTyp\" ) == expected_user_type : return None else : return BaseScimWebService . getErrorResponse ( 403 , None , \"Attempt to handle a not allowed user type\" ) Note no usage of the payload took place. A case you may like to evaluate is where mistakenly using an update operation, the userType is set to an unexpected value. Allow/Deny searches This time instead of inspecting an entity, we ought to make a filter expression to restrict the search when the database is queried. For your reference, a valid filter expression is for instance userType eq \"Contractor\" . def manageSearchOperation ( self , context , searchRequest , configurationAttributes ) : print \"manageSearchOperation. SCIM endpoint invoked is %s (HTTP %s)\" % ( context . getPath () , context . getMethod ()) resource_type = context . getResourceType () print \"manageSearchOperation. This is a search over %s resources\" % resource_type if resource_type != \"User\" : return None expected_user_type = self . getUserType ( context . getRequestHeaders ()) if expected_user_type != None : context . setFilterPrepend ( \"userType eq \\\" % s \\ \"\" % expected_user_type ) return None else : return BaseScimWebService . getErrorResponse ( 403 , None , \"Attempt to handle a not allowed user type\" ) The manageSearchOperation must return a javax.ws.rs.core.Response . A None value makes continue the operation processing normally. Working with more than one script # You may have already noticed that it is possible to have several scripts under the SCIM type. This is how execution takes place when there are several scripts enabled: The applicable method is called in the first script. If the return value was True , the method is called again but this time in the subsequent script. If at any point a False return value is encountered, the SCIM operation is aborted with error 500. This means that a normal operation execution requires all involved methods across different scripts to be successful. There is an important exception to the above and is related to the manage* methods. In this case, only one script takes effect (the first script found). Note that in most cases having a single SCIM script suffices for all needs. Common Use Cases # Script Type: Python # Custom SCIM Event Handler # Find the script here The sample code snippet shows how to - 1. Modify Search Results 2. Segment the user base 3. Allow/Deny resource operations 4. Allow/Deny searches Script Type: Java # Custom SCIM Event Handler # Find the code here The sample code snippet shows how to - 1. Modify Search Results 2. Segment the user base 3. Allow/Deny resource operations 4. Allow/Deny searches", "title": "SCIM"}, {"location": "script-catalog/scim/scim/#scim-guide", "text": "", "title": "SCIM Guide"}, {"location": "script-catalog/scim/scim/#overview", "text": "SCIM script allows you to execute custom logic when certain SCIM API operations are invoked. With SCIM scripts, custom business logic can be executed when several of the SCIM API operations are invoked. This is useful in many situations, for example: Trigger notifications to external systems when certain resources are deleted Alter the actual responses the service produces Attach additional information to resources when they are created or updated Implement a fine-grained level of access to resources so different callers have permission to handle only a restricted number of resources", "title": "Overview"}, {"location": "script-catalog/scim/scim/#notes", "text": "In this document, the term resources refer to those \"entities\" the service can manage, for instance, users or groups The term operation refers to any SCIM functionality accessible through its HTTP endpoints Basic development skills are assumed. Some grasp of Java and Python are required as well as understanding of the SCIM protocol.", "title": "Notes:"}, {"location": "script-catalog/scim/scim/#interface", "text": "", "title": "Interface"}, {"location": "script-catalog/scim/scim/#methods", "text": "API Overview Custom scripts adhere to a simple API (ie. a well-defined collection of methods/routines) that is described in the following. It is advised to check the dummy script provided here as you read this section. Scripts' config properties All methods contain a configurationAttributes parameter, this gives access to the configuration properties of the script itself. This is a relevant aspect of Gluu scripts: they are all parameterizable!. configurationAttributes is a java.util.Map<String, SimpleCustomProperty> and here is how SimpleCustomProperty looks. Basic Methods These are methods not related to SCIM operations but still play key roles: |Method Name|Description|Return Value| |:---|:---|:---| | init |Called when the (SCIM) service starts and every time the script properties or code changes|A boolean value describing success or failure| | destroy |Called every time the script properties or code changes (called before init )|A boolean value describing success or failure| | getApiVersion |Determines what methods are effectively called when SCIM endpoints are invoked|A positive integer| Pre-resource Modification They are called when the resource is about to be persisted. The second parameter in these methods hold the object that will be persisted to permanent storage, thus any change or manipulation upon the object will be reflected in the underlying database (as well as in the output of the SCIM operation call itself). These methods are called regardless of the API version used. Names are self explanatory: Methods 2nd param 2nd param Class/Link createUser , updateUser , deleteUser user ScimCustomPerson createGroup , updateGroup , deleteGroup group GluuGroup Pre-resource modification methods return a boolean. A False value aborts the corresponding SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that update* methods are called for both SCIM PUT and PATCH operations. Post-resource Modification They are called after the resource is persisted. The second parameter in these methods hold the object that was saved. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 2. Methods 2nd param 2nd param Class/Link postCreateUser , postUpdateUser , postDeleteUser user ScimCustomPerson postCreateGroup , postUpdateGroup , postDeleteGroup group GluuGroup Post-resource modification methods return a boolean. A False value aborts the corresponding SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that postUpdate* methods are called for both SCIM PUT and PATCH operations. Single Resource Retrieval These apply for SCIM operations that retrieve a resource by ID. They are called after the resource has been obtained from the database. The second parameter in these methods hold a reference to such object. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 3. Methods 2nd param 2nd param Class/Link getUser user ScimCustomPerson getGroup group GluuGroup Single resource retrieval methods return a boolean. A False value aborts the whole SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Multiple Resources Retrieval These apply for SCIM search operations. They are called after the results have been obtained from the database. The second parameter in these methods hold a reference to such result set. Any change or manipulation upon the object will not be reflected in the underlying database, but may still modify the service response. These methods are called if getApiVersion returns a number >= 4. Methods 2nd param 2nd param Class/Link postSearchUsers results PagedResult postSearchGroups results PagedResult Multiple resources retrieval methods return a boolean. A False value aborts the whole SCIM operation and a 500 error is returned. The same applies if the method execution crashes at runtime. Note that searching using the root .search SCIM endpoint will trigger calls to both of the methods listed. Advanced control These are alternative methods that allow to tweak the response the service produces. They can be employed to introduce complex business rules when operations are executed. These methods are called if getApiVersion returns a number >= 5. Methods manageResourceOperation manageSearchOperation", "title": "Methods"}, {"location": "script-catalog/scim/scim/#example-modifying-search-results", "text": "SCIM spec defines the concept of attribute returnability where some attributes should never be part of a response (like passwords), always be returned (like resource identifiers), or be returned by default unless otherwise stated by the excludedAttributes parameter. Assume you are maintaining a user base of secret agents that work for your company and need to avoid exposing information such as their physical addresses for safety reasons. To keep it simple let's restrict the scope to user searches only. In practice you should take steps to hide this data on user retrieval and update. Let's alter postSearchUsers 's second parameter ( results ) to ensure addresses are not leaked: for user in results . getEntries () : user . setAttribute ( \"jansAddress\" , None ) This is very straightforward code except for the usage of jansAddress . Shouldn't it be simply addresses as the known SCIM attribute? Scripts work with entities that are about to be persisted or have already been saved so they kind of resemble the database structure (schema in MySQL terms). It turns out that database attribute names rarely match with SCIM names. While it is easy to know the SCIM name of a database attribute, the converse requires checking the code, however since you already have the skill this shouldn't be a problem: in this Java class you'll find the representation of a user resource in SCIM spec terms. Pay attention to the addresses field and its associated StoreReference annotation that contains the attribute where addresses are actually stored. With that said, save your modifications. You may like the idea of adding some prints for enlightment like: print \"%d entries returned of %d\" % ( results . getEntriesCount () , results . getTotalEntriesCount ()) for user in results . getEntries () : print \"Flushing addresses for user %s\" % user . getUid () user . setAttribute ( \"jansAddress\" , None ) Ensure no addresses are returned anymore in your SCIM user searches. Happy testing!", "title": "Example: Modifying Search Results"}, {"location": "script-catalog/scim/scim/#controlling-execution-of-scim-operations", "text": "With the manageResourceOperation and manageSearchOperation methods you can make complex decisions on how processing should take place based on contextual data and the incoming payload. manageResourceOperation This method is invoked when any following operations are executed: resource creation, modification, removal and retrieval by ID. In case of bulks, the method is called for every operation that fits into these categories. Parameters are described in the table below: Name Description Class/Link context Provides contextual information about the SCIM operation being called such as type of resource involved, HTTP verb, request headers, query params, etc. OperationContext entity A non-null object representing the resource involved A descendant of Entry . If the resource is a user, it will be an instance of ScimCustomPerson . In case of a group, it will be a GluuGroup payload The payload sent in the invocation; null when the operation is removal or retrieval by ID The datatype depends on the operation called. Check the interface that suits best and inspect the first parameter's datatype. The class will belong to some subpackage inside io.jans.scim.model.scim2 This method is expected to return an instance of javax.ws.rs.core.Response that supersedes the output of the operation itself. In other words, the actual processing of the operation is skipped in favor of the code supplied here. However note that minor validations may take place in the payload before your code is actually called. Returning None transfers the control of the operation for normal processing (default Jans implementation). If the method execution crashes at runtime, a 500 HTTP error is sent. Notes: Possible values for context.getResourceType() are: User, Group, FidoDevice, Fido2Device context.getTokenDetails().getValue() is a shortcut that will give you the access token the caller employed to issue the service call Both context.getTokenDetails().getTokenType() and context.getTokenDetails().getScope() return non null values when the protection mechanism of the API is OAuth or test mode Note that for resource creation operation, entity basically contains the same data supplied in the POST payload . In this case, entity has not originated from the database and has not been persisted either For the case of modification, retrieval and removal, entity contains the data currently stored in the database for the resource in question Since many values come from Java code, you can always do getClass().getName() to get an idea of what type of variables you are dealing with To build custom error responses your can reuse some of the getErrorResponse methods of class BaseScimWebService This method offers a high degree of flexibility. Perform careful testing of your code and account all potential scenarios. manageSearchOperation This method is invoked when resource searches are performed. Parameters are described in the table below: name Description Class/Link context Provides contextual information about the SCIM operation being called such as type of resource involved, HTTP verb, request headers, query params, etc. OperationContext searchRequest An object representing the search parameters provided in the call (applies for both GET and POST) SearchRequest Unlike manageResourceOperation , no entity parameter is passed. This is so because making decisions based on already executed searches would have a performance impact. Instead you can use context.setFilterPrepend(...) to help restrict the search against the database: here you can pass a String value that will be interpreted as an SCIM filter expression (see section 3.4.2.2 of RFC 7644). When the search being performed already contains a search filter (i.e. searchRequest.getFilter() is non-empty), a new filter is created by appending both \"subfilters\" with an and operator. As in the case of manageResourceOperation this method is expected to return an instance of javax.ws.rs.core.Response . Returning None transfers the control of the operation for normal processing (the Jans implementation). If the method execution crashes at runtime, a 500 HTTP error is sent. The same recommendations given for manageResourceOperation apply here. If you build filter expressions in your method, ensure they are syntactically valid to avoid your callers getting unexpected \"invalidFilter\" 400 errors. Example: segmenting the user base Let's assume you make use of the SCIM attribute userType so that your user base is partitioned into three disjoint segments according to such attribute and you have designated its possible values to be: Contractor, Employee, or Intern. Suppose your company has three different applications that make management of users in every category, that is, only one application is devoted to manage contractors, another employees, and other interns. You are interested in consistently granting access so that no application can create, query or modify users that don't belong to its focus. To properly handle this multi-tenancy scenario, you decide to use the contextual information coming from every request to determine if the operation should be allowed or not. For this purpose you communicate every application developer to send an additional HTTP header in their call with a value that only you (the administrator) and the developer knows. Let's call it the \"secret\". For the sake of simplicity let's assume developers are external to the company and only you know their identities. They don't know each other so they cannot exchange secrets. The strategy to implement segmentation is rather simple: Alter the default SCIM script by supplying a custom implementation for the methods that control execution Make the HTTP header name be a configuration property of the script so that it is not hard-coded Add a configuration property that contains the mapping of userType value vs. expected header value in JSON format Adding and parsing config properties Using Jans Config CLI update the SCIM script and add properties: custom_header with value USER-SEGMENT-SECRET access_map with value { \"<random_string>\":\"Contractor\", \"<random_string>\":\"Employee\", \"<random_string>\":\"Intern\" } Save the changes. In the init method this properties should be parsed. To start, let's add some imports: from io.jans.scim.ws.rs.scim2 import BaseScimWebService import json Here is how init would look like: def init ( self , configurationAttributes ): self . custom_header = configurationAttributes . get ( \"custom_header\" ) . getValue2 () access_map_json = configurationAttributes . get ( \"access_map\" ) . getValue2 () self . access_map = json . loads ( access_map_json ) print \"ScimEventHandler (init): Initialized successfully\" return True Note no validations took place here: we assumed the script contains the properties, that they are non empty and have sensible values. Allow/Deny resource operations The first step is to know the kind of application that is calling our service. For this purpose let's create a method that given incoming request headers returns the matching userType # headers params is an instance of javax . ws . rs . core . MultivaluedMap < String , String > def getUserType ( self , headers ) : secret = headers . getFirst ( self . custom_header ) if secret in self . access_map : return self . access_map [ secret ] else : return None Now let's code manageResourceOperation . We should allow access only under the following conditions: The getUserType method does not return None The entity object ( ScimCustomPerson instance) has a proper userType value. This means that for user creation, the incoming payload comes with a matching userType and for the other cases, the already stored attribute matches as well Assume that if the operation invoked is not user-related, we should allow access freely. Here is how the implementation might look: def manageResourceOperation ( self , context , entity , payload , configurationAttributes ): print \"manageResourceOperation. SCIM endpoint invoked is %s (HTTP %s )\" % ( context . getPath (), context . getMethod ()) if context . getResourceType () != \"User\" : return None expected_user_type = self . getUserType ( context . getRequestHeaders ()) if expected_user_type != None and entity . getAttribute ( \"jansUsrTyp\" ) == expected_user_type : return None else : return BaseScimWebService . getErrorResponse ( 403 , None , \"Attempt to handle a not allowed user type\" ) Note no usage of the payload took place. A case you may like to evaluate is where mistakenly using an update operation, the userType is set to an unexpected value. Allow/Deny searches This time instead of inspecting an entity, we ought to make a filter expression to restrict the search when the database is queried. For your reference, a valid filter expression is for instance userType eq \"Contractor\" . def manageSearchOperation ( self , context , searchRequest , configurationAttributes ) : print \"manageSearchOperation. SCIM endpoint invoked is %s (HTTP %s)\" % ( context . getPath () , context . getMethod ()) resource_type = context . getResourceType () print \"manageSearchOperation. This is a search over %s resources\" % resource_type if resource_type != \"User\" : return None expected_user_type = self . getUserType ( context . getRequestHeaders ()) if expected_user_type != None : context . setFilterPrepend ( \"userType eq \\\" % s \\ \"\" % expected_user_type ) return None else : return BaseScimWebService . getErrorResponse ( 403 , None , \"Attempt to handle a not allowed user type\" ) The manageSearchOperation must return a javax.ws.rs.core.Response . A None value makes continue the operation processing normally.", "title": "Controlling execution of SCIM operations"}, {"location": "script-catalog/scim/scim/#working-with-more-than-one-script", "text": "You may have already noticed that it is possible to have several scripts under the SCIM type. This is how execution takes place when there are several scripts enabled: The applicable method is called in the first script. If the return value was True , the method is called again but this time in the subsequent script. If at any point a False return value is encountered, the SCIM operation is aborted with error 500. This means that a normal operation execution requires all involved methods across different scripts to be successful. There is an important exception to the above and is related to the manage* methods. In this case, only one script takes effect (the first script found). Note that in most cases having a single SCIM script suffices for all needs.", "title": "Working with more than one script"}, {"location": "script-catalog/scim/scim/#common-use-cases", "text": "", "title": "Common Use Cases"}, {"location": "script-catalog/scim/scim/#script-type-python", "text": "", "title": "Script Type: Python"}, {"location": "script-catalog/scim/scim/#custom-scim-event-handler", "text": "Find the script here The sample code snippet shows how to - 1. Modify Search Results 2. Segment the user base 3. Allow/Deny resource operations 4. Allow/Deny searches", "title": "Custom SCIM Event Handler"}, {"location": "script-catalog/scim/scim/#script-type-java", "text": "", "title": "Script Type: Java"}, {"location": "script-catalog/scim/scim/#custom-scim-event-handler_1", "text": "Find the code here The sample code snippet shows how to - 1. Modify Search Results 2. Segment the user base 3. Allow/Deny resource operations 4. Allow/Deny searches", "title": "Custom SCIM Event Handler"}, {"location": "script-catalog/select_account/select-account/", "tags": ["administration", "developer", "script-catalog", "SelectAccount"], "text": "Overview # A person may have several accounts on a single Jans Auth Server instance. For example, it is common to have several Gmail accounts. Jans Auth Server uses two cookies to track which accounts are associated with a browser: session_id and current_sessions . Please check Multiple Sessions In One Browser Overview Select Account interception script can be used to customize account selection behavior. E.g. redirect to external page or change text representation of sessions on page. Interface # The select account script implements the SelectAccountType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def getSelectAccountPage(self, context) This method is called to return path to custom select account page (e.g. /customs/page/path/myselectaccount.xhtml) def prepare(self, context) This method is called before select account page is loaded. It can be used to prevent loading or redirect to external url. def getAccountDisplayName(self, context) This method is used to customize text representation of the session shown on the page. Returns display name for given session id (https://github.com/JanssenProject/jans/blob/main/jans-auth-server/common/src/main/java/io/jans/as/common/model/session/SessionId.java). def onSelect(self, context) This method is called on session selection and can be used to forbid selection. Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Execution Context Reference Use case: Dummy Select Account example script (does not have impact on built-in account selection) # Select Account script example . Script Type: Python # # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2020, Janssen # # Author: Yuriy Z # from io.jans.model.custom.script.type.selectaccount import SelectAccountType from java.lang import String class SelectAccount ( SelectAccountType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"SelectAccount script. Initializing ...\" print \"SelectAccount script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"SelectAccount script. Destroying ...\" print \"SelectAccount script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns path to select account page (e.g. /customs/page/path/myselectaccount.xhtml) # If none or empty string is returned, AS uses built-in page. # (Note: Custom page can be also put into `custom/pages/selectAccount.xhtml` and used without custom script.) # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def getSelectAccountPage ( self , context ): return \"\" # This method is called before select account page is loaded. # It is good place to make preparation processing. # E.g. check whether it is ok to land on select account page or maybe redirect to external page. # Return True - continue loading of the page # Return False - stop loading and show error page # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def prepare ( self , context ): return True # Returns display name for given session id (https://github.com/JanssenProject/jans/blob/main/jans-auth-server/common/src/main/java/io/jans/as/common/model/session/SessionId.java). # Session can be accessed via context.getSessionId() # Typical use is: context.getSessionId().getUser().getAttribute(\"myDisplayName\") # Returns string. If blank string is returned, AS will return built-in implementation to return display name # which is context.getSessionId().getUser().getAttribute(\"displayName\") # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def getAccountDisplayName ( self , context ): return \"\" # This method is called on session selection. # Selected session can be accessed as context.getSessionId() # Return True - continue session selection # Return False - stop session selection (forbid it) # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def onSelect ( self , context ): return True Script Type: Java # import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import java.util.Map ; /** * @author Yuriy Z */ public class DummySelectAccountType implements SelectAccountType { @Override public String getSelectAccountPage ( Object context ) { return \"\" ; } @Override public boolean prepare ( Object context ) { return true ; } @Override public String getAccountDisplayName ( Object context ) { return \"\" ; } @Override public boolean onSelect ( Object context ) { return false ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public int getApiVersion () { return 1 ; } }", "title": "Select Account"}, {"location": "script-catalog/select_account/select-account/#overview", "text": "A person may have several accounts on a single Jans Auth Server instance. For example, it is common to have several Gmail accounts. Jans Auth Server uses two cookies to track which accounts are associated with a browser: session_id and current_sessions . Please check Multiple Sessions In One Browser Overview Select Account interception script can be used to customize account selection behavior. E.g. redirect to external page or change text representation of sessions on page.", "title": "Overview"}, {"location": "script-catalog/select_account/select-account/#interface", "text": "The select account script implements the SelectAccountType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/select_account/select-account/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/select_account/select-account/#new-methods", "text": "Method header Method description def getSelectAccountPage(self, context) This method is called to return path to custom select account page (e.g. /customs/page/path/myselectaccount.xhtml) def prepare(self, context) This method is called before select account page is loaded. It can be used to prevent loading or redirect to external url. def getAccountDisplayName(self, context) This method is used to customize text representation of the session shown on the page. Returns display name for given session id (https://github.com/JanssenProject/jans/blob/main/jans-auth-server/common/src/main/java/io/jans/as/common/model/session/SessionId.java). def onSelect(self, context) This method is called on session selection and can be used to forbid selection.", "title": "New Methods"}, {"location": "script-catalog/select_account/select-account/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Execution Context Reference", "title": "Objects"}, {"location": "script-catalog/select_account/select-account/#use-case-dummy-select-account-example-script-does-not-have-impact-on-built-in-account-selection", "text": "Select Account script example .", "title": "Use case: Dummy Select Account example script (does not have impact on built-in account selection)"}, {"location": "script-catalog/select_account/select-account/#script-type-python", "text": "# oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2020, Janssen # # Author: Yuriy Z # from io.jans.model.custom.script.type.selectaccount import SelectAccountType from java.lang import String class SelectAccount ( SelectAccountType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"SelectAccount script. Initializing ...\" print \"SelectAccount script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"SelectAccount script. Destroying ...\" print \"SelectAccount script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns path to select account page (e.g. /customs/page/path/myselectaccount.xhtml) # If none or empty string is returned, AS uses built-in page. # (Note: Custom page can be also put into `custom/pages/selectAccount.xhtml` and used without custom script.) # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def getSelectAccountPage ( self , context ): return \"\" # This method is called before select account page is loaded. # It is good place to make preparation processing. # E.g. check whether it is ok to land on select account page or maybe redirect to external page. # Return True - continue loading of the page # Return False - stop loading and show error page # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def prepare ( self , context ): return True # Returns display name for given session id (https://github.com/JanssenProject/jans/blob/main/jans-auth-server/common/src/main/java/io/jans/as/common/model/session/SessionId.java). # Session can be accessed via context.getSessionId() # Typical use is: context.getSessionId().getUser().getAttribute(\"myDisplayName\") # Returns string. If blank string is returned, AS will return built-in implementation to return display name # which is context.getSessionId().getUser().getAttribute(\"displayName\") # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def getAccountDisplayName ( self , context ): return \"\" # This method is called on session selection. # Selected session can be accessed as context.getSessionId() # Return True - continue session selection # Return False - stop session selection (forbid it) # context is reference of io.jans.as.server.model.common.ExecutionContext( https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java ) def onSelect ( self , context ): return True", "title": "Script Type: Python"}, {"location": "script-catalog/select_account/select-account/#script-type-java", "text": "import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import java.util.Map ; /** * @author Yuriy Z */ public class DummySelectAccountType implements SelectAccountType { @Override public String getSelectAccountPage ( Object context ) { return \"\" ; } @Override public boolean prepare ( Object context ) { return true ; } @Override public String getAccountDisplayName ( Object context ) { return \"\" ; } @Override public boolean onSelect ( Object context ) { return false ; } @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { return true ; } @Override public int getApiVersion () { return 1 ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/", "tags": ["administration", "developer", "script-catalog"], "text": "Interface # The Spontaneous scope script implements the SpontaneousScopeType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def manipulateScopes(self, context) This method is called before spontaneous scope is persisted. It's possible to disable persistence via context.setAllowSpontaneousScopePersistence(false) Also it's possible to manipulated already granted scopes, e.g. context.getGrantedScopes().remove(\"transaction:456\") Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference Script Type: Python # # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2020, Janssen # # Author: Yuriy Z # from io.jans.model.custom.script.type.spontaneous import SpontaneousScopeType from java.lang import String class SpontaneousScope ( SpontaneousScopeType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Spontaneous scope script. Initializing ...\" print \"Spontaneous scope script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Spontaneous scope script. Destroying ...\" print \"Spontaneous scope script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # This method is called before spontaneous scope is persisted. It's possible to disable persistence via context.setAllowSpontaneousScopePersistence(false) # Also it's possible to manipulated already granted scopes, e.g. context.getGrantedScopes().remove(\"transaction:456\") # Note : # context is reference of io.jans.as.service.external.context.SpontaneousScopeExternalContext(in https://github.com/JanssenFederation/oxauth project, ) def manipulateScopes ( self , context ): return This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Spontaneous Scope"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#interface", "text": "The Spontaneous scope script implements the SpontaneousScopeType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#new-methods", "text": "Method header Method description def manipulateScopes(self, context) This method is called before spontaneous scope is persisted. It's possible to disable persistence via context.setAllowSpontaneousScopePersistence(false) Also it's possible to manipulated already granted scopes, e.g. context.getGrantedScopes().remove(\"transaction:456\")", "title": "New Methods"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference", "title": "Objects"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#script-type-python", "text": "# oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2020, Janssen # # Author: Yuriy Z # from io.jans.model.custom.script.type.spontaneous import SpontaneousScopeType from java.lang import String class SpontaneousScope ( SpontaneousScopeType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Spontaneous scope script. Initializing ...\" print \"Spontaneous scope script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Spontaneous scope script. Destroying ...\" print \"Spontaneous scope script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # This method is called before spontaneous scope is persisted. It's possible to disable persistence via context.setAllowSpontaneousScopePersistence(false) # Also it's possible to manipulated already granted scopes, e.g. context.getGrantedScopes().remove(\"transaction:456\") # Note : # context is reference of io.jans.as.service.external.context.SpontaneousScopeExternalContext(in https://github.com/JanssenFederation/oxauth project, ) def manipulateScopes ( self , context ): return", "title": "Script Type: Python"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/spontaneous_scope/spontaneous-scope/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/", "tags": ["administration", "developer", "script-catalog"], "text": "Interface # The UmaClaimsGathering script implements the UmaClaimsGatheringType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def gather(self, step, context): Main gather method. Must return True (if gathering performed successfully) or False (if fail). Method must set claim into context (via context.putClaim('name', value)) in order to persist it (otherwise it will be lost). All user entered values can be access via Map context.getPageClaims() def prepareForStep(self, step, context) ... def getNextStep(self, step, context) ... def getPageForStep(self, step, context) ... Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference Script Type: Python # from io.jans.model.custom.script.type.uma import UmaClaimsGatheringType class UmaClaimsGathering ( UmaClaimsGatheringType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Claims-Gathering. Initializing ...\" print \"Claims-Gathering. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Claims-Gathering. Destroying ...\" print \"Claims-Gathering. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Main gather method. Must return True (if gathering performed successfully) or False (if fail). # Method must set claim into context (via context.putClaim('name', value)) in order to persist it (otherwise it will be lost). # All user entered values can be access via Map<String, String> context.getPageClaims() def gather ( self , step , context ): # context is reference of io.jans.as.uma.authorization.UmaGatherContext print \"Claims-Gathering. Gathering ...\" if step == 1 : if ( context . getPageClaims () . containsKey ( \"country\" )): country = context . getPageClaims () . get ( \"country\" ) print \"Country: \" + country context . putClaim ( \"country\" , country ) return True print \"Claims-Gathering. 'country' is not provided on step 1.\" return False elif step == 2 : if ( context . getPageClaims () . containsKey ( \"city\" )): city = context . getPageClaims () . get ( \"city\" ) print \"City: \" + city context . putClaim ( \"city\" , city ) print \"Claims-Gathering. 'city' is not provided on step 2.\" return True return False def getNextStep ( self , step , context ): return - 1 def prepareForStep ( self , step , context ): if step == 10 and not context . isAuthenticated (): # user is not authenticated, so we are redirecting user to authorization endpoint # client_id is specified via configuration attribute. # Make sure that given client has redirect_uri to Claims-Gathering Endpoint with parameter authentication=true # Sample https://sample.com/restv1/uma/gather_claims?authentication=true # If redirect to external url is performated, make sure that viewAction has onPostback=\"true\" (otherwise redirect will not work) # After user is authenticated then within the script it's possible to get user attributes as # context.getUser(\"uid\", \"sn\") # If user is authenticated to current AS (to the same server, not external one) then it's possible to # access Connect session attributes directly (no need to obtain id_token after redirect with 'code'). # To fetch attributes please use getConnectSessionAttributes() method. print \"User is not authenticated. Redirect for authentication ...\" clientId = context . getConfigurationAttributes () . get ( \"client_id\" ) . getValue2 () redirectUri = context . getClaimsGatheringEndpoint () + \"?authentication=true\" # without authentication=true parameter it will not work authorizationUrl = context . getAuthorizationEndpoint () + \"?client_id=\" + clientId + \"&redirect_uri=\" + redirectUri + \"&scope=openid&response_type=code\" context . redirectToExternalUrl ( authorizationUrl ) # redirect to external url return False if step == 10 and context . isAuthenticated (): # example how to get session attribute if user is authenticated to same AS arc = context . getConnectSessionAttributes () . get ( \"acr\" ) return True def getStepsCount ( self , context ): return 2 def getPageForStep ( self , step , context ): if step == 1 : return \"/uma2/sample/country.xhtml\" elif step == 2 : return \"/uma2/sample/city.xhtml\" return \"\" This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "UMA Claims Gathering (Web Flow)"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#interface", "text": "The UmaClaimsGathering script implements the UmaClaimsGatheringType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#new-methods", "text": "Method header Method description def gather(self, step, context): Main gather method. Must return True (if gathering performed successfully) or False (if fail). Method must set claim into context (via context.putClaim('name', value)) in order to persist it (otherwise it will be lost). All user entered values can be access via Map context.getPageClaims() def prepareForStep(self, step, context) ... def getNextStep(self, step, context) ... def getPageForStep(self, step, context) ...", "title": "New Methods"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference", "title": "Objects"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#script-type-python", "text": "from io.jans.model.custom.script.type.uma import UmaClaimsGatheringType class UmaClaimsGathering ( UmaClaimsGatheringType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"Claims-Gathering. Initializing ...\" print \"Claims-Gathering. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"Claims-Gathering. Destroying ...\" print \"Claims-Gathering. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Main gather method. Must return True (if gathering performed successfully) or False (if fail). # Method must set claim into context (via context.putClaim('name', value)) in order to persist it (otherwise it will be lost). # All user entered values can be access via Map<String, String> context.getPageClaims() def gather ( self , step , context ): # context is reference of io.jans.as.uma.authorization.UmaGatherContext print \"Claims-Gathering. Gathering ...\" if step == 1 : if ( context . getPageClaims () . containsKey ( \"country\" )): country = context . getPageClaims () . get ( \"country\" ) print \"Country: \" + country context . putClaim ( \"country\" , country ) return True print \"Claims-Gathering. 'country' is not provided on step 1.\" return False elif step == 2 : if ( context . getPageClaims () . containsKey ( \"city\" )): city = context . getPageClaims () . get ( \"city\" ) print \"City: \" + city context . putClaim ( \"city\" , city ) print \"Claims-Gathering. 'city' is not provided on step 2.\" return True return False def getNextStep ( self , step , context ): return - 1 def prepareForStep ( self , step , context ): if step == 10 and not context . isAuthenticated (): # user is not authenticated, so we are redirecting user to authorization endpoint # client_id is specified via configuration attribute. # Make sure that given client has redirect_uri to Claims-Gathering Endpoint with parameter authentication=true # Sample https://sample.com/restv1/uma/gather_claims?authentication=true # If redirect to external url is performated, make sure that viewAction has onPostback=\"true\" (otherwise redirect will not work) # After user is authenticated then within the script it's possible to get user attributes as # context.getUser(\"uid\", \"sn\") # If user is authenticated to current AS (to the same server, not external one) then it's possible to # access Connect session attributes directly (no need to obtain id_token after redirect with 'code'). # To fetch attributes please use getConnectSessionAttributes() method. print \"User is not authenticated. Redirect for authentication ...\" clientId = context . getConfigurationAttributes () . get ( \"client_id\" ) . getValue2 () redirectUri = context . getClaimsGatheringEndpoint () + \"?authentication=true\" # without authentication=true parameter it will not work authorizationUrl = context . getAuthorizationEndpoint () + \"?client_id=\" + clientId + \"&redirect_uri=\" + redirectUri + \"&scope=openid&response_type=code\" context . redirectToExternalUrl ( authorizationUrl ) # redirect to external url return False if step == 10 and context . isAuthenticated (): # example how to get session attribute if user is authenticated to same AS arc = context . getConnectSessionAttributes () . get ( \"acr\" ) return True def getStepsCount ( self , context ): return 2 def getPageForStep ( self , step , context ): if step == 1 : return \"/uma2/sample/country.xhtml\" elif step == 2 : return \"/uma2/sample/city.xhtml\" return \"\"", "title": "Script Type: Python"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/uma_claims_gathering/uma-claims-web/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/", "tags": ["administration", "developer", "script-catalog"], "text": "Interface # The UmaRptClaims script implements the UmaRptClaimsType interface. This extends methods from the base script type in addition to adding new methods: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def modify(self, rptAsJsonObject, context) responseAsJsonObject - is org.codehaus.jettison.json.JSONObject , you can use any method to manipulate json. context is reference of io.jans.as.service.external.context.ExternalUmaRptClaimsContext (in https://github.com/JanssenFederation/oxauth project, ) Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference Script Type: Python # from io.jans.model.custom.script.type.uma import UmaRptClaimsType from java.lang import String class UmaRptClaims ( UmaRptClaimsType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"RPT Claims script. Initializing ...\" print \"RPT Claims script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"RPT Claims script. Destroying ...\" print \"RPT Claims script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply changes from script method, false - ignore it. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.service.external.context.ExternalUmaRptClaimsContext (in https://github.com/JanssenFederation/oxauth project, ) def modify ( self , rptAsJsonObject , context ): rptAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True This content is in progress # The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. Have questions in the meantime? # While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover. Want to contribute? # If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "UMA Claims (JWT Transformation)"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#interface", "text": "The UmaRptClaims script implements the UmaRptClaimsType interface. This extends methods from the base script type in addition to adding new methods:", "title": "Interface"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#new-methods", "text": "Method header Method description def modify(self, rptAsJsonObject, context) responseAsJsonObject - is org.codehaus.jettison.json.JSONObject , you can use any method to manipulate json. context is reference of io.jans.as.service.external.context.ExternalUmaRptClaimsContext (in https://github.com/JanssenFederation/oxauth project, )", "title": "New Methods"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes context Execution Context Reference", "title": "Objects"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#script-type-python", "text": "from io.jans.model.custom.script.type.uma import UmaRptClaimsType from java.lang import String class UmaRptClaims ( UmaRptClaimsType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , customScript , configurationAttributes ): print \"RPT Claims script. Initializing ...\" print \"RPT Claims script. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"RPT Claims script. Destroying ...\" print \"RPT Claims script. Destroyed successfully\" return True def getApiVersion ( self ): return 11 # Returns boolean, true - apply changes from script method, false - ignore it. # Note : # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json # context is reference of io.jans.as.service.external.context.ExternalUmaRptClaimsContext (in https://github.com/JanssenFederation/oxauth project, ) def modify ( self , rptAsJsonObject , context ): rptAsJsonObject . accumulate ( \"key_from_script\" , \"value_from_script\" ) return True", "title": "Script Type: Python"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#this-content-is-in-progress", "text": "The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future.", "title": "This content is in progress"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#have-questions-in-the-meantime", "text": "While this documentation is in progress, you can ask questions through GitHub Discussions or the community chat on Gitter . Any questions you have will help determine what information our documentation should cover.", "title": "Have questions in the meantime?"}, {"location": "script-catalog/uma_rpt_claims/uma-claims-jwt/#want-to-contribute", "text": "If you have content you'd like to contribute to this page in the meantime, you can get started with our Contribution guide .", "title": "Want to contribute?"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/", "tags": ["administration", "developer", "script-catalog", "UmaRptPolicy"], "text": "Overview # This is a special script for UMA. It allows an admin to protect UMA scopes with policies. It is possible to add more than one UMA policy to an UMA scope. On requesting access to a specified resource, the application should call specified UMA policies in order to grant or deny access. Interface # The UMA RPT Authorization Policy script implements the UmaRptPolicyType interface. This extends methods from the base script type in addition to adding new method: Inherited Methods # Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 New Methods # Method header Method description def getRequiredClaims(self, authorizationContext) Returns required claims definitions. This method must provide definition of all claims that is used in 'authorize' method. Return empty array [] if no claims should be gathered. Note : name in both places must match. %1$s - placeholder for issuer. It uses standard Java Formatter, docs : https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html def authorize(self, authorizationContext) Main authorization method. Must return True or False. def getClaimsGatheringScriptName(self, authorizationContext) Returns name of the Claims-Gathering script which will be invoked if need_info error is returned. Return blank/empty string if claims gathering flow is not involved. Objects # Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference ClaimDefinition Reference Use case: Request Country and City Policies # This script was adapted from the Gluu Server UMA RPT Authorization Script . Script Type: Python # from io.jans.model.custom.script.type.uma import UmaRptPolicyType from io.jans.model.uma import ClaimDefinitionBuilder from java.lang import String class UmaRptPolicy ( UmaRptPolicyType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"RPT Policy. Initializing ...\" print \"RPT Policy. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"RPT Policy. Destroying ...\" print \"RPT Policy. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Returns required claims definitions. # This method must provide definition of all claims that is used in 'authorize' method. # Return empty array `[]` if no claims should be gathered. # Note : name in both places must match. # %1$s - placeholder for issuer. It uses standard Java Formatter, docs : https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html def getRequiredClaims ( self , context ): json = \"\"\"[ { \"issuer\" : [ \"%1$s\" ], \"name\" : \"country\", \"claim_token_format\" : [ \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], \"claim_type\" : \"string\", \"friendly_name\" : \"country\" }, { \"issuer\" : [ \"%1$s\" ], \"name\" : \"city\", \"claim_token_format\" : [ \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], \"claim_type\" : \"string\", \"friendly_name\" : \"city\" } ]\"\"\" context . addRedirectUserParam ( \"customUserParam1\" , \"value1\" ) # pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. return ClaimDefinitionBuilder . build ( String . format ( json , context . getIssuer ())) # Main authorization method. Must return True or False. def authorize ( self , context ): print \"RPT Policy. Authorizing ...\" if context . getClaim ( \"country\" ) == 'US' and context . getClaim ( \"city\" ) == 'NY' : print \"Authorized successfully!\" return True return False # Returns name of the Claims-Gathering script which will be invoked if need_info error is returned. Return blank/empty string if claims gathering flow is not involved. def getClaimsGatheringScriptName ( self , context ): context . addRedirectUserParam ( \"customUserParam2\" , \"value2\" ) # pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. return \"sampleClaimsGathering\" Script Type: Java # import java.util.List ; import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.uma.UmaRptPolicyType ; import io.jans.model.uma.ClaimDefinition ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.uma.authorization.UmaAuthorizationContext ; import io.jans.model.uma.ClaimDefinitionBuilder ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class UmaRptPolicy implements UmaRptPolicyType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Initializing...\" ); log . info ( \"UMA RPT Policy Authorization. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Initializing...\" ); log . info ( \"UMA RPT Policy Authorization. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Destroying...\" ); log . info ( \"UMA RPT Policy Authorization. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public List < ClaimDefinition > getRequiredClaims ( Object authorizationContext ) { /* needs to be a valid JSON string * Sample: [ { \"issuer\" : [ \"https://example.com\" ], \"name\" : * \"country\", \"claim_token_format\" : [ * \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], * \"claim_type\" : \"string\", \"friendly_name\" : \"country\" } ] * */ String json = \"\" ; UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; authContext . addRedirectUserParam ( \"customUserParam1\" , \"value1\" ); return ClaimDefinitionBuilder . build ( String . format ( json , authContext . getIssuer ())); } @Override public boolean authorize ( Object authorizationContext ) { log . info ( \"UMA RPT Policy Authorization. Authorizing...\" ); UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; if ( authContext . getClaim ( \"country\" ). equals ( \"US\" ) && authContext . getClaim ( \"city\" ). equals ( \"NY\" )) { log . info ( \"Authorized successfully!\" ); return true ; } return false ; } @Override public String getClaimsGatheringScriptName ( Object authorizationContext ) { UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; // pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. authContext . addRedirectUserParam ( \"customUserParam2\" , \"value2\" ); return \"sampleClaimsGathering\" ; } }", "title": "UMA RPT Policies"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#overview", "text": "This is a special script for UMA. It allows an admin to protect UMA scopes with policies. It is possible to add more than one UMA policy to an UMA scope. On requesting access to a specified resource, the application should call specified UMA policies in order to grant or deny access.", "title": "Overview"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#interface", "text": "The UMA RPT Authorization Policy script implements the UmaRptPolicyType interface. This extends methods from the base script type in addition to adding new method:", "title": "Interface"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#inherited-methods", "text": "Method header Method description def init(self, customScript, configurationAttributes) This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc def destroy(self, configurationAttributes) This method is called once to destroy events. It can be used to free resource and objects created in the init() method def getApiVersion(self, configurationAttributes, customScript) The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10", "title": "Inherited Methods"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#new-methods", "text": "Method header Method description def getRequiredClaims(self, authorizationContext) Returns required claims definitions. This method must provide definition of all claims that is used in 'authorize' method. Return empty array [] if no claims should be gathered. Note : name in both places must match. %1$s - placeholder for issuer. It uses standard Java Formatter, docs : https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html def authorize(self, authorizationContext) Main authorization method. Must return True or False. def getClaimsGatheringScriptName(self, authorizationContext) Returns name of the Claims-Gathering script which will be invoked if need_info error is returned. Return blank/empty string if claims gathering flow is not involved.", "title": "New Methods"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#objects", "text": "Object name Object description customScript The custom script object. Reference configurationAttributes configurationProperties passed in when adding custom script. Map<String, SimpleCustomProperty> configurationAttributes SimpleCustomProperty Map of configuration properties. Reference context Reference ClaimDefinition Reference", "title": "Objects"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#use-case-request-country-and-city-policies", "text": "This script was adapted from the Gluu Server UMA RPT Authorization Script .", "title": "Use case: Request Country and City Policies"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#script-type-python", "text": "from io.jans.model.custom.script.type.uma import UmaRptPolicyType from io.jans.model.uma import ClaimDefinitionBuilder from java.lang import String class UmaRptPolicy ( UmaRptPolicyType ): def __init__ ( self , currentTimeMillis ): self . currentTimeMillis = currentTimeMillis def init ( self , configurationAttributes ): print \"RPT Policy. Initializing ...\" print \"RPT Policy. Initialized successfully\" return True def destroy ( self , configurationAttributes ): print \"RPT Policy. Destroying ...\" print \"RPT Policy. Destroyed successfully\" return True def getApiVersion ( self ): return 1 # Returns required claims definitions. # This method must provide definition of all claims that is used in 'authorize' method. # Return empty array `[]` if no claims should be gathered. # Note : name in both places must match. # %1$s - placeholder for issuer. It uses standard Java Formatter, docs : https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html def getRequiredClaims ( self , context ): json = \"\"\"[ { \"issuer\" : [ \"%1$s\" ], \"name\" : \"country\", \"claim_token_format\" : [ \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], \"claim_type\" : \"string\", \"friendly_name\" : \"country\" }, { \"issuer\" : [ \"%1$s\" ], \"name\" : \"city\", \"claim_token_format\" : [ \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], \"claim_type\" : \"string\", \"friendly_name\" : \"city\" } ]\"\"\" context . addRedirectUserParam ( \"customUserParam1\" , \"value1\" ) # pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. return ClaimDefinitionBuilder . build ( String . format ( json , context . getIssuer ())) # Main authorization method. Must return True or False. def authorize ( self , context ): print \"RPT Policy. Authorizing ...\" if context . getClaim ( \"country\" ) == 'US' and context . getClaim ( \"city\" ) == 'NY' : print \"Authorized successfully!\" return True return False # Returns name of the Claims-Gathering script which will be invoked if need_info error is returned. Return blank/empty string if claims gathering flow is not involved. def getClaimsGatheringScriptName ( self , context ): context . addRedirectUserParam ( \"customUserParam2\" , \"value2\" ) # pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. return \"sampleClaimsGathering\"", "title": "Script Type: Python"}, {"location": "script-catalog/uma_rpt_policy/uma-rpt/#script-type-java", "text": "import java.util.List ; import java.util.Map ; import io.jans.model.SimpleCustomProperty ; import io.jans.model.custom.script.model.CustomScript ; import io.jans.model.custom.script.type.uma.UmaRptPolicyType ; import io.jans.model.uma.ClaimDefinition ; import io.jans.service.custom.script.CustomScriptManager ; import io.jans.as.server.uma.authorization.UmaAuthorizationContext ; import io.jans.model.uma.ClaimDefinitionBuilder ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class UmaRptPolicy implements UmaRptPolicyType { private static final Logger log = LoggerFactory . getLogger ( CustomScriptManager . class ); @Override public boolean init ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Initializing...\" ); log . info ( \"UMA RPT Policy Authorization. Initialized\" ); return true ; } @Override public boolean init ( CustomScript customScript , Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Initializing...\" ); log . info ( \"UMA RPT Policy Authorization. Initialized\" ); return true ; } @Override public boolean destroy ( Map < String , SimpleCustomProperty > configurationAttributes ) { log . info ( \"UMA RPT Policy Authorization. Destroying...\" ); log . info ( \"UMA RPT Policy Authorization. Destroyed.\" ); return true ; } @Override public int getApiVersion () { return 11 ; } @Override public List < ClaimDefinition > getRequiredClaims ( Object authorizationContext ) { /* needs to be a valid JSON string * Sample: [ { \"issuer\" : [ \"https://example.com\" ], \"name\" : * \"country\", \"claim_token_format\" : [ * \"http://openid.net/specs/openid-connect-core-1_0.html#IDToken\" ], * \"claim_type\" : \"string\", \"friendly_name\" : \"country\" } ] * */ String json = \"\" ; UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; authContext . addRedirectUserParam ( \"customUserParam1\" , \"value1\" ); return ClaimDefinitionBuilder . build ( String . format ( json , authContext . getIssuer ())); } @Override public boolean authorize ( Object authorizationContext ) { log . info ( \"UMA RPT Policy Authorization. Authorizing...\" ); UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; if ( authContext . getClaim ( \"country\" ). equals ( \"US\" ) && authContext . getClaim ( \"city\" ). equals ( \"NY\" )) { log . info ( \"Authorized successfully!\" ); return true ; } return false ; } @Override public String getClaimsGatheringScriptName ( Object authorizationContext ) { UmaAuthorizationContext authContext = ( UmaAuthorizationContext ) authorizationContext ; // pass some custom parameters to need_info uri. It can be removed if you don't need custom parameters. authContext . addRedirectUserParam ( \"customUserParam2\" , \"value2\" ); return \"sampleClaimsGathering\" ; } }", "title": "Script Type: Java"}, {"location": "script-catalog/update_token/update-token/", "tags": ["administration", "developer", "script-catalog"], "text": "Overview # By overriding the interface methods in UpdateTokenType inside a custom script you can Enable transformation of claims and values in id_token and Access token e.g. add a custom claim to an id_token , change a token expiry, change the sub value, or remove the nonce . Example use-case: * As per the open banking standard, the id_token should contain claim openbanking_intent_id and the same value should also reflect in the sub claim. * As specified in the FAPI Baseline Specification the sub claim should have the user id. Set a specific token lifetime Perform extra business logic like adding or removing scopes. Add an extra audit log for each token response. Flow # sequenceDiagram title UpdateToken script autonumber 1 RP->>Jans AS: Request token Jans AS->>Jans AS: Is UpdateToken script is associated with client? <br/>(or is there a script that applies to all clients? ) Jans AS->>Jans AS: do stuff note right of Jans AS: do stuff<br/>1. Enable transformation of claims and values in id_token <br/> OR 2. set token expiry <br/> or 3. add / remove scopes. <br/> or 4. perform audit logs Jans AS->>RP: return token(s) (Access token, ID token or Refresh Token) reflecting step 3 Adding the custom script to Jans server # Create cs.json with the contents of a CUSTOM script. To do that, run the following command. /opt/jans/jans-cli/config-cli.py --schema CustomScript > /tmp/cs.json Edit the file's contents to reflect the addition of the UpdateToken custom script. Set enabled flag true Configure any parameters that the script may use. name field should reflect the use case script_type should be UPDATE_TOKEN script.py can have contents similar to Sample Script ) and is present in jans-cli's host machine. { \"dn\": null, \"inum\": null, \"name\": \"update_token\", \"aliases\": [], \"description\": \"Update token custom script\", \"script\": \"_file /root/script.py\", \"scriptType\": \"UPDATE_TOKEN\", \"programmingLanguage\": \"JYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": [ { \"value1\": \"param_name\", \"value2\": \"DI3ICTTJKLL8PPPNGH7YI\", \"description\": \"This is just an example\", \"hide\": true }, { \"value1\": \"param_name_2\", \"value2\": \"eEbJdi3hg42zxyFYbHArU5RuioPP\", \"description\": \"yet another example\", \"hide\": true } ] , \"level\": \"integer\", \"revision\": 0, \"enabled\": true, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } Add the custom script. Save the response, it will contain the inum of the newly added script. /opt/jans/jans-cli/config-cli.py --operation-id post-config-scripts --data /tmp/cs.json Associate an Update Token script to a client (RP) [optional step] # \ud83d\udcdd Note: If the Update token script is not associated with a client, then it will be applicable to all clients registered in the Jans Server. Which implies that all tokens obtained using the Jans server will reflect modifications as per the script. To Associate an Update Token script to a client (RP), execute the command below with appropriate values for: - inum of the client - inum of the update_token script /opt/jans/jans-cli/config-cli.py --operation-id patch-oauth-openid-clients-by-inum --url-suffix inum:inum_of_client --data '[ { \"op\": \"add\", \"path\": \"updateTokenScriptDns\", \"value\": [\"inum={SCRIPT_ID},ou=scripts,o=jans\"] } ]' Writing an Update token script (Pseudo code for potential usecases) # Mandatory methods # class UpdateToken(UpdateTokenType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): return True def destroy(self, configurationAttributes): return True def getApiVersion(self): return 11 modifyIdToken () : Used to modify claims in an ID token # Pseudocode and example : # Returns boolean, true - indicates that script applied changes # jsonWebResponse - is JwtHeader, you can use any method to manipulate JWT # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyIdToken(self, jsonWebResponse, context): # header claims jsonWebResponse.getHeader().setClaim(\"header_name\", \"header_value\") #custom claims jsonWebResponse.getClaims().setClaim(\"openbanking_intent_id\", openbanking_intent_id_value) #regular claims jsonWebResponse.getClaims().setClaim(\"sub\", claimValue) return True modifyAccessToken() # Granularity of access control # An UpdateTokenType script is great for adding scopes or removing scopes to/from the Access token. By doing so you can tailor build the granularity of access control according to business need. context.overwriteAccessTokenScopes is ready to use method of the context variable def modifyAccessToken(self, accessToken, context): context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"openid\", \"mynewscope\")) Perform business check before returning AT # Pseudocode and example - Issue Access token only if account balance is greater than 0 # Returns boolean, true - indicates that script applied changes # accessToken - is JwtHeader, you can use any method to manipulate JWT # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence org_id = sessionId.getSessionAttributes().get(\"org_id\") balance = thirdPartyApi.checkBalance(org_id) if balance > 0 : return True else: return False # forbid the creation of AT Modify claims in an access token # # Returns boolean, true - indicates that script applied changes. If false is returned token will not be created. # accessToken is reference of io.jans.as.server.model.common.AccessToken (note authorization grant can be taken as context.getGrant()) # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyAccessToken(self, accessToken, context): # header claims context.getHeader().setClaim(\"header_name\", \"header_value\") #custom claims context.getClaims().setClaim(\"claim_name\", \"claimValue\") #regular claims context.getClaims().setClaim(\"sub\", claimValue) return True Modify a specific token lifetime based on the context # Refresh token lifetime: def getRefreshTokenLifetimeInSeconds(self, context): return 24 * 60 * 60 # one day ID token lifetime: def getIdTokenLifetimeInSeconds(self, context): return 10 * 60 * 60 # 10 hours Access token lifetime: def getAccessTokenLifetimeInSeconds(self, context): return 10 * 60 * 60 # 10 hours Access token lifetime from script has highest priority (it wins from client's access token lifetime configuration). modifyRefreshToken() : # Used to modify claims in a Refresh Token # Returns boolean, true - indicates that script applied changes. If false is returned token will not be created. # refreshToken is reference of io.jans.as.server.model.common.RefreshToken (note authorization grant can be taken as context.getGrant()) # context is reference of io.jans.as.server.service.external.context.ExternalUpdateTokenContext (in https://github.com/JanssenProject/jans-auth-server project, ) def modifyRefreshToken(self, refreshToken, context): return True IntrospectionType script vs UpdateTokenType script # IntrospectionType UpdateTokenType Client configuration parameter Introspection script is invoked only when accessTokenAsJwt = true Update token script is invoked irrespective of whether accessTokenAsJwt is true or false Core Purpose Used to return access token meta information like current validity, approved scopes, and information about the context in which the token was issued when a Resource Server which queries the Introspection endpoint used to enable transformation of claims and values in id_token and Access token, set a specific token lifetime, change granularity of access control (up-scoping, down-scoping), audit logging for each token response, forbid the creation of AT based on a criteria. Functionality 1. Can be used to modify claims of an Access token as JWT, however this it is recommended to use UpdateToken script instead. 1. Used to modify id_token, refresh token and access token 2. Introspection script cannot change scope of AT 2. UpdateToken can change scope of AT and modify AT object in persistence irrespective of the value of accessTokenAsJwt as true or false Script Invocation sequence 2. After an Access token is generated 2. Before the creation of AT, id_token and refresh_token Testing # Use this: Reference for testing Inspect the tokens. Use jwt.io to inspect the contents of a JWT. FAQ # How can I add a dict type object as a claim value? from io.jans.as.model.uti import JwtUtil from org.json import JSONObject; def modifyIdToken(self, jsonWebResponse, context): datas = {'country': 'ID', 'sponsor': '7022952467', 'role': 'BusinessOwner', 'salesplanaff': '220', 'acctsubtype': 'BusinessOwner', 'accttype': 'AmBCBusiness', 'abo': '7022953754', 'aboname': 'NEW', 'lclpartyid': '119700175', 'email': None, 'status': 'Active'} string_rep = json.dumps(datas) jsonObject = JwtUtil.fromJson(string_rep) jsonWebResponse.getClaims().setClaim(\"test\", jsonObject) print \"Update token script. Modify idToken: %s\" % jsonWebResponse return True 2. How can I set integer value in id token claim? jsonWebResponse.getClaims().setClaim(\"claimY\", Integer.valueOf(124456191)) Get it as integer, via getClaims().getClaimAsInteger(\"claimY\")", "title": "Update Token"}, {"location": "script-catalog/update_token/update-token/#overview", "text": "By overriding the interface methods in UpdateTokenType inside a custom script you can Enable transformation of claims and values in id_token and Access token e.g. add a custom claim to an id_token , change a token expiry, change the sub value, or remove the nonce . Example use-case: * As per the open banking standard, the id_token should contain claim openbanking_intent_id and the same value should also reflect in the sub claim. * As specified in the FAPI Baseline Specification the sub claim should have the user id. Set a specific token lifetime Perform extra business logic like adding or removing scopes. Add an extra audit log for each token response.", "title": "Overview"}, {"location": "script-catalog/update_token/update-token/#flow", "text": "sequenceDiagram title UpdateToken script autonumber 1 RP->>Jans AS: Request token Jans AS->>Jans AS: Is UpdateToken script is associated with client? <br/>(or is there a script that applies to all clients? ) Jans AS->>Jans AS: do stuff note right of Jans AS: do stuff<br/>1. Enable transformation of claims and values in id_token <br/> OR 2. set token expiry <br/> or 3. add / remove scopes. <br/> or 4. perform audit logs Jans AS->>RP: return token(s) (Access token, ID token or Refresh Token) reflecting step 3", "title": "Flow"}, {"location": "script-catalog/update_token/update-token/#adding-the-custom-script-to-jans-server", "text": "Create cs.json with the contents of a CUSTOM script. To do that, run the following command. /opt/jans/jans-cli/config-cli.py --schema CustomScript > /tmp/cs.json Edit the file's contents to reflect the addition of the UpdateToken custom script. Set enabled flag true Configure any parameters that the script may use. name field should reflect the use case script_type should be UPDATE_TOKEN script.py can have contents similar to Sample Script ) and is present in jans-cli's host machine. { \"dn\": null, \"inum\": null, \"name\": \"update_token\", \"aliases\": [], \"description\": \"Update token custom script\", \"script\": \"_file /root/script.py\", \"scriptType\": \"UPDATE_TOKEN\", \"programmingLanguage\": \"JYTHON\", \"moduleProperties\": { \"value1\": null, \"value2\": null, \"description\": null }, \"configurationProperties\": [ { \"value1\": \"param_name\", \"value2\": \"DI3ICTTJKLL8PPPNGH7YI\", \"description\": \"This is just an example\", \"hide\": true }, { \"value1\": \"param_name_2\", \"value2\": \"eEbJdi3hg42zxyFYbHArU5RuioPP\", \"description\": \"yet another example\", \"hide\": true } ] , \"level\": \"integer\", \"revision\": 0, \"enabled\": true, \"scriptError\": { \"raisedAt\": null, \"stackTrace\": null }, \"modified\": false, \"internal\": false } Add the custom script. Save the response, it will contain the inum of the newly added script. /opt/jans/jans-cli/config-cli.py --operation-id post-config-scripts --data /tmp/cs.json", "title": "Adding the custom script to Jans server"}, {"location": "script-catalog/update_token/update-token/#associate-an-update-token-script-to-a-client-rp-optional-step", "text": "\ud83d\udcdd Note: If the Update token script is not associated with a client, then it will be applicable to all clients registered in the Jans Server. Which implies that all tokens obtained using the Jans server will reflect modifications as per the script. To Associate an Update Token script to a client (RP), execute the command below with appropriate values for: - inum of the client - inum of the update_token script /opt/jans/jans-cli/config-cli.py --operation-id patch-oauth-openid-clients-by-inum --url-suffix inum:inum_of_client --data '[ { \"op\": \"add\", \"path\": \"updateTokenScriptDns\", \"value\": [\"inum={SCRIPT_ID},ou=scripts,o=jans\"] } ]'", "title": "Associate an Update Token script to a client (RP) [optional step]"}, {"location": "script-catalog/update_token/update-token/#writing-an-update-token-script-pseudo-code-for-potential-usecases", "text": "", "title": "Writing an Update token script (Pseudo code for potential usecases)"}, {"location": "script-catalog/update_token/update-token/#mandatory-methods", "text": "class UpdateToken(UpdateTokenType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): return True def destroy(self, configurationAttributes): return True def getApiVersion(self): return 11", "title": "Mandatory methods"}, {"location": "script-catalog/update_token/update-token/#modifyidtoken-used-to-modify-claims-in-an-id-token", "text": "Pseudocode and example : # Returns boolean, true - indicates that script applied changes # jsonWebResponse - is JwtHeader, you can use any method to manipulate JWT # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyIdToken(self, jsonWebResponse, context): # header claims jsonWebResponse.getHeader().setClaim(\"header_name\", \"header_value\") #custom claims jsonWebResponse.getClaims().setClaim(\"openbanking_intent_id\", openbanking_intent_id_value) #regular claims jsonWebResponse.getClaims().setClaim(\"sub\", claimValue) return True", "title": "modifyIdToken () : Used to modify claims in an ID token"}, {"location": "script-catalog/update_token/update-token/#modifyaccesstoken", "text": "", "title": "modifyAccessToken()"}, {"location": "script-catalog/update_token/update-token/#granularity-of-access-control", "text": "An UpdateTokenType script is great for adding scopes or removing scopes to/from the Access token. By doing so you can tailor build the granularity of access control according to business need. context.overwriteAccessTokenScopes is ready to use method of the context variable def modifyAccessToken(self, accessToken, context): context.overwriteAccessTokenScopes(accessToken, Sets.newHashSet(\"openid\", \"mynewscope\"))", "title": "Granularity of access control"}, {"location": "script-catalog/update_token/update-token/#perform-business-check-before-returning-at", "text": "Pseudocode and example - Issue Access token only if account balance is greater than 0 # Returns boolean, true - indicates that script applied changes # accessToken - is JwtHeader, you can use any method to manipulate JWT # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyAccessToken(self, accessToken, context): #read from session sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence org_id = sessionId.getSessionAttributes().get(\"org_id\") balance = thirdPartyApi.checkBalance(org_id) if balance > 0 : return True else: return False # forbid the creation of AT", "title": "Perform business check before returning AT"}, {"location": "script-catalog/update_token/update-token/#modify-claims-in-an-access-token", "text": "# Returns boolean, true - indicates that script applied changes. If false is returned token will not be created. # accessToken is reference of io.jans.as.server.model.common.AccessToken (note authorization grant can be taken as context.getGrant()) # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext def modifyAccessToken(self, accessToken, context): # header claims context.getHeader().setClaim(\"header_name\", \"header_value\") #custom claims context.getClaims().setClaim(\"claim_name\", \"claimValue\") #regular claims context.getClaims().setClaim(\"sub\", claimValue) return True", "title": "Modify claims in an access token"}, {"location": "script-catalog/update_token/update-token/#modify-a-specific-token-lifetime-based-on-the-context", "text": "Refresh token lifetime: def getRefreshTokenLifetimeInSeconds(self, context): return 24 * 60 * 60 # one day ID token lifetime: def getIdTokenLifetimeInSeconds(self, context): return 10 * 60 * 60 # 10 hours Access token lifetime: def getAccessTokenLifetimeInSeconds(self, context): return 10 * 60 * 60 # 10 hours Access token lifetime from script has highest priority (it wins from client's access token lifetime configuration).", "title": "Modify a specific token lifetime based on the context"}, {"location": "script-catalog/update_token/update-token/#modifyrefreshtoken", "text": "Used to modify claims in a Refresh Token # Returns boolean, true - indicates that script applied changes. If false is returned token will not be created. # refreshToken is reference of io.jans.as.server.model.common.RefreshToken (note authorization grant can be taken as context.getGrant()) # context is reference of io.jans.as.server.service.external.context.ExternalUpdateTokenContext (in https://github.com/JanssenProject/jans-auth-server project, ) def modifyRefreshToken(self, refreshToken, context): return True", "title": "modifyRefreshToken() :"}, {"location": "script-catalog/update_token/update-token/#introspectiontype-script-vs-updatetokentype-script", "text": "IntrospectionType UpdateTokenType Client configuration parameter Introspection script is invoked only when accessTokenAsJwt = true Update token script is invoked irrespective of whether accessTokenAsJwt is true or false Core Purpose Used to return access token meta information like current validity, approved scopes, and information about the context in which the token was issued when a Resource Server which queries the Introspection endpoint used to enable transformation of claims and values in id_token and Access token, set a specific token lifetime, change granularity of access control (up-scoping, down-scoping), audit logging for each token response, forbid the creation of AT based on a criteria. Functionality 1. Can be used to modify claims of an Access token as JWT, however this it is recommended to use UpdateToken script instead. 1. Used to modify id_token, refresh token and access token 2. Introspection script cannot change scope of AT 2. UpdateToken can change scope of AT and modify AT object in persistence irrespective of the value of accessTokenAsJwt as true or false Script Invocation sequence 2. After an Access token is generated 2. Before the creation of AT, id_token and refresh_token", "title": "IntrospectionType script vs UpdateTokenType script"}, {"location": "script-catalog/update_token/update-token/#testing", "text": "Use this: Reference for testing Inspect the tokens. Use jwt.io to inspect the contents of a JWT.", "title": "Testing"}, {"location": "script-catalog/update_token/update-token/#faq", "text": "How can I add a dict type object as a claim value? from io.jans.as.model.uti import JwtUtil from org.json import JSONObject; def modifyIdToken(self, jsonWebResponse, context): datas = {'country': 'ID', 'sponsor': '7022952467', 'role': 'BusinessOwner', 'salesplanaff': '220', 'acctsubtype': 'BusinessOwner', 'accttype': 'AmBCBusiness', 'abo': '7022953754', 'aboname': 'NEW', 'lclpartyid': '119700175', 'email': None, 'status': 'Active'} string_rep = json.dumps(datas) jsonObject = JwtUtil.fromJson(string_rep) jsonWebResponse.getClaims().setClaim(\"test\", jsonObject) print \"Update token script. Modify idToken: %s\" % jsonWebResponse return True 2. How can I set integer value in id token claim? jsonWebResponse.getClaims().setClaim(\"claimY\", Integer.valueOf(124456191)) Get it as integer, via getClaims().getClaimAsInteger(\"claimY\")", "title": "FAQ"}]} \ No newline at end of file diff --git a/nightly/sitemap.xml.gz b/nightly/sitemap.xml.gz index b94557c5912..d25e6932d84 100644 Binary files a/nightly/sitemap.xml.gz and b/nightly/sitemap.xml.gz differ